Merge "Fix ScreenDecorWindowTests on devices without nav bar"
diff --git a/Android.bp b/Android.bp
index e669307..3095ca5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -181,6 +181,7 @@
         "core/java/android/hardware/input/IInputManager.aidl",
         "core/java/android/hardware/input/IInputDevicesChangedListener.aidl",
         "core/java/android/hardware/input/ITabletModeChangedListener.aidl",
+        "core/java/android/hardware/iris/IIrisService.aidl",
         "core/java/android/hardware/location/IActivityRecognitionHardware.aidl",
         "core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl",
         "core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl",
@@ -286,6 +287,8 @@
         "core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl",
         "core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl",
         "core/java/android/service/gatekeeper/IGateKeeperService.aidl",
+        "core/java/android/service/intelligence/IIntelligenceService.aidl",
+
         "core/java/android/service/notification/INotificationListener.aidl",
         "core/java/android/service/notification/IStatusBarNotificationHolder.aidl",
         "core/java/android/service/notification/IConditionListener.aidl",
@@ -342,6 +345,7 @@
         "core/java/android/view/autofill/IAutoFillManager.aidl",
         "core/java/android/view/autofill/IAutoFillManagerClient.aidl",
         "core/java/android/view/autofill/IAutofillWindowPresenter.aidl",
+        "core/java/android/view/intelligence/IIntelligenceManager.aidl",
         "core/java/android/view/IApplicationToken.aidl",
         "core/java/android/view/IAppTransitionAnimationSpecsFuture.aidl",
         "core/java/android/view/IDockedStackListener.aidl",
@@ -389,6 +393,9 @@
         "core/java/com/android/internal/backup/IObbBackupService.aidl",
         "core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl",
         "core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl",
+        "core/java/com/android/internal/inputmethod/IMultiClientInputMethod.aidl",
+        "core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl",
+        "core/java/com/android/internal/inputmethod/IMultiClientInputMethodSession.aidl",
         "core/java/com/android/internal/net/INetworkWatchlistManager.aidl",
         "core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl",
         "core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl",
@@ -529,6 +536,7 @@
         "telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl",
         "telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl",
         "telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl",
+        "telephony/java/android/telephony/ICellInfoCallback.aidl",
         "telephony/java/android/telephony/INetworkService.aidl",
         "telephony/java/android/telephony/INetworkServiceCallback.aidl",
         "telephony/java/com/android/ims/internal/IImsCallSession.aidl",
@@ -563,7 +571,6 @@
         "telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl",
         "telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl",
         "telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl",
-        "telephony/java/com/android/internal/telephony/IRcs.aidl",
         "telephony/java/com/android/internal/telephony/ISms.aidl",
         "telephony/java/com/android/internal/telephony/ISub.aidl",
         "telephony/java/com/android/internal/telephony/IAns.aidl",
@@ -594,6 +601,9 @@
         "telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.aidl",
         "telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl",
         "telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl",
+        "telephony/java/com/android/internal/telephony/rcs/IRcs.aidl",
+        "wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl",
+        "wifi/java/android/net/wifi/INetworkRequestUserSelectionCallback.aidl",
         "wifi/java/android/net/wifi/ISoftApCallback.aidl",
         "wifi/java/android/net/wifi/ITrafficStateCallback.aidl",
         "wifi/java/android/net/wifi/IWifiManager.aidl",
@@ -692,6 +702,7 @@
     ],
 
     static_libs: [
+        "apex_aidl_interface-java",
         "framework-protos",
         "mediaplayer2-protos",
         "android.hidl.base-V1.0-java",
@@ -699,6 +710,8 @@
         "android.hardware.contexthub-V1.0-java",
         "android.hardware.health-V1.0-java-constants",
         "android.hardware.thermal-V1.0-java-constants",
+        "android.hardware.thermal-V1.1-java",
+        "android.hardware.thermal-V2.0-java",
         "android.hardware.tv.input-V1.0-java-constants",
         "android.hardware.usb-V1.0-java-constants",
         "android.hardware.usb-V1.1-java-constants",
@@ -757,6 +770,16 @@
     ],
 }
 
+// A host library containing the inspector annotations for inspector-annotation-processor.
+java_library_host {
+    name: "inspector-annotation",
+    srcs: [
+        "core/java/android/view/inspector/InspectableChildren.java",
+        "core/java/android/view/inspector/InspectableNodeName.java",
+        "core/java/android/view/inspector/InspectableProperty.java",
+    ],
+}
+
 // A host library including just UnsupportedAppUsage.java so that the annotation
 // processor can also use this annotation.
 java_library_host {
@@ -1177,6 +1200,7 @@
         ":openjdk_javadoc_files",
         ":non_openjdk_javadoc_files",
         ":android_icu4j_src_files_for_docs",
+        ":conscrypt_public_api_files",
         "test-mock/src/**/*.java",
         "test-runner/src/**/*.java",
     ],
@@ -1237,6 +1261,7 @@
         ":openjdk_javadoc_files",
         ":non_openjdk_javadoc_files",
         ":android_icu4j_src_files_for_docs",
+        ":conscrypt_public_api_files",
     ],
     srcs_lib: "framework",
     srcs_lib_whitelist_dirs: frameworks_base_subdirs,
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
index 434b8e5..bd91112 100644
--- a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
@@ -343,13 +343,14 @@
             textView.setText(text);
             textView.measure(width, height);
             textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
-            final RecordingCanvas c = node.start(
+            final RecordingCanvas c = node.startRecording(
                 textView.getMeasuredWidth(), textView.getMeasuredHeight());
             textView.nullLayouts();
             Canvas.freeTextLayoutCaches();
             state.resumeTiming();
 
             textView.onDraw(c);
+            node.endRecording();
         }
     }
 
@@ -369,13 +370,14 @@
             textView.setText(text);
             textView.measure(width, height);
             textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
-            final RecordingCanvas c = node.start(
+            final RecordingCanvas c = node.startRecording(
                 textView.getMeasuredWidth(), textView.getMeasuredHeight());
             textView.nullLayouts();
             Canvas.freeTextLayoutCaches();
             state.resumeTiming();
 
             textView.onDraw(c);
+            node.endRecording();
         }
     }
 
@@ -397,13 +399,14 @@
             textView.setText(text);
             textView.measure(width, height);
             textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
-            final RecordingCanvas c = node.start(
+            final RecordingCanvas c = node.startRecording(
                 textView.getMeasuredWidth(), textView.getMeasuredHeight());
             textView.nullLayouts();
             Canvas.freeTextLayoutCaches();
             state.resumeTiming();
 
             textView.onDraw(c);
+            node.endRecording();
         }
     }
 
@@ -426,13 +429,14 @@
             textView.setText(text);
             textView.measure(width, height);
             textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
-            final RecordingCanvas c = node.start(
+            final RecordingCanvas c = node.startRecording(
                 textView.getMeasuredWidth(), textView.getMeasuredHeight());
             textView.nullLayouts();
             Canvas.freeTextLayoutCaches();
             state.resumeTiming();
 
             textView.onDraw(c);
+            node.endRecording();
         }
     }
 }
diff --git a/api/current.txt b/api/current.txt
index f387c5d..b192d7f 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -740,6 +740,7 @@
     field public static final int immersive = 16843456; // 0x10102c0
     field public static final int importantForAccessibility = 16843690; // 0x10103aa
     field public static final int importantForAutofill = 16844120; // 0x1010558
+    field public static final int importantForContentCapture = 16844182; // 0x1010596
     field public static final int inAnimation = 16843127; // 0x1010177
     field public static final int includeFontPadding = 16843103; // 0x101015f
     field public static final int includeInGlobalSearch = 16843374; // 0x101026e
@@ -769,6 +770,7 @@
     field public static final int insetRight = 16843192; // 0x10101b8
     field public static final int insetTop = 16843193; // 0x10101b9
     field public static final int installLocation = 16843447; // 0x10102b7
+    field public static final int interactiveUiTimeout = 16844181; // 0x1010595
     field public static final int interpolator = 16843073; // 0x1010141
     field public static final int isAlwaysSyncable = 16843571; // 0x1010333
     field public static final int isAsciiCapable = 16843753; // 0x10103e9
@@ -941,7 +943,6 @@
     field public static final int minSdkVersion = 16843276; // 0x101020c
     field public static final int minWidth = 16843071; // 0x101013f
     field public static final int minimumHorizontalAngle = 16843901; // 0x101047d
-    field public static final int minimumUiTimeout = 16844175; // 0x101058f
     field public static final int minimumVerticalAngle = 16843902; // 0x101047e
     field public static final int mipMap = 16843725; // 0x10103cd
     field public static final int mirrorForRtl = 16843726; // 0x10103ce
@@ -965,6 +966,7 @@
     field public static final int nextFocusRight = 16842978; // 0x10100e2
     field public static final int nextFocusUp = 16842979; // 0x10100e3
     field public static final int noHistory = 16843309; // 0x101022d
+    field public static final int nonInteractiveUiTimeout = 16844175; // 0x101058f
     field public static final int normalScreens = 16843397; // 0x1010285
     field public static final int notificationTimeout = 16843651; // 0x1010383
     field public static final int numColumns = 16843032; // 0x1010118
@@ -1844,6 +1846,10 @@
     field public static final int accessibilityActionContextClick = 16908348; // 0x102003c
     field public static final int accessibilityActionHideTooltip = 16908357; // 0x1020045
     field public static final int accessibilityActionMoveWindow = 16908354; // 0x1020042
+    field public static final int accessibilityActionPageDown = 16908359; // 0x1020047
+    field public static final int accessibilityActionPageLeft = 16908360; // 0x1020048
+    field public static final int accessibilityActionPageRight = 16908361; // 0x1020049
+    field public static final int accessibilityActionPageUp = 16908358; // 0x1020046
     field public static final int accessibilityActionScrollDown = 16908346; // 0x102003a
     field public static final int accessibilityActionScrollLeft = 16908345; // 0x1020039
     field public static final int accessibilityActionScrollRight = 16908347; // 0x102003b
@@ -2886,12 +2892,14 @@
     method public int getCapabilities();
     method public deprecated java.lang.String getDescription();
     method public java.lang.String getId();
-    method public int getMinimumUiTimeoutMillis();
+    method public int getInteractiveUiTimeoutMillis();
+    method public int getNonInteractiveUiTimeoutMillis();
     method public android.content.pm.ResolveInfo getResolveInfo();
     method public java.lang.String getSettingsActivityName();
     method public java.lang.String loadDescription(android.content.pm.PackageManager);
     method public java.lang.CharSequence loadSummary(android.content.pm.PackageManager);
-    method public void setMinimumUiTimeoutMillis(int);
+    method public void setInteractiveUiTimeoutMillis(int);
+    method public void setNonInteractiveUiTimeoutMillis(int);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CAPABILITY_CAN_CONTROL_MAGNIFICATION = 16; // 0x10
     field public static final int CAPABILITY_CAN_PERFORM_GESTURES = 32; // 0x20
@@ -5362,6 +5370,7 @@
     field public static final android.os.Parcelable.Creator<android.app.Notification.Action> CREATOR;
     field public static final int SEMANTIC_ACTION_ARCHIVE = 5; // 0x5
     field public static final int SEMANTIC_ACTION_CALL = 10; // 0xa
+    field public static final int SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION = 11; // 0xb
     field public static final int SEMANTIC_ACTION_DELETE = 4; // 0x4
     field public static final int SEMANTIC_ACTION_MARK_AS_READ = 2; // 0x2
     field public static final int SEMANTIC_ACTION_MARK_AS_UNREAD = 3; // 0x3
@@ -6181,6 +6190,7 @@
 
   public final class UiAutomation {
     method public void adoptShellPermissionIdentity();
+    method public void adoptShellPermissionIdentity(java.lang.String...);
     method public void clearWindowAnimationFrameStats();
     method public boolean clearWindowContentFrameStats(int);
     method public void dropShellPermissionIdentity();
@@ -7572,6 +7582,8 @@
     method public java.lang.String getShortcutId();
     method public long getTimeStamp();
     field public static final int CONFIGURATION_CHANGE = 5; // 0x5
+    field public static final int FOREGROUND_SERVICE_START = 19; // 0x13
+    field public static final int FOREGROUND_SERVICE_STOP = 20; // 0x14
     field public static final int KEYGUARD_HIDDEN = 18; // 0x12
     field public static final int KEYGUARD_SHOWN = 17; // 0x11
     field public static final int MOVE_TO_BACKGROUND = 2; // 0x2
@@ -7589,9 +7601,11 @@
     method public void add(android.app.usage.UsageStats);
     method public int describeContents();
     method public long getFirstTimeStamp();
+    method public long getLastTimeForegroundServiceUsed();
     method public long getLastTimeStamp();
     method public long getLastTimeUsed();
     method public java.lang.String getPackageName();
+    method public long getTotalTimeForegroundServiceUsed();
     method public long getTotalTimeInForeground();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.usage.UsageStats> CREATOR;
@@ -9462,6 +9476,7 @@
 
   public abstract class Context {
     ctor public Context();
+    method public abstract boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, java.lang.String);
     method public abstract boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
     method public abstract int checkCallingOrSelfPermission(java.lang.String);
     method public abstract int checkCallingOrSelfUriPermission(android.net.Uri, int);
@@ -9673,6 +9688,7 @@
   public class ContextWrapper extends android.content.Context {
     ctor public ContextWrapper(android.content.Context);
     method protected void attachBaseContext(android.content.Context);
+    method public boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, java.lang.String);
     method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
     method public int checkCallingOrSelfPermission(java.lang.String);
     method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
@@ -11176,12 +11192,17 @@
 
   public static class PackageInstaller.Session implements java.io.Closeable {
     method public void abandon();
+    method public void addChildSessionId(int);
     method public void close();
     method public void commit(android.content.IntentSender);
     method public void fsync(java.io.OutputStream) throws java.io.IOException;
+    method public int[] getChildSessionIds();
     method public java.lang.String[] getNames() throws java.io.IOException;
+    method public int getParentSessionId();
+    method public boolean isMultiPackage();
     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 removeChildSessionId(int);
     method public void removeSplit(java.lang.String) throws java.io.IOException;
     method public void setStagingProgress(float);
     method public void transfer(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -11202,20 +11223,24 @@
     method public android.graphics.Bitmap getAppIcon();
     method public java.lang.CharSequence getAppLabel();
     method public java.lang.String getAppPackageName();
+    method public int[] getChildSessionIds();
     method public int getInstallLocation();
     method public int getInstallReason();
     method public java.lang.String getInstallerPackageName();
     method public int getMode();
     method public int getOriginatingUid();
     method public android.net.Uri getOriginatingUri();
+    method public int getParentSessionId();
     method public float getProgress();
     method public android.net.Uri getReferrerUri();
     method public int getSessionId();
     method public long getSize();
     method public boolean isActive();
+    method public boolean isMultiPackage();
     method public boolean isSealed();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionInfo> CREATOR;
+    field public static final int INVALID_ID = -1; // 0xffffffff
   }
 
   public static class PackageInstaller.SessionParams implements android.os.Parcelable {
@@ -11226,6 +11251,7 @@
     method public void setAppPackageName(java.lang.String);
     method public void setInstallLocation(int);
     method public void setInstallReason(int);
+    method public void setMultiPackage();
     method public void setOriginatingUid(int);
     method public void setOriginatingUri(android.net.Uri);
     method public void setReferrerUri(android.net.Uri);
@@ -13878,6 +13904,7 @@
     field public static final int RAW_SENSOR = 32; // 0x20
     field public static final int RGB_565 = 4; // 0x4
     field public static final int UNKNOWN = 0; // 0x0
+    field public static final int Y8 = 538982489; // 0x20203859
     field public static final int YUV_420_888 = 35; // 0x23
     field public static final int YUV_422_888 = 39; // 0x27
     field public static final int YUV_444_888 = 40; // 0x28
@@ -14610,9 +14637,9 @@
     method public final boolean next(android.graphics.Rect);
   }
 
-  public class RenderNode {
+  public final class RenderNode {
+    ctor public RenderNode(java.lang.String);
     method public int computeApproximateMemoryUsage();
-    method public static android.graphics.RenderNode create(java.lang.String);
     method public void discardDisplayList();
     method public void endRecording();
     method public float getAlpha();
@@ -14769,9 +14796,10 @@
 
   public static class Typeface.CustomFallbackBuilder {
     ctor public Typeface.CustomFallbackBuilder(android.graphics.fonts.FontFamily);
+    method public android.graphics.Typeface.CustomFallbackBuilder addCustomFallback(android.graphics.fonts.FontFamily);
     method public android.graphics.Typeface build();
-    method public android.graphics.Typeface.CustomFallbackBuilder setFallback(java.lang.String);
     method public android.graphics.Typeface.CustomFallbackBuilder setStyle(android.graphics.fonts.FontStyle);
+    method public android.graphics.Typeface.CustomFallbackBuilder setSystemFallback(java.lang.String);
   }
 
   public class Xfermode {
@@ -14978,7 +15006,7 @@
     method public final int getLevel();
     method public int getMinimumHeight();
     method public int getMinimumWidth();
-    method public abstract int getOpacity();
+    method public abstract deprecated int getOpacity();
     method public android.graphics.Insets getOpticalInsets();
     method public void getOutline(android.graphics.Outline);
     method public boolean getPadding(android.graphics.Rect);
@@ -16291,6 +16319,7 @@
     method public java.util.List<android.hardware.camera2.CameraCharacteristics.Key<?>> getKeys();
     method public java.util.List<android.hardware.camera2.CameraCharacteristics.Key<?>> getKeysNeedingPermission();
     method public java.util.Set<java.lang.String> getPhysicalCameraIds();
+    method public android.hardware.camera2.params.RecommendedStreamConfigurationMap getRecommendedStreamConfigurationMap(int);
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AE_AVAILABLE_ANTIBANDING_MODES;
     field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AE_AVAILABLE_MODES;
@@ -16607,6 +16636,8 @@
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG = 2; // 0x2
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG = 1; // 0x1
+    field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO = 5; // 0x5
+    field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR = 6; // 0x6
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4; // 0x4
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB = 0; // 0x0
     field public static final int SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME = 1; // 0x1
@@ -16953,6 +16984,33 @@
     field public static final int SURFACE_GROUP_ID_NONE = -1; // 0xffffffff
   }
 
+  public final class RecommendedStreamConfigurationMap {
+    method public java.util.Set<android.util.Size> getHighResolutionOutputSizes(int);
+    method public java.util.Set<android.util.Range<java.lang.Integer>> getHighSpeedVideoFpsRanges();
+    method public java.util.Set<android.util.Range<java.lang.Integer>> getHighSpeedVideoFpsRangesFor(android.util.Size);
+    method public java.util.Set<android.util.Size> getHighSpeedVideoSizes();
+    method public java.util.Set<android.util.Size> getHighSpeedVideoSizesFor(android.util.Range<java.lang.Integer>);
+    method public java.util.Set<java.lang.Integer> getInputFormats();
+    method public java.util.Set<android.util.Size> getInputSizes(int);
+    method public java.util.Set<java.lang.Integer> getOutputFormats();
+    method public long getOutputMinFrameDuration(int, android.util.Size);
+    method public <T> long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
+    method public java.util.Set<android.util.Size> getOutputSizes(int);
+    method public <T> java.util.Set<android.util.Size> getOutputSizes(java.lang.Class<T>);
+    method public long getOutputStallDuration(int, android.util.Size);
+    method public <T> long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
+    method public int getRecommendedUseCase();
+    method public java.util.Set<java.lang.Integer> getValidOutputFormatsForInput(int);
+    method public boolean isOutputSupportedFor(int);
+    method public boolean isOutputSupportedFor(android.view.Surface);
+    field public static final int USECASE_PREVIEW = 0; // 0x0
+    field public static final int USECASE_RAW = 5; // 0x5
+    field public static final int USECASE_RECORD = 1; // 0x1
+    field public static final int USECASE_SNAPSHOT = 3; // 0x3
+    field public static final int USECASE_VIDEO_SNAPSHOT = 2; // 0x2
+    field public static final int USECASE_ZSL = 4; // 0x4
+  }
+
   public final class RggbChannelVector {
     ctor public RggbChannelVector(float, float, float, float);
     method public void copyTo(float[], int);
@@ -20664,6 +20722,51 @@
     enum_constant public static final android.icu.text.TimeZoneNames.NameType SHORT_STANDARD;
   }
 
+  public abstract class Transliterator {
+    method public static final android.icu.text.Transliterator createFromRules(java.lang.String, java.lang.String, int);
+    method public void filteredTransliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, boolean);
+    method public final void finishTransliteration(android.icu.text.Replaceable, android.icu.text.Transliterator.Position);
+    method public static final java.util.Enumeration<java.lang.String> getAvailableIDs();
+    method public static final java.util.Enumeration<java.lang.String> getAvailableSources();
+    method public static final java.util.Enumeration<java.lang.String> getAvailableTargets(java.lang.String);
+    method public static final java.util.Enumeration<java.lang.String> getAvailableVariants(java.lang.String, java.lang.String);
+    method public static final java.lang.String getDisplayName(java.lang.String);
+    method public static java.lang.String getDisplayName(java.lang.String, java.util.Locale);
+    method public static java.lang.String getDisplayName(java.lang.String, android.icu.util.ULocale);
+    method public android.icu.text.Transliterator[] getElements();
+    method public final android.icu.text.UnicodeFilter getFilter();
+    method public final java.lang.String getID();
+    method public static final android.icu.text.Transliterator getInstance(java.lang.String);
+    method public static android.icu.text.Transliterator getInstance(java.lang.String, int);
+    method public final android.icu.text.Transliterator getInverse();
+    method public final int getMaximumContextLength();
+    method public final android.icu.text.UnicodeSet getSourceSet();
+    method public android.icu.text.UnicodeSet getTargetSet();
+    method public void setFilter(android.icu.text.UnicodeFilter);
+    method public java.lang.String toRules(boolean);
+    method public final int transliterate(android.icu.text.Replaceable, int, int);
+    method public final void transliterate(android.icu.text.Replaceable);
+    method public final java.lang.String transliterate(java.lang.String);
+    method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, java.lang.String);
+    method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, int);
+    method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position);
+    field public static final int FORWARD = 0; // 0x0
+    field public static final int REVERSE = 1; // 0x1
+  }
+
+  public static class Transliterator.Position {
+    ctor public Transliterator.Position();
+    ctor public Transliterator.Position(int, int, int);
+    ctor public Transliterator.Position(int, int, int, int);
+    ctor public Transliterator.Position(android.icu.text.Transliterator.Position);
+    method public void set(android.icu.text.Transliterator.Position);
+    method public final void validate(int);
+    field public int contextLimit;
+    field public int contextStart;
+    field public int limit;
+    field public int start;
+  }
+
   public abstract class UCharacterIterator implements java.lang.Cloneable {
     ctor protected UCharacterIterator();
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
@@ -23148,6 +23251,7 @@
     method public android.media.VolumeShaper createVolumeShaper(android.media.VolumeShaper.Configuration);
     method protected void finalize();
     method public void flush();
+    method public android.media.AudioAttributes getAudioAttributes();
     method public int getAudioFormat();
     method public int getAudioSessionId();
     method public int getBufferCapacityInFrames();
@@ -24160,6 +24264,8 @@
     method public static int getMaxSecurityLevel();
     method public int getMaxSessionCount();
     method public android.os.PersistableBundle getMetrics();
+    method public java.util.List<byte[]> getOfflineLicenseKeySetIds();
+    method public int getOfflineLicenseState(byte[]);
     method public int getOpenSessionCount();
     method public byte[] getPropertyByteArray(java.lang.String);
     method public java.lang.String getPropertyString(java.lang.String);
@@ -24180,6 +24286,7 @@
     method public void releaseSecureStops(byte[]);
     method public void removeAllSecureStops();
     method public void removeKeys(byte[]);
+    method public void removeOfflineLicense(byte[]);
     method public void removeSecureStop(byte[]);
     method public void restoreKeys(byte[], byte[]);
     method public void setOnEventListener(android.media.MediaDrm.OnEventListener);
@@ -24202,6 +24309,9 @@
     field public static final int KEY_TYPE_OFFLINE = 2; // 0x2
     field public static final int KEY_TYPE_RELEASE = 3; // 0x3
     field public static final int KEY_TYPE_STREAMING = 1; // 0x1
+    field public static final int OFFLINE_LICENSE_INACTIVE = 2; // 0x2
+    field public static final int OFFLINE_LICENSE_STATE_UNKNOWN = 0; // 0x0
+    field public static final int OFFLINE_LICENSE_USABLE = 1; // 0x1
     field public static final java.lang.String PROPERTY_ALGORITHMS = "algorithms";
     field public static final java.lang.String PROPERTY_DESCRIPTION = "description";
     field public static final java.lang.String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId";
@@ -24356,6 +24466,7 @@
   }
 
   public static final class MediaExtractor.CasInfo {
+    method public byte[] getPrivateData();
     method public android.media.MediaCas.Session getSession();
     method public int getSystemId();
   }
@@ -28644,6 +28755,20 @@
 
 }
 
+package android.net.ssl {
+
+  public class SSLEngines {
+    method public static boolean isSupportedEngine(javax.net.ssl.SSLEngine);
+    method public static void setUseSessionTickets(javax.net.ssl.SSLEngine, boolean);
+  }
+
+  public class SSLSockets {
+    method public static boolean isSupportedSocket(javax.net.ssl.SSLSocket);
+    method public static void setUseSessionTickets(javax.net.ssl.SSLSocket, boolean);
+  }
+
+}
+
 package android.net.wifi {
 
   public class ScanResult implements android.os.Parcelable {
@@ -28690,7 +28815,7 @@
     enum_constant public static final android.net.wifi.SupplicantState UNINITIALIZED;
   }
 
-  public class WifiConfiguration implements android.os.Parcelable {
+  public deprecated class WifiConfiguration implements android.os.Parcelable {
     ctor public WifiConfiguration();
     method public int describeContents();
     method public android.net.ProxyInfo getHttpProxy();
@@ -28702,9 +28827,11 @@
     field public java.lang.String SSID;
     field public java.util.BitSet allowedAuthAlgorithms;
     field public java.util.BitSet allowedGroupCiphers;
+    field public java.util.BitSet allowedGroupMgmtCiphers;
     field public java.util.BitSet allowedKeyManagement;
     field public java.util.BitSet allowedPairwiseCiphers;
     field public java.util.BitSet allowedProtocols;
+    field public java.util.BitSet allowedSuiteBCiphers;
     field public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
     field public boolean hiddenSSID;
     field public boolean isHomeProviderNetwork;
@@ -28728,6 +28855,7 @@
 
   public static class WifiConfiguration.GroupCipher {
     field public static final int CCMP = 3; // 0x3
+    field public static final int GCMP_256 = 5; // 0x5
     field public static final int TKIP = 2; // 0x2
     field public static final deprecated int WEP104 = 1; // 0x1
     field public static final deprecated int WEP40 = 0; // 0x0
@@ -28735,9 +28863,18 @@
     field public static final java.lang.String varName = "group";
   }
 
+  public static class WifiConfiguration.GroupMgmtCipher {
+    field public static final int BIP_CMAC_256 = 0; // 0x0
+    field public static final int BIP_GMAC_128 = 1; // 0x1
+    field public static final int BIP_GMAC_256 = 2; // 0x2
+  }
+
   public static class WifiConfiguration.KeyMgmt {
     field public static final int IEEE8021X = 3; // 0x3
     field public static final int NONE = 0; // 0x0
+    field public static final int OWE = 9; // 0x9
+    field public static final int SAE = 8; // 0x8
+    field public static final int SUITE_B_192 = 10; // 0xa
     field public static final int WPA_EAP = 2; // 0x2
     field public static final int WPA_PSK = 1; // 0x1
     field public static final java.lang.String[] strings;
@@ -28746,6 +28883,7 @@
 
   public static class WifiConfiguration.PairwiseCipher {
     field public static final int CCMP = 2; // 0x2
+    field public static final int GCMP_256 = 3; // 0x3
     field public static final int NONE = 0; // 0x0
     field public static final deprecated int TKIP = 1; // 0x1
     field public static final java.lang.String[] strings;
@@ -28844,7 +28982,8 @@
   }
 
   public class WifiManager {
-    method public int addNetwork(android.net.wifi.WifiConfiguration);
+    method public deprecated int addNetwork(android.net.wifi.WifiConfiguration);
+    method public boolean addNetworkSuggestions(java.util.List<android.net.wifi.WifiNetworkSuggestion>);
     method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
     method public static int calculateSignalLevel(int, int);
     method public deprecated void cancelWps(android.net.wifi.WifiManager.WpsCallback);
@@ -28852,10 +28991,10 @@
     method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(java.lang.String);
     method public android.net.wifi.WifiManager.WifiLock createWifiLock(int, java.lang.String);
     method public android.net.wifi.WifiManager.WifiLock createWifiLock(java.lang.String);
-    method public boolean disableNetwork(int);
-    method public boolean disconnect();
-    method public boolean enableNetwork(int, boolean);
-    method public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
+    method public deprecated boolean disableNetwork(int);
+    method public deprecated boolean disconnect();
+    method public deprecated boolean enableNetwork(int, boolean);
+    method public deprecated java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
     method public android.net.wifi.WifiInfo getConnectionInfo();
     method public android.net.DhcpInfo getDhcpInfo();
     method public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
@@ -28864,29 +29003,35 @@
     method public boolean is5GHzBandSupported();
     method public boolean isDeviceToApRttSupported();
     method public boolean isEnhancedPowerReportingSupported();
+    method public boolean isOweSupported();
     method public boolean isP2pSupported();
     method public boolean isPreferredNetworkOffloadSupported();
-    method public boolean isScanAlwaysAvailable();
+    method public deprecated boolean isScanAlwaysAvailable();
     method public boolean isTdlsSupported();
     method public boolean isWifiEnabled();
+    method public boolean isWpa3SaeSupported();
+    method public boolean isWpa3SuiteBSupported();
     method public deprecated boolean pingSupplicant();
-    method public boolean reassociate();
-    method public boolean reconnect();
-    method public boolean removeNetwork(int);
+    method public deprecated boolean reassociate();
+    method public deprecated boolean reconnect();
+    method public deprecated boolean removeNetwork(int);
+    method public boolean removeNetworkSuggestions(java.util.List<android.net.wifi.WifiNetworkSuggestion>);
     method public void removePasspointConfiguration(java.lang.String);
     method public deprecated boolean saveConfiguration();
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
-    method public boolean setWifiEnabled(boolean);
+    method public deprecated boolean setWifiEnabled(boolean);
     method public void startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback, android.os.Handler);
     method public deprecated boolean startScan();
     method public deprecated void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
-    method public int updateNetwork(android.net.wifi.WifiConfiguration);
+    method public deprecated int updateNetwork(android.net.wifi.WifiConfiguration);
     field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
+    field public static final java.lang.String ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION = "android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION";
     field public static final deprecated int ERROR_AUTHENTICATING = 1; // 0x1
     field public static final deprecated java.lang.String EXTRA_BSSID = "bssid";
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
+    field public static final java.lang.String EXTRA_NETWORK_SUGGESTION = "android.net.wifi.extra.NETWORK_SUGGESTION";
     field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
     field public static final deprecated java.lang.String EXTRA_NEW_STATE = "newState";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
@@ -28955,6 +29100,29 @@
     method public abstract deprecated void onSucceeded();
   }
 
+  public class WifiNetworkConfigBuilder {
+    ctor public WifiNetworkConfigBuilder();
+    method public android.net.NetworkSpecifier buildNetworkSpecifier();
+    method public android.net.wifi.WifiNetworkSuggestion buildNetworkSuggestion();
+    method public android.net.wifi.WifiNetworkConfigBuilder setBssid(android.net.MacAddress);
+    method public android.net.wifi.WifiNetworkConfigBuilder setBssidPattern(android.net.MacAddress, android.net.MacAddress);
+    method public android.net.wifi.WifiNetworkConfigBuilder setEnterpriseConfig(android.net.wifi.WifiEnterpriseConfig);
+    method public android.net.wifi.WifiNetworkConfigBuilder setIsAppInteractionRequired();
+    method public android.net.wifi.WifiNetworkConfigBuilder setIsHiddenSsid();
+    method public android.net.wifi.WifiNetworkConfigBuilder setIsMetered();
+    method public android.net.wifi.WifiNetworkConfigBuilder setIsUserInteractionRequired();
+    method public android.net.wifi.WifiNetworkConfigBuilder setPriority(int);
+    method public android.net.wifi.WifiNetworkConfigBuilder setPskPassphrase(java.lang.String);
+    method public android.net.wifi.WifiNetworkConfigBuilder setSsid(java.lang.String);
+    method public android.net.wifi.WifiNetworkConfigBuilder setSsidPattern(android.os.PatternMatcher);
+  }
+
+  public final class WifiNetworkSuggestion implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.wifi.WifiNetworkSuggestion> CREATOR;
+  }
+
   public deprecated class WpsInfo implements android.os.Parcelable {
     ctor public deprecated WpsInfo();
     ctor public deprecated WpsInfo(android.net.wifi.WpsInfo);
@@ -34374,7 +34542,7 @@
   }
 
   public final class StorageVolume implements android.os.Parcelable {
-    method public android.content.Intent createAccessIntent(java.lang.String);
+    method public deprecated android.content.Intent createAccessIntent(java.lang.String);
     method public int describeContents();
     method public java.lang.String getDescription(android.content.Context);
     method public java.lang.String getState();
@@ -35613,6 +35781,15 @@
     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 BLOCK_REASON = "block_reason";
+    field public static final int BLOCK_REASON_BLOCKED_NUMBER = 3; // 0x3
+    field public static final int BLOCK_REASON_CALL_SCREENING_SERVICE = 1; // 0x1
+    field public static final int BLOCK_REASON_DIRECT_TO_VOICEMAIL = 2; // 0x2
+    field public static final int BLOCK_REASON_NOT_BLOCKED = 0; // 0x0
+    field public static final int BLOCK_REASON_NOT_IN_CONTACTS = 7; // 0x7
+    field public static final int BLOCK_REASON_PAY_PHONE = 6; // 0x6
+    field public static final int BLOCK_REASON_RESTRICTED_NUMBER = 5; // 0x5
+    field public static final int BLOCK_REASON_UNKNOWN_NUMBER = 4; // 0x4
     field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number";
     field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri";
     field public static final java.lang.String CACHED_MATCHED_NUMBER = "matched_number";
@@ -35622,6 +35799,8 @@
     field public static final java.lang.String CACHED_NUMBER_TYPE = "numbertype";
     field public static final java.lang.String CACHED_PHOTO_ID = "photo_id";
     field public static final java.lang.String CACHED_PHOTO_URI = "photo_uri";
+    field public static final java.lang.String CALL_SCREENING_APP_NAME = "call_screening_app_name";
+    field public static final java.lang.String CALL_SCREENING_COMPONENT_NAME = "call_screening_component_name";
     field public static final android.net.Uri CONTENT_FILTER_URI;
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/calls";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/calls";
@@ -37414,7 +37593,7 @@
     field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS";
     field public static final java.lang.String ACTION_SHOW_REGULATORY_INFO = "android.settings.SHOW_REGULATORY_INFO";
     field public static final java.lang.String ACTION_SOUND_SETTINGS = "android.settings.SOUND_SETTINGS";
-    field public static final java.lang.String ACTION_STORAGE_VOLUME_ACCESS_SETTINGS = "android.settings.STORAGE_VOLUME_ACCESS_SETTINGS";
+    field public static final deprecated java.lang.String ACTION_STORAGE_VOLUME_ACCESS_SETTINGS = "android.settings.STORAGE_VOLUME_ACCESS_SETTINGS";
     field public static final java.lang.String ACTION_SYNC_SETTINGS = "android.settings.SYNC_SETTINGS";
     field public static final java.lang.String ACTION_USAGE_ACCESS_SETTINGS = "android.settings.USAGE_ACCESS_SETTINGS";
     field public static final java.lang.String ACTION_USER_DICTIONARY_SETTINGS = "android.settings.USER_DICTIONARY_SETTINGS";
@@ -40274,6 +40453,7 @@
 
   public static class NotificationListenerService.Ranking {
     ctor public NotificationListenerService.Ranking();
+    method public boolean audiblyAlerted();
     method public boolean canShowBadge();
     method public android.app.NotificationChannel getChannel();
     method public int getImportance();
@@ -41971,7 +42151,7 @@
     field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
     field public static final int CAPABILITY_CAN_PULL_CALL = 16777216; // 0x1000000
     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 deprecated 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_MANAGE_CONFERENCE = 128; // 0x80
@@ -42391,6 +42571,7 @@
     method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
     method public java.util.List<android.telecom.PhoneAccountHandle> getSelfManagedPhoneAccounts();
     method public android.telecom.PhoneAccountHandle getSimCallManager();
+    method public java.lang.String getSystemDialerPackage();
     method public java.lang.String getVoiceMailNumber(android.telecom.PhoneAccountHandle);
     method public boolean handleMmi(java.lang.String);
     method public boolean handleMmi(java.lang.String, android.telecom.PhoneAccountHandle);
@@ -42806,6 +42987,16 @@
     field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityLte> CREATOR;
   }
 
+  public final class CellIdentityNr extends android.telephony.CellIdentity {
+    method public int getChannelNumber();
+    method public java.lang.String getMccString();
+    method public java.lang.String getMncString();
+    method public int getPci();
+    method public int getTac();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityNr> CREATOR;
+  }
+
   public final class CellIdentityTdscdma extends android.telephony.CellIdentity {
     method public int getCid();
     method public int getCpid();
@@ -42865,6 +43056,13 @@
     field public static final android.os.Parcelable.Creator<android.telephony.CellInfoLte> CREATOR;
   }
 
+  public final class CellInfoNr extends android.telephony.CellInfo {
+    method public android.telephony.CellIdentity getCellIdentity();
+    method public android.telephony.CellSignalStrength getCellSignalStrength();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.CellInfoNr> CREATOR;
+  }
+
   public final class CellInfoWcdma extends android.telephony.CellInfo implements android.os.Parcelable {
     method public android.telephony.CellIdentityWcdma getCellIdentity();
     method public android.telephony.CellSignalStrengthWcdma getCellSignalStrength();
@@ -42925,12 +43123,28 @@
     method public int getLevel();
     method public int getRsrp();
     method public int getRsrq();
+    method public int getRssi();
     method public int getRssnr();
     method public int getTimingAdvance();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthLte> CREATOR;
   }
 
+  public final class CellSignalStrengthNr extends android.telephony.CellSignalStrength implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getAsuLevel();
+    method public int getCsiRsrp();
+    method public int getCsiRsrq();
+    method public int getCsiSinr();
+    method public int getDbm();
+    method public int getLevel();
+    method public int getSsRsrp();
+    method public int getSsRsrq();
+    method public int getSsSinr();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthNr> CREATOR;
+  }
+
   public final class CellSignalStrengthWcdma extends android.telephony.CellSignalStrength implements android.os.Parcelable {
     method public int describeContents();
     method public int getAsuLevel();
@@ -43120,6 +43334,7 @@
 
   public class PhoneStateListener {
     ctor public PhoneStateListener();
+    ctor public PhoneStateListener(java.util.concurrent.Executor);
     method public void onCallForwardingIndicatorChanged(boolean);
     method public void onCallStateChanged(int, java.lang.String);
     method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
@@ -43345,6 +43560,7 @@
     method public java.lang.String getCountryIso();
     method public int getDataRoaming();
     method public java.lang.CharSequence getDisplayName();
+    method public java.lang.String getGroupUuid();
     method public java.lang.String getIccId();
     method public int getIconTint();
     method public deprecated int getMcc();
@@ -43352,7 +43568,6 @@
     method public deprecated int getMnc();
     method public java.lang.String getMncString();
     method public java.lang.String getNumber();
-    method public int getParentSubId();
     method public int getSimSlotIndex();
     method public int getSubscriptionId();
     method public boolean isEmbedded();
@@ -43386,6 +43601,7 @@
     method public static boolean isValidSubscriptionId(int);
     method public void removeOnOpportunisticSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
     method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+    method public java.lang.String setSubscriptionGroup(int[]);
     method public void setSubscriptionOverrideCongested(int, boolean, long);
     method public void setSubscriptionOverrideUnmetered(int, boolean, long);
     method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
@@ -43478,6 +43694,7 @@
     method public int getNetworkType();
     method public int getPhoneCount();
     method public int getPhoneType();
+    method public int getPreferredOpportunisticDataSubscription();
     method public android.telephony.ServiceState getServiceState();
     method public android.telephony.SignalStrength getSignalStrength();
     method public int getSimCarrierId();
@@ -43516,6 +43733,7 @@
     method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isWorldPhone();
     method public void listen(android.telephony.PhoneStateListener, int);
+    method public void requestCellInfoUpdate(java.util.concurrent.Executor, android.telephony.TelephonyManager.CellInfoCallback);
     method public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
     method public void sendDialerSpecialCode(java.lang.String);
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
@@ -43527,6 +43745,7 @@
     method public boolean setNetworkSelectionModeManual(java.lang.String, boolean);
     method public boolean setOperatorBrandOverride(java.lang.String);
     method public boolean setPreferredNetworkTypeToGlobal();
+    method public boolean setPreferredOpportunisticDataSubscription(int);
     method public void setVisualVoicemailSmsFilterSettings(android.telephony.VisualVoicemailSmsFilterSettings);
     method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
     method public deprecated void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
@@ -43617,6 +43836,11 @@
     field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
   }
 
+  public static abstract class TelephonyManager.CellInfoCallback {
+    ctor public TelephonyManager.CellInfoCallback();
+    method public abstract void onCellInfo(java.util.List<android.telephony.CellInfo>);
+  }
+
   public static abstract class TelephonyManager.UssdResponseCallback {
     ctor public TelephonyManager.UssdResponseCallback();
     method public void onReceiveUssdResponse(android.telephony.TelephonyManager, java.lang.String, java.lang.CharSequence);
@@ -43705,6 +43929,7 @@
     method public java.lang.String getApnName();
     method public int getApnTypeBitmask();
     method public int getAuthType();
+    method public int getCarrierId();
     method public java.lang.String getEntryName();
     method public int getId();
     method public deprecated java.net.InetAddress getMmsProxyAddress();
@@ -43755,6 +43980,7 @@
     method public android.telephony.data.ApnSetting.Builder setApnTypeBitmask(int);
     method public android.telephony.data.ApnSetting.Builder setAuthType(int);
     method public android.telephony.data.ApnSetting.Builder setCarrierEnabled(boolean);
+    method public android.telephony.data.ApnSetting.Builder setCarrierId(int);
     method public android.telephony.data.ApnSetting.Builder setEntryName(java.lang.String);
     method public deprecated android.telephony.data.ApnSetting.Builder setMmsProxyAddress(java.net.InetAddress);
     method public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(java.lang.String);
@@ -47718,6 +47944,7 @@
     field public static final int KEYCODE_PLUS = 81; // 0x51
     field public static final int KEYCODE_POUND = 18; // 0x12
     field public static final int KEYCODE_POWER = 26; // 0x1a
+    field public static final int KEYCODE_PROFILE_SWITCH = 288; // 0x120
     field public static final int KEYCODE_PROG_BLUE = 186; // 0xba
     field public static final int KEYCODE_PROG_GREEN = 184; // 0xb8
     field public static final int KEYCODE_PROG_RED = 183; // 0xb7
@@ -47756,6 +47983,8 @@
     field public static final int KEYCODE_SYSTEM_NAVIGATION_UP = 280; // 0x118
     field public static final int KEYCODE_T = 48; // 0x30
     field public static final int KEYCODE_TAB = 61; // 0x3d
+    field public static final int KEYCODE_THUMBS_DOWN = 287; // 0x11f
+    field public static final int KEYCODE_THUMBS_UP = 286; // 0x11e
     field public static final int KEYCODE_TV = 170; // 0xaa
     field public static final int KEYCODE_TV_ANTENNA_CABLE = 242; // 0xf2
     field public static final int KEYCODE_TV_AUDIO_DESCRIPTION = 252; // 0xfc
@@ -48637,6 +48866,7 @@
     method public int getId();
     method public int getImportantForAccessibility();
     method public int getImportantForAutofill();
+    method public int getImportantForContentCapture();
     method public boolean getKeepScreenOn();
     method public android.view.KeyEvent.DispatcherState getKeyDispatcherState();
     method public int getLabelFor();
@@ -48770,6 +49000,7 @@
     method public boolean isHovered();
     method public boolean isImportantForAccessibility();
     method public final boolean isImportantForAutofill();
+    method public final boolean isImportantForContentCapture();
     method public boolean isInEditMode();
     method public boolean isInLayout();
     method public boolean isInTouchMode();
@@ -48844,6 +49075,7 @@
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public void onProvideAutofillStructure(android.view.ViewStructure, int);
     method public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
+    method public boolean onProvideContentCaptureStructure(android.view.ViewStructure, int);
     method public void onProvideStructure(android.view.ViewStructure);
     method public void onProvideVirtualStructure(android.view.ViewStructure);
     method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
@@ -48962,6 +49194,7 @@
     method public void setId(int);
     method public void setImportantForAccessibility(int);
     method public void setImportantForAutofill(int);
+    method public void setImportantForContentCapture(int);
     method public void setKeepScreenOn(boolean);
     method public void setKeyboardNavigationCluster(boolean);
     method public void setLabelFor(int);
@@ -49132,6 +49365,11 @@
     field public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
     field public static final int IMPORTANT_FOR_AUTOFILL_YES = 1; // 0x1
     field public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
+    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0; // 0x0
+    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 2; // 0x2
+    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 8; // 0x8
+    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 1; // 0x1
+    field public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 4; // 0x4
     field public static final int INVISIBLE = 4; // 0x4
     field public static final int KEEP_SCREEN_ON = 67108864; // 0x4000000
     field public static final int LAYER_TYPE_HARDWARE = 2; // 0x2
@@ -50118,17 +50356,29 @@
     method public int getStableInsetLeft();
     method public int getStableInsetRight();
     method public int getStableInsetTop();
+    method public android.graphics.Insets getStableInsets();
     method public int getSystemWindowInsetBottom();
     method public int getSystemWindowInsetLeft();
     method public int getSystemWindowInsetRight();
     method public int getSystemWindowInsetTop();
+    method public android.graphics.Insets getSystemWindowInsets();
     method public boolean hasInsets();
     method public boolean hasStableInsets();
     method public boolean hasSystemWindowInsets();
+    method public android.view.WindowInsets inset(int, int, int, int);
     method public boolean isConsumed();
     method public boolean isRound();
-    method public android.view.WindowInsets replaceSystemWindowInsets(int, int, int, int);
-    method public android.view.WindowInsets replaceSystemWindowInsets(android.graphics.Rect);
+    method public deprecated android.view.WindowInsets replaceSystemWindowInsets(int, int, int, int);
+    method public deprecated android.view.WindowInsets replaceSystemWindowInsets(android.graphics.Rect);
+  }
+
+  public static class WindowInsets.Builder {
+    ctor public WindowInsets.Builder();
+    ctor public WindowInsets.Builder(android.view.WindowInsets);
+    method public android.view.WindowInsets build();
+    method public android.view.WindowInsets.Builder setDisplayCutout(android.view.DisplayCutout);
+    method public android.view.WindowInsets.Builder setStableInsets(android.graphics.Insets);
+    method public android.view.WindowInsets.Builder setSystemWindowInsets(android.graphics.Insets);
   }
 
   public abstract interface WindowManager implements android.view.ViewManager {
@@ -50384,7 +50634,7 @@
     method public deprecated java.util.List<android.content.pm.ServiceInfo> getAccessibilityServiceList();
     method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int);
     method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
-    method public int getMinimumUiTimeoutMillis();
+    method public int getRecommendedTimeoutMillis(int, int);
     method public void interrupt();
     method public static boolean isAccessibilityButtonSupported();
     method public boolean isEnabled();
@@ -50393,6 +50643,9 @@
     method public boolean removeAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener);
     method public boolean removeTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener);
     method public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
+    field public static final int FLAG_CONTENT_CONTROLS = 4; // 0x4
+    field public static final int FLAG_CONTENT_ICONS = 1; // 0x1
+    field public static final int FLAG_CONTENT_TEXT = 2; // 0x2
   }
 
   public static abstract interface AccessibilityManager.AccessibilityStateChangeListener {
@@ -50609,6 +50862,10 @@
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_MOVE_WINDOW;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_NEXT_AT_MOVEMENT_GRANULARITY;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_NEXT_HTML_ELEMENT;
+    field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PAGE_DOWN;
+    field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PAGE_LEFT;
+    field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PAGE_RIGHT;
+    field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PAGE_UP;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PASTE;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
     field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_PREVIOUS_HTML_ELEMENT;
@@ -51567,6 +51824,10 @@
     method public void disableContentCapture();
     method public android.content.ComponentName getIntelligenceServiceComponentName();
     method public boolean isContentCaptureEnabled();
+    method public android.view.ViewStructure newVirtualViewStructure(android.view.autofill.AutofillId, int);
+    method public void notifyViewAppeared(android.view.ViewStructure);
+    method public void notifyViewDisappeared(android.view.autofill.AutofillId);
+    method public void notifyViewTextChanged(android.view.autofill.AutofillId, java.lang.CharSequence, int);
     field public static final int FLAG_USER_INPUT = 1; // 0x1
   }
 
@@ -51880,6 +52141,7 @@
   public final class TextLinks implements android.os.Parcelable {
     method public int apply(android.text.Spannable, int, java.util.function.Function<android.view.textclassifier.TextLinks.TextLink, android.view.textclassifier.TextLinks.TextLinkSpan>);
     method public int describeContents();
+    method public android.os.Bundle getExtras();
     method public java.util.Collection<android.view.textclassifier.TextLinks.TextLink> getLinks();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int APPLY_STRATEGY_IGNORE = 0; // 0x0
@@ -51896,12 +52158,14 @@
     method public android.view.textclassifier.TextLinks.Builder addLink(int, int, java.util.Map<java.lang.String, java.lang.Float>);
     method public android.view.textclassifier.TextLinks build();
     method public android.view.textclassifier.TextLinks.Builder clearTextLinks();
+    method public android.view.textclassifier.TextLinks.Builder setExtras(android.os.Bundle);
   }
 
   public static final class TextLinks.Request implements android.os.Parcelable {
     method public int describeContents();
     method public android.os.LocaleList getDefaultLocales();
     method public android.view.textclassifier.TextClassifier.EntityConfig getEntityConfig();
+    method public android.os.Bundle getExtras();
     method public java.lang.CharSequence getText();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.view.textclassifier.TextLinks.Request> CREATOR;
@@ -51912,6 +52176,7 @@
     method public android.view.textclassifier.TextLinks.Request build();
     method public android.view.textclassifier.TextLinks.Request.Builder setDefaultLocales(android.os.LocaleList);
     method public android.view.textclassifier.TextLinks.Request.Builder setEntityConfig(android.view.textclassifier.TextClassifier.EntityConfig);
+    method public android.view.textclassifier.TextLinks.Request.Builder setExtras(android.os.Bundle);
   }
 
   public static final class TextLinks.TextLink implements android.os.Parcelable {
@@ -51936,6 +52201,7 @@
     method public float getConfidenceScore(java.lang.String);
     method public java.lang.String getEntity(int);
     method public int getEntityCount();
+    method public android.os.Bundle getExtras();
     method public java.lang.String getId();
     method public int getSelectionEndIndex();
     method public int getSelectionStartIndex();
@@ -51947,6 +52213,7 @@
     ctor public TextSelection.Builder(int, int);
     method public android.view.textclassifier.TextSelection build();
     method public android.view.textclassifier.TextSelection.Builder setEntityType(java.lang.String, float);
+    method public android.view.textclassifier.TextSelection.Builder setExtras(android.os.Bundle);
     method public android.view.textclassifier.TextSelection.Builder setId(java.lang.String);
   }
 
@@ -51954,6 +52221,7 @@
     method public int describeContents();
     method public android.os.LocaleList getDefaultLocales();
     method public int getEndIndex();
+    method public android.os.Bundle getExtras();
     method public int getStartIndex();
     method public java.lang.CharSequence getText();
     method public void writeToParcel(android.os.Parcel, int);
@@ -51964,6 +52232,7 @@
     ctor public TextSelection.Request.Builder(java.lang.CharSequence, int, int);
     method public android.view.textclassifier.TextSelection.Request build();
     method public android.view.textclassifier.TextSelection.Request.Builder setDefaultLocales(android.os.LocaleList);
+    method public android.view.textclassifier.TextSelection.Request.Builder setExtras(android.os.Bundle);
   }
 
 }
@@ -54098,10 +54367,14 @@
     method public int getSourceWidth();
     method public int getWidth();
     method public float getZoom();
+    method public boolean isForcePositionWithinWindowSystemInsetsBounds();
     method public void setZoom(float);
     method public void show(float, float);
     method public void show(float, float, float, float);
     method public void update();
+    field public static final int SOURCE_BOUND_MAX_IN_SURFACE = 0; // 0x0
+    field public static final int SOURCE_BOUND_MAX_IN_VIEW = 1; // 0x1
+    field public static final int SOURCE_BOUND_MAX_VISIBLE = 2; // 0x2
   }
 
   public static class Magnifier.Builder {
@@ -54110,7 +54383,9 @@
     method public android.widget.Magnifier.Builder setCornerRadius(float);
     method public android.widget.Magnifier.Builder setDefaultSourceToMagnifierOffset(int, int);
     method public android.widget.Magnifier.Builder setElevation(float);
+    method public android.widget.Magnifier.Builder setForcePositionWithinWindowSystemInsetsBounds(boolean);
     method public android.widget.Magnifier.Builder setSize(int, int);
+    method public android.widget.Magnifier.Builder setSourceBounds(int, int, int, int);
     method public android.widget.Magnifier.Builder setZoom(float);
   }
 
@@ -73666,10 +73941,13 @@
     method public abstract void beginHandshake() throws javax.net.ssl.SSLException;
     method public abstract void closeInbound() throws javax.net.ssl.SSLException;
     method public abstract void closeOutbound();
+    method public java.lang.String getApplicationProtocol();
     method public abstract java.lang.Runnable getDelegatedTask();
     method public abstract boolean getEnableSessionCreation();
     method public abstract java.lang.String[] getEnabledCipherSuites();
     method public abstract java.lang.String[] getEnabledProtocols();
+    method public java.lang.String getHandshakeApplicationProtocol();
+    method public java.util.function.BiFunction<javax.net.ssl.SSLEngine, java.util.List<java.lang.String>, java.lang.String> getHandshakeApplicationProtocolSelector();
     method public javax.net.ssl.SSLSession getHandshakeSession();
     method public abstract javax.net.ssl.SSLEngineResult.HandshakeStatus getHandshakeStatus();
     method public abstract boolean getNeedClientAuth();
@@ -73686,6 +73964,7 @@
     method public abstract void setEnableSessionCreation(boolean);
     method public abstract void setEnabledCipherSuites(java.lang.String[]);
     method public abstract void setEnabledProtocols(java.lang.String[]);
+    method public void setHandshakeApplicationProtocolSelector(java.util.function.BiFunction<javax.net.ssl.SSLEngine, java.util.List<java.lang.String>, java.lang.String>);
     method public abstract void setNeedClientAuth(boolean);
     method public void setSSLParameters(javax.net.ssl.SSLParameters);
     method public abstract void setUseClientMode(boolean);
@@ -73744,6 +74023,7 @@
     ctor public SSLParameters(java.lang.String[]);
     ctor public SSLParameters(java.lang.String[], java.lang.String[]);
     method public java.security.AlgorithmConstraints getAlgorithmConstraints();
+    method public java.lang.String[] getApplicationProtocols();
     method public java.lang.String[] getCipherSuites();
     method public java.lang.String getEndpointIdentificationAlgorithm();
     method public boolean getNeedClientAuth();
@@ -73753,6 +74033,7 @@
     method public final boolean getUseCipherSuitesOrder();
     method public boolean getWantClientAuth();
     method public void setAlgorithmConstraints(java.security.AlgorithmConstraints);
+    method public void setApplicationProtocols(java.lang.String[]);
     method public void setCipherSuites(java.lang.String[]);
     method public void setEndpointIdentificationAlgorithm(java.lang.String);
     method public void setNeedClientAuth(boolean);
@@ -73857,9 +74138,12 @@
     ctor protected SSLSocket(java.lang.String, int, java.net.InetAddress, int) throws java.io.IOException, java.net.UnknownHostException;
     ctor protected SSLSocket(java.net.InetAddress, int, java.net.InetAddress, int) throws java.io.IOException;
     method public abstract void addHandshakeCompletedListener(javax.net.ssl.HandshakeCompletedListener);
+    method public java.lang.String getApplicationProtocol();
     method public abstract boolean getEnableSessionCreation();
     method public abstract java.lang.String[] getEnabledCipherSuites();
     method public abstract java.lang.String[] getEnabledProtocols();
+    method public java.lang.String getHandshakeApplicationProtocol();
+    method public java.util.function.BiFunction<javax.net.ssl.SSLSocket, java.util.List<java.lang.String>, java.lang.String> getHandshakeApplicationProtocolSelector();
     method public javax.net.ssl.SSLSession getHandshakeSession();
     method public abstract boolean getNeedClientAuth();
     method public javax.net.ssl.SSLParameters getSSLParameters();
@@ -73872,6 +74156,7 @@
     method public abstract void setEnableSessionCreation(boolean);
     method public abstract void setEnabledCipherSuites(java.lang.String[]);
     method public abstract void setEnabledProtocols(java.lang.String[]);
+    method public void setHandshakeApplicationProtocolSelector(java.util.function.BiFunction<javax.net.ssl.SSLSocket, java.util.List<java.lang.String>, java.lang.String>);
     method public abstract void setNeedClientAuth(boolean);
     method public void setSSLParameters(javax.net.ssl.SSLParameters);
     method public abstract void setUseClientMode(boolean);
diff --git a/api/system-current.txt b/api/system-current.txt
index 3074efd..cdd711f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -137,6 +137,7 @@
     field public static final java.lang.String PROVIDE_RESOLVER_RANKER_SERVICE = "android.permission.PROVIDE_RESOLVER_RANKER_SERVICE";
     field public static final java.lang.String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT";
     field public static final java.lang.String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES";
+    field public static final java.lang.String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
     field public static final java.lang.String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
     field public static final java.lang.String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
     field public static final java.lang.String READ_INSTALL_SESSIONS = "android.permission.READ_INSTALL_SESSIONS";
@@ -300,8 +301,8 @@
     method public static java.lang.String[] getOpStrs();
     method public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, java.lang.String, int[]);
     method public java.util.List<android.app.AppOpsManager.PackageOps> getPackagesForOpStrs(java.lang.String[]);
+    method public static int opToDefaultMode(java.lang.String);
     method public static java.lang.String opToPermission(java.lang.String);
-    method public void resetUidMode(java.lang.String, int, boolean);
     method public void setMode(java.lang.String, int, java.lang.String, int);
     method public void setUidMode(java.lang.String, int, int);
     field public static final java.lang.String OPSTR_ACCEPT_HANDOVER = "android:accept_handover";
@@ -1052,6 +1053,7 @@
     field public static final java.lang.String ACTION_INSTALL_INSTANT_APP_PACKAGE = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
     field public static final java.lang.String ACTION_INSTANT_APP_RESOLVER_SETTINGS = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
     field public static final java.lang.String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
+    field public static final java.lang.String ACTION_MANAGE_APP_PERMISSION = "android.intent.action.MANAGE_APP_PERMISSION";
     field public static final java.lang.String ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS";
     field public static final java.lang.String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS";
     field public static final java.lang.String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
@@ -1087,6 +1089,7 @@
     field public static final java.lang.String EXTRA_RESULT_NEEDED = "android.intent.extra.RESULT_NEEDED";
     field public static final java.lang.String EXTRA_UNKNOWN_INSTANT_APP = "android.intent.extra.UNKNOWN_INSTANT_APP";
     field public static final java.lang.String EXTRA_VERIFICATION_BUNDLE = "android.intent.extra.VERIFICATION_BUNDLE";
+    field public static final java.lang.String METADATA_SETUP_VERSION = "android.SETUP_VERSION";
   }
 
   public class IntentFilter implements android.os.Parcelable {
@@ -1203,6 +1206,7 @@
   public abstract class PackageManager {
     method public abstract void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
     method public abstract boolean arePermissionsIndividuallyControlled();
+    method public boolean canSuspendPackage(java.lang.String);
     method public abstract java.util.List<android.content.IntentFilter> getAllIntentFilters(java.lang.String);
     method public android.content.pm.dex.ArtManager getArtManager();
     method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
@@ -2719,6 +2723,7 @@
   public class LocationManager {
     method public deprecated boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
     method public deprecated boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
+    method public android.app.PendingIntent createManageLocationPermissionIntent(java.lang.String, java.lang.String);
     method public void flushGnssBatch();
     method public int getGnssBatchSize();
     method public java.lang.String getNetworkProviderPackage();
@@ -3615,7 +3620,7 @@
     field public byte id;
   }
 
-  public class WifiConfiguration implements android.os.Parcelable {
+  public deprecated class WifiConfiguration implements android.os.Parcelable {
     method public boolean hasNoInternetAccess();
     method public boolean isEphemeral();
     method public boolean isNoInternetAccessExpected();
@@ -3636,6 +3641,8 @@
 
   public class WifiManager {
     method public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
+    method public java.util.List<android.net.wifi.WifiConfiguration> getAllMatchingWifiConfigs(java.util.List<android.net.wifi.ScanResult>);
+    method public java.util.List<android.net.wifi.hotspot2.OsuProvider> getMatchingOsuProviders(java.util.List<android.net.wifi.ScanResult>);
     method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
     method public android.net.wifi.WifiConfiguration getWifiApConfiguration();
     method public int getWifiApState();
@@ -3644,8 +3651,10 @@
     method public boolean isPortableHotspotSupported();
     method public boolean isWifiApEnabled();
     method public boolean isWifiScannerSupported();
+    method public void registerNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback, android.os.Handler);
     method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
     method public boolean startScan(android.os.WorkSource);
+    method public void unregisterNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback);
     field public static final int CHANGE_REASON_ADDED = 0; // 0x0
     field public static final int CHANGE_REASON_CONFIG_CHANGE = 2; // 0x2
     field public static final int CHANGE_REASON_REMOVED = 1; // 0x1
@@ -3673,6 +3682,18 @@
     method public abstract void onSuccess();
   }
 
+  public static abstract interface WifiManager.NetworkRequestMatchCallback {
+    method public abstract void onMatch(java.util.List<android.net.wifi.WifiConfiguration>);
+    method public abstract void onUserSelectionCallbackRegistration(android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback);
+    method public abstract void onUserSelectionConnectFailure(android.net.wifi.WifiConfiguration);
+    method public abstract void onUserSelectionConnectSuccess(android.net.wifi.WifiConfiguration);
+  }
+
+  public static abstract interface WifiManager.NetworkRequestUserSelectionCallback {
+    method public abstract void reject();
+    method public abstract void select(android.net.wifi.WifiConfiguration);
+  }
+
   public class WifiNetworkConnectionStatistics implements android.os.Parcelable {
     ctor public WifiNetworkConnectionStatistics(int, int);
     ctor public WifiNetworkConnectionStatistics();
@@ -3815,6 +3836,14 @@
 
 }
 
+package android.net.wifi.p2p {
+
+  public class WifiP2pManager {
+    method public void factoryReset(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+  }
+
+}
+
 package android.net.wifi.rtt {
 
   public static final class RangingRequest.Builder {
@@ -4081,8 +4110,13 @@
   }
 
   public final class PowerManager {
+    method public void dream(long);
+    method public int getPowerSaveMode();
+    method public boolean setDynamicPowerSavings(boolean, int);
     method public boolean setPowerSaveMode(boolean);
     method public void userActivity(long, int, int);
+    field public static final int POWER_SAVER_MODE_DYNAMIC = 1; // 0x1
+    field public static final int POWER_SAVER_MODE_PERCENTAGE = 0; // 0x0
     field public static final int USER_ACTIVITY_EVENT_ACCESSIBILITY = 3; // 0x3
     field public static final int USER_ACTIVITY_EVENT_BUTTON = 1; // 0x1
     field public static final int USER_ACTIVITY_EVENT_OTHER = 0; // 0x0
@@ -4513,10 +4547,6 @@
   public final class Settings {
     field public static final java.lang.String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
     field public static final java.lang.String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
-    field public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10; // 0xa
-    field public static final int USER_SETUP_PERSONALIZATION_NOT_STARTED = 0; // 0x0
-    field public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2; // 0x2
-    field public static final int USER_SETUP_PERSONALIZATION_STARTED = 1; // 0x1
   }
 
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
@@ -4560,6 +4590,10 @@
     field public static final java.lang.String LOCK_SCREEN_SHOW_NOTIFICATIONS = "lock_screen_show_notifications";
     field public static final java.lang.String MANUAL_RINGER_TOGGLE_COUNT = "manual_ringer_toggle_count";
     field public static final java.lang.String USER_SETUP_COMPLETE = "user_setup_complete";
+    field public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10; // 0xa
+    field public static final int USER_SETUP_PERSONALIZATION_NOT_STARTED = 0; // 0x0
+    field public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2; // 0x2
+    field public static final int USER_SETUP_PERSONALIZATION_STARTED = 1; // 0x1
     field public static final java.lang.String USER_SETUP_PERSONALIZATION_STATE = "user_setup_personalization_state";
     field public static final java.lang.String VOLUME_HUSH_GESTURE = "volume_hush_gesture";
   }
@@ -4751,6 +4785,16 @@
 
 }
 
+package android.service.carrier {
+
+  public abstract class ApnService extends android.app.Service {
+    ctor public ApnService();
+    method public abstract java.util.List<android.content.ContentValues> onRestoreApns(int);
+    method public android.os.IBinder onBind(android.content.Intent);
+  }
+
+}
+
 package android.service.euicc {
 
   public final class EuiccProfileInfo implements android.os.Parcelable {
@@ -5399,15 +5443,21 @@
     method public int getAllPhoneAccountsCount();
     method public int getCallState();
     method public android.telecom.PhoneAccountHandle getConnectionManager();
+    method public int getCurrentTtyMode();
     method public deprecated android.content.ComponentName getDefaultPhoneApp();
     method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
     method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(java.lang.String);
     method public boolean isInEmergencyCall();
     method public boolean isRinging();
     method public boolean isTtySupported();
+    method public boolean setDefaultDialer(java.lang.String);
     field public static final java.lang.String EXTRA_CALL_BACK_INTENT = "android.telecom.extra.CALL_BACK_INTENT";
     field public static final java.lang.String EXTRA_CLEAR_MISSED_CALLS_INTENT = "android.telecom.extra.CLEAR_MISSED_CALLS_INTENT";
     field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
+    field public static final int TTY_MODE_FULL = 1; // 0x1
+    field public static final int TTY_MODE_HCO = 2; // 0x2
+    field public static final int TTY_MODE_OFF = 0; // 0x0
+    field public static final int TTY_MODE_VCO = 3; // 0x3
   }
 
 }
@@ -5423,6 +5473,7 @@
     method public static android.os.PersistableBundle getDefaultConfig();
     method public void overrideConfig(int, android.os.PersistableBundle);
     method public void updateConfigForPhoneId(int, java.lang.String);
+    field public static final java.lang.String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
     field public static final java.lang.String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
   }
 
@@ -5448,6 +5499,7 @@
     method public int getDomain();
     method public int getRegState();
     method public int getRejectCause();
+    method public int getRoamingType();
     method public int getTransportType();
     method public boolean isEmergencyEnabled();
     method public boolean isRoaming();
@@ -5495,7 +5547,11 @@
 
   public class PhoneStateListener {
     method public void onRadioPowerStateChanged(int);
+    method public void onSrvccStateChanged(int);
+    method public void onVoiceActivationStateChanged(int);
     field public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
+    field public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000
+    field public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000
   }
 
   public class ServiceState implements android.os.Parcelable {
@@ -5505,6 +5561,10 @@
     method public deprecated android.telephony.NetworkRegistrationState getNetworkRegistrationStates(int, int);
     method public java.util.List<android.telephony.NetworkRegistrationState> getNetworkRegistrationStatesForDomain(int);
     method public java.util.List<android.telephony.NetworkRegistrationState> getNetworkRegistrationStatesForTransportType(int);
+    field public static final int ROAMING_TYPE_DOMESTIC = 2; // 0x2
+    field public static final int ROAMING_TYPE_INTERNATIONAL = 3; // 0x3
+    field public static final int ROAMING_TYPE_NOT_ROAMING = 0; // 0x0
+    field public static final int ROAMING_TYPE_UNKNOWN = 1; // 0x1
   }
 
   public final class SmsManager {
@@ -5543,8 +5603,12 @@
     method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
     field public static final java.lang.String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
     field public static final java.lang.String ACTION_REFRESH_SUBSCRIPTION_PLANS = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
-    field public static final android.net.Uri ENHANCED_4G_ENABLED_CONTENT_URI;
+    field public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
+    field public static final android.net.Uri VT_ENABLED_CONTENT_URI;
     field public static final android.net.Uri WFC_ENABLED_CONTENT_URI;
+    field public static final android.net.Uri WFC_MODE_CONTENT_URI;
+    field public static final android.net.Uri WFC_ROAMING_ENABLED_CONTENT_URI;
+    field public static final android.net.Uri WFC_ROAMING_MODE_CONTENT_URI;
   }
 
   public final class SubscriptionPlan implements android.os.Parcelable {
@@ -5644,6 +5708,7 @@
     method public deprecated boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
     method public boolean needsOtaServiceProvisioning();
     method public boolean rebootRadio();
+    method public void requestCellInfoUpdate(android.os.WorkSource, java.util.concurrent.Executor, android.telephony.TelephonyManager.CellInfoCallback);
     method public boolean resetRadioConfig();
     method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
     method public void setCarrierDataEnabled(boolean);
@@ -5724,6 +5789,11 @@
     field public static final int SIM_ACTIVATION_STATE_UNKNOWN = 0; // 0x0
     field public static final int SIM_STATE_LOADED = 10; // 0xa
     field public static final int SIM_STATE_PRESENT = 11; // 0xb
+    field public static final int SRVCC_STATE_HANDOVER_CANCELED = 3; // 0x3
+    field public static final int SRVCC_STATE_HANDOVER_COMPLETED = 1; // 0x1
+    field public static final int SRVCC_STATE_HANDOVER_FAILED = 2; // 0x2
+    field public static final int SRVCC_STATE_HANDOVER_NONE = -1; // 0xffffffff
+    field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0
   }
 
   public final class UiccAccessRule implements android.os.Parcelable {
@@ -5903,6 +5973,7 @@
     field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2
     field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1
     field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4
+    field public static final int RESULT_CALLER_NOT_ALLOWED = -3; // 0xfffffffd
     field public static final int RESULT_EUICC_NOT_FOUND = -2; // 0xfffffffe
     field public static final int RESULT_OK = 0; // 0x0
     field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff
@@ -6027,6 +6098,7 @@
     method public void setCallExtra(java.lang.String, java.lang.String);
     method public void setCallExtraBoolean(java.lang.String, boolean);
     method public void setCallExtraInt(java.lang.String, int);
+    method public void setCallRestrictCause(int);
     method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
     method public void updateCallType(android.telephony.ims.ImsCallProfile);
     method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
@@ -6544,6 +6616,22 @@
     method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
   }
 
+  public class ProvisioningManager {
+    method public static android.telephony.ims.ProvisioningManager createForSubscriptionId(android.content.Context, int);
+    method public int getProvisioningIntValue(int);
+    method public java.lang.String getProvisioningStringValue(int);
+    method public void registerProvisioningChangedCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.Callback);
+    method public int setProvisioningIntValue(int, int);
+    method public int setProvisioningStringValue(int, java.lang.String);
+    method public void unregisterProvisioningChangedCallback(android.telephony.ims.ProvisioningManager.Callback);
+  }
+
+  public static class ProvisioningManager.Callback {
+    ctor public ProvisioningManager.Callback();
+    method public void onProvisioningIntChanged(int, int);
+    method public void onProvisioningStringChanged(int, java.lang.String);
+  }
+
 }
 
 package android.telephony.ims.feature {
@@ -6953,8 +7041,8 @@
     field public static final int TYPE_ACTIVITY_RESUMED = 2; // 0x2
     field public static final int TYPE_ACTIVITY_STARTED = 1; // 0x1
     field public static final int TYPE_ACTIVITY_STOPPED = 4; // 0x4
-    field public static final int TYPE_VIEW_ADDED = 5; // 0x5
-    field public static final int TYPE_VIEW_REMOVED = 6; // 0x6
+    field public static final int TYPE_VIEW_APPEARED = 5; // 0x5
+    field public static final int TYPE_VIEW_DISAPPEARED = 6; // 0x6
     field public static final int TYPE_VIEW_TEXT_CHANGED = 7; // 0x7
   }
 
@@ -7354,6 +7442,7 @@
     method public default void onMovedToDisplay(int, android.content.res.Configuration);
     method public abstract void onOverScrolled(int, int, boolean, boolean);
     method public default void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
+    method public default boolean onProvideContentCaptureStructure(android.view.ViewStructure, int);
     method public abstract void onProvideVirtualStructure(android.view.ViewStructure);
     method public abstract void onScrollChanged(int, int, int, int);
     method public abstract void onSizeChanged(int, int, int, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 604eebd..5531014 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -25,6 +25,10 @@
 
 package android.app {
 
+  public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+    method public void onMovedToDisplay(int, android.content.res.Configuration);
+  }
+
   public class ActivityManager {
     method public void addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int);
     method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
@@ -208,10 +212,12 @@
     method public int getActivityType();
     method public android.graphics.Rect getAppBounds();
     method public android.graphics.Rect getBounds();
+    method public int getRotation();
     method public int getWindowingMode();
     method public void setActivityType(int);
     method public void setAppBounds(android.graphics.Rect);
     method public void setBounds(android.graphics.Rect);
+    method public void setRotation(int);
     method public void setTo(android.app.WindowConfiguration);
     method public void setWindowingMode(int);
     method public void writeToParcel(android.os.Parcel, int);
@@ -220,6 +226,7 @@
     field public static final int ACTIVITY_TYPE_RECENTS = 3; // 0x3
     field public static final int ACTIVITY_TYPE_STANDARD = 1; // 0x1
     field public static final int ACTIVITY_TYPE_UNDEFINED = 0; // 0x0
+    field public static final int ROTATION_UNDEFINED = -1; // 0xffffffff
     field public static final int WINDOWING_MODE_FREEFORM = 5; // 0x5
     field public static final int WINDOWING_MODE_FULLSCREEN = 1; // 0x1
     field public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY = 4; // 0x4
@@ -707,6 +714,7 @@
 
   public class Environment {
     method public static java.io.File buildPath(java.io.File, java.lang.String...);
+    method public static java.io.File getProductDirectory();
     method public static java.io.File getStorageDirectory();
   }
 
@@ -736,7 +744,11 @@
   }
 
   public final class PowerManager {
+    method public int getPowerSaveMode();
+    method public boolean setDynamicPowerSavings(boolean, int);
     method public boolean setPowerSaveMode(boolean);
+    field public static final int POWER_SAVER_MODE_DYNAMIC = 1; // 0x1
+    field public static final int POWER_SAVER_MODE_PERCENTAGE = 0; // 0x0
   }
 
   public class Process {
@@ -973,6 +985,9 @@
 
   public static final class Settings.Global extends android.provider.Settings.NameValueTable {
     field public static final java.lang.String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
+    field public static final java.lang.String AUTOMATIC_POWER_SAVER_MODE = "automatic_power_saver_mode";
+    field public static final java.lang.String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold";
+    field public static final java.lang.String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
     field public static final java.lang.String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
     field public static final java.lang.String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
     field public static final java.lang.String LOW_POWER_MODE = "low_power";
@@ -1588,7 +1603,8 @@
 
   public class KeyEvent extends android.view.InputEvent implements android.os.Parcelable {
     method public static java.lang.String actionToString(int);
-    field public static final int LAST_KEYCODE = 285; // 0x11d
+    method public final void setDisplayId(int);
+    field public static final int LAST_KEYCODE = 288; // 0x120
   }
 
   public final class KeyboardShortcutGroup implements android.os.Parcelable {
@@ -1633,6 +1649,12 @@
     method public boolean unregisterFrameCommitCallback(java.lang.Runnable);
   }
 
+  public abstract interface WindowManager implements android.view.ViewManager {
+    method public default void setShouldShowIme(int, boolean);
+    method public default void setShouldShowSystemDecors(int, boolean);
+    method public default void setShouldShowWithInsecureKeyguard(int, boolean);
+  }
+
   public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
     field public static final int ACCESSIBILITY_TITLE_CHANGED = 33554432; // 0x2000000
     field public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 64; // 0x40
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index 33c274e..00c49e3 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -138,7 +138,8 @@
   std::stringstream stream;
   for (auto iter = interesting_apks.cbegin(); iter != interesting_apks.cend(); ++iter) {
     const std::string idmap_path = Idmap::CanonicalIdmapPathFor(output_directory, *iter);
-    if (!Verify(std::vector<std::string>({"--idmap-path", idmap_path}), out_error) &&
+    std::stringstream dev_null;
+    if (!Verify(std::vector<std::string>({"--idmap-path", idmap_path}), dev_null) &&
         !Create(std::vector<std::string>({
                     "--target-apk-path",
                     target_apk_path,
diff --git a/cmds/screencap/Android.bp b/cmds/screencap/Android.bp
new file mode 100644
index 0000000..248c675
--- /dev/null
+++ b/cmds/screencap/Android.bp
@@ -0,0 +1,21 @@
+cc_binary {
+    name: "screencap",
+
+    srcs: ["screencap.cpp"],
+
+    shared_libs: [
+        "libcutils",
+        "libutils",
+        "libbinder",
+        "libhwui",
+        "libui",
+        "libgui",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+}
diff --git a/cmds/screencap/Android.mk b/cmds/screencap/Android.mk
deleted file mode 100644
index 72e3c56..0000000
--- a/cmds/screencap/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    screencap.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libutils \
-    libbinder \
-    libhwui \
-    libui \
-    libgui
-
-LOCAL_MODULE:= screencap
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index 09343f1..783c8c4 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -101,6 +101,8 @@
             runFstrim();
         } else if ("set-virtual-disk".equals(op)) {
             runSetVirtualDisk();
+        } else if ("set-isolated-storage".equals(op)) {
+            runIsolatedStorage();
         } else {
             throw new IllegalArgumentException();
         }
@@ -125,6 +127,8 @@
             filterType = VolumeInfo.TYPE_PRIVATE;
         } else if ("emulated".equals(filter)) {
             filterType = VolumeInfo.TYPE_EMULATED;
+        } else if ("stub".equals(filter)) {
+            filterType = VolumeInfo.TYPE_STUB;
         } else {
             filterType = -1;
         }
@@ -278,6 +282,20 @@
                 StorageManager.DEBUG_VIRTUAL_DISK);
     }
 
+    public void runIsolatedStorage() throws RemoteException {
+        final boolean enableIsolatedStorage = Boolean.parseBoolean(nextArg());
+        // Toggling isolated-storage state will result in a device reboot. So to avoid this command
+        // from erroring out (DeadSystemException), call setDebugFlags() in a separate thread.
+        new Thread(() -> {
+            try {
+                mSm.setDebugFlags(enableIsolatedStorage ? StorageManager.DEBUG_ISOLATED_STORAGE : 0,
+                        StorageManager.DEBUG_ISOLATED_STORAGE);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Encountered an error!", e);
+            }
+        }).start();
+    }
+
     public void runIdleMaint() throws RemoteException {
         final boolean im_run = "run".equals(nextArg());
         if (im_run) {
@@ -298,7 +316,7 @@
 
     private static int showUsage() {
         System.err.println("usage: sm list-disks [adoptable]");
-        System.err.println("       sm list-volumes [public|private|emulated|all]");
+        System.err.println("       sm list-volumes [public|private|emulated|stub|all]");
         System.err.println("       sm has-adoptable");
         System.err.println("       sm get-primary-storage-uuid");
         System.err.println("       sm set-force-adoptable [on|off|default]");
@@ -316,6 +334,8 @@
         System.err.println("");
         System.err.println("       sm set-emulate-fbe [true|false]");
         System.err.println("");
+        System.err.println("       sm set-isolated-storage [true|false]");
+        System.err.println("");
         return 1;
     }
 }
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 6547b3a..0114ff4 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -72,6 +72,7 @@
         "src/external/StatsPuller.cpp",
         "src/external/StatsCompanionServicePuller.cpp",
         "src/external/SubsystemSleepStatePuller.cpp",
+        "src/external/PowerStatsPuller.cpp",
         "src/external/ResourceHealthManagerPuller.cpp",
         "src/external/ResourceThermalManagerPuller.cpp",
         "src/external/StatsPullerManager.cpp",
@@ -134,6 +135,7 @@
         "android.hardware.health@2.0",
         "android.hardware.power@1.0",
         "android.hardware.power@1.1",
+        "android.hardware.power.stats@1.0",
         "android.hardware.thermal@1.0",
         "libpackagelistparser",
         "libsysutils",
@@ -205,10 +207,6 @@
     ],
 
     srcs: [
-        // atom_field_options.proto needs field_options.proto, but that is
-        // not included in libprotobuf-cpp-lite, so compile it here.
-        ":libprotobuf-internal-protos",
-
         "src/atom_field_options.proto",
         "src/atoms.proto",
         "src/stats_log.proto",
@@ -263,11 +261,11 @@
     ],
 
     proto: {
-        type: "lite",
+        type: "full",
         include_dirs: ["external/protobuf/src"],
     },
 
-    shared_libs: ["libprotobuf-cpp-lite"],
+    shared_libs: ["libprotobuf-cpp-full"],
 
 }
 
@@ -280,10 +278,6 @@
     defaults: ["statsd_defaults"],
 
     srcs: [
-        // atom_field_options.proto needs field_options.proto, but that is
-        // not included in libprotobuf-cpp-lite, so compile it here.
-        ":libprotobuf-internal-protos",
-
         "src/atom_field_options.proto",
         "src/atoms.proto",
         "src/stats_log.proto",
@@ -298,7 +292,7 @@
     ],
 
     proto: {
-        type: "lite",
+        type: "full",
         include_dirs: ["external/protobuf/src"],
     },
 
@@ -320,7 +314,7 @@
     shared_libs: [
         "libgtest_prod",
         "libstatslog",
-        "libprotobuf-cpp-lite",
+        "libprotobuf-cpp-full",
     ],
 }
 
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index fc1a61c..80ed807 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -18,6 +18,7 @@
 #include "Log.h"
 #include "FieldValue.h"
 #include "HashableDimensionKey.h"
+#include "math.h"
 
 namespace android {
 namespace os {
@@ -174,6 +175,25 @@
     }
 }
 
+bool Value::isZero() const {
+    switch (type) {
+        case INT:
+            return int_value == 0;
+        case LONG:
+            return long_value == 0;
+        case FLOAT:
+            return fabs(float_value) <= std::numeric_limits<float>::epsilon();
+        case DOUBLE:
+            return fabs(double_value) <= std::numeric_limits<double>::epsilon();
+        case STRING:
+            return str_value.size() == 0;
+        case STORAGE:
+            return storage_value.size() == 0;
+        default:
+            return false;
+    }
+}
+
 bool Value::operator==(const Value& that) const {
     if (type != that.getType()) return false;
 
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index 77163f9..a5d00ac 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -331,6 +331,8 @@
 
     std::string toString() const;
 
+    bool isZero() const;
+
     Type getType() const {
         return type;
     }
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 12e2560a..a981997 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -71,6 +71,9 @@
 
 #define STATS_DATA_DIR "/data/misc/stats-data"
 
+// Cool down period for writing data to disk to avoid overwriting files.
+#define WRITE_DATA_COOL_DOWN_SEC 5
+
 StatsLogProcessor::StatsLogProcessor(const sp<UidMap>& uidMap,
                                      const sp<StatsPullerManager>& pullerManager,
                                      const sp<AlarmMonitor>& anomalyAlarmMonitor,
@@ -272,26 +275,25 @@
 }
 
 /*
- * onDumpReport dumps serialized ConfigMetricsReportList into outData.
+ * onDumpReport dumps serialized ConfigMetricsReportList into proto.
  */
 void StatsLogProcessor::onDumpReport(const ConfigKey& key, const int64_t dumpTimeStampNs,
                                      const bool include_current_partial_bucket,
+                                     const bool erase_data,
                                      const DumpReportReason dumpReportReason,
-                                     vector<uint8_t>* outData) {
+                                     ProtoOutputStream* proto) {
     std::lock_guard<std::mutex> lock(mMetricsMutex);
 
-    ProtoOutputStream proto;
-
     // Start of ConfigKey.
-    uint64_t configKeyToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_CONFIG_KEY);
-    proto.write(FIELD_TYPE_INT32 | FIELD_ID_UID, key.GetUid());
-    proto.write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)key.GetId());
-    proto.end(configKeyToken);
+    uint64_t configKeyToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_ID_CONFIG_KEY);
+    proto->write(FIELD_TYPE_INT32 | FIELD_ID_UID, key.GetUid());
+    proto->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)key.GetId());
+    proto->end(configKeyToken);
     // End of ConfigKey.
 
     // Then, check stats-data directory to see there's any file containing
     // ConfigMetricsReport from previous shutdowns to concatenate to reports.
-    StorageManager::appendConfigMetricsReport(key, &proto);
+    StorageManager::appendConfigMetricsReport(key, proto);
 
     auto it = mMetricsManagers.find(key);
     if (it != mMetricsManagers.end()) {
@@ -301,14 +303,27 @@
 
         // Start of ConfigMetricsReport (reports).
         uint64_t reportsToken =
-                proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);
+                proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS);
         onConfigMetricsReportLocked(key, dumpTimeStampNs, include_current_partial_bucket,
-                                    dumpReportReason, &proto);
-        proto.end(reportsToken);
+                                    erase_data, dumpReportReason, proto);
+        proto->end(reportsToken);
         // End of ConfigMetricsReport (reports).
     } else {
         ALOGW("Config source %s does not exist", key.ToString().c_str());
     }
+}
+
+/*
+ * onDumpReport dumps serialized ConfigMetricsReportList into outData.
+ */
+void StatsLogProcessor::onDumpReport(const ConfigKey& key, const int64_t dumpTimeStampNs,
+                                     const bool include_current_partial_bucket,
+                                     const bool erase_data,
+                                     const DumpReportReason dumpReportReason,
+                                     vector<uint8_t>* outData) {
+    ProtoOutputStream proto;
+    onDumpReport(key, dumpTimeStampNs, include_current_partial_bucket, erase_data,
+                 dumpReportReason, &proto);
 
     if (outData != nullptr) {
         outData->clear();
@@ -332,6 +347,7 @@
 void StatsLogProcessor::onConfigMetricsReportLocked(const ConfigKey& key,
                                                     const int64_t dumpTimeStampNs,
                                                     const bool include_current_partial_bucket,
+                                                    const bool erase_data,
                                                     const DumpReportReason dumpReportReason,
                                                     ProtoOutputStream* proto) {
     // We already checked whether key exists in mMetricsManagers in
@@ -348,17 +364,15 @@
     // First, fill in ConfigMetricsReport using current data on memory, which
     // starts from filling in StatsLogReport's.
     it->second->onDumpReport(dumpTimeStampNs, include_current_partial_bucket,
-                             &str_set, proto);
+                             erase_data, &str_set, proto);
 
     // Fill in UidMap if there is at least one metric to report.
     // This skips the uid map if it's an empty config.
     if (it->second->getNumMetrics() > 0) {
         uint64_t uidMapToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP);
-        if (it->second->hashStringInReport()) {
-            mUidMap->appendUidMap(dumpTimeStampNs, key, &str_set, proto);
-        } else {
-            mUidMap->appendUidMap(dumpTimeStampNs, key, nullptr, proto);
-        }
+        mUidMap->appendUidMap(
+                dumpTimeStampNs, key, it->second->hashStringInReport() ? &str_set : nullptr,
+                it->second->versionStringsInReport(), it->second->installerInReport(), proto);
         proto->end(uidMapToken);
     }
 
@@ -479,7 +493,7 @@
     }
     ProtoOutputStream proto;
     onConfigMetricsReportLocked(key, timestampNs, true /* include_current_partial_bucket*/,
-                                dumpReportReason, &proto);
+                                true /* erase_data */, dumpReportReason, &proto);
     string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_DATA_DIR,
          (long)getWallClockSec(), key.GetUid(), (long long)key.GetId());
     android::base::unique_fd fd(open(file_name.c_str(),
@@ -495,6 +509,16 @@
 
 void StatsLogProcessor::WriteDataToDiskLocked(const DumpReportReason dumpReportReason) {
     const int64_t timeNs = getElapsedRealtimeNs();
+    // Do not write to disk if we already have in the last few seconds.
+    // This is to avoid overwriting files that would have the same name if we
+    //   write twice in the same second.
+    if (static_cast<unsigned long long> (timeNs) <
+            mLastWriteTimeNs + WRITE_DATA_COOL_DOWN_SEC * NS_PER_SEC) {
+        ALOGI("Statsd skipping writing data to disk. Already wrote data in last %d seconds",
+                WRITE_DATA_COOL_DOWN_SEC);
+        return;
+    }
+    mLastWriteTimeNs = timeNs;
     for (auto& pair : mMetricsManagers) {
         WriteDataToDiskLocked(pair.first, timeNs, dumpReportReason);
     }
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 3e8b9b8..a5ce9b6 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -61,8 +61,11 @@
     size_t GetMetricsSize(const ConfigKey& key) const;
 
     void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs,
-                      const bool include_current_partial_bucket,
+                      const bool include_current_partial_bucket, const bool erase_data,
                       const DumpReportReason dumpReportReason, vector<uint8_t>* outData);
+    void onDumpReport(const ConfigKey& key, const int64_t dumpTimeNs,
+                      const bool include_current_partial_bucket, const bool erase_data,
+                      const DumpReportReason dumpReportReason, ProtoOutputStream* proto);
 
     /* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
     void onAnomalyAlarmFired(
@@ -141,6 +144,7 @@
 
     void onConfigMetricsReportLocked(const ConfigKey& key, const int64_t dumpTimeStampNs,
                                      const bool include_current_partial_bucket,
+                                     const bool erase_data,
                                      const DumpReportReason dumpReportReason,
                                      util::ProtoOutputStream* proto);
 
@@ -173,6 +177,9 @@
 
     long mLastPullerCacheClearTimeSec = 0;
 
+    // Last time we wrote data to disk.
+    int64_t mLastWriteTimeNs = 0;
+
 #ifdef VERY_VERBOSE_PRINTING
     bool mPrintAllLogs = false;
 #endif
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index ce28777..7fa05be 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -46,6 +46,8 @@
 using namespace android;
 
 using android::base::StringPrintf;
+using android::util::FIELD_COUNT_REPEATED;
+using android::util::FIELD_TYPE_MESSAGE;
 
 namespace android {
 namespace os {
@@ -58,6 +60,9 @@
 
 #define STATS_SERVICE_DIR "/data/misc/stats-service"
 
+// for StatsDataDumpProto
+const int FIELD_ID_REPORTS_LIST = 1;
+
 static binder::Status ok() {
     return binder::Status::ok();
 }
@@ -224,31 +229,48 @@
 }
 
 /**
- * Write debugging data about statsd.
+ * Write data from statsd.
+ * Format for statsdStats:  adb shell dumpsys stats --metadata [-v] [--proto]
+ * Format for data report:  adb shell dumpsys stats [anything other than --metadata] [--proto]
+ * Anything ending in --proto will be in proto format.
+ * Anything without --metadata as the first argument will be report information.
+ *     (bugreports call "adb shell dumpsys stats --dump-priority NORMAL -a --proto")
+ * TODO: Come up with a more robust method of enacting <serviceutils/PriorityDumper.h>.
  */
 status_t StatsService::dump(int fd, const Vector<String16>& args) {
     if (!checkCallingPermission(String16(kPermissionDump))) {
         return PERMISSION_DENIED;
     }
-
-    bool verbose = false;
-    bool proto = false;
-    if (args.size() > 0 && !args[0].compare(String16("-v"))) {
-        verbose = true;
+    int lastArg = args.size() - 1;
+    bool asProto = false;
+    if (lastArg >= 0 && !args[lastArg].compare(String16("--proto"))) { // last argument
+        asProto = true;
+        lastArg--;
     }
-    if (args.size() > 0 && !args[args.size()-1].compare(String16("--proto"))) {
-        proto = true;
+    if (args.size() > 0 && !args[0].compare(String16("--metadata"))) { // first argument
+        // Request is to dump statsd stats.
+        bool verbose = false;
+        if (lastArg >= 0 && !args[lastArg].compare(String16("-v"))) {
+            verbose = true;
+            lastArg--;
+        }
+        dumpStatsdStats(fd, verbose, asProto);
+    } else {
+        // Request is to dump statsd report data.
+        if (asProto) {
+            dumpIncidentSection(fd);
+        } else {
+            dprintf(fd, "Non-proto format of stats data dump not available; see proto version.\n");
+        }
     }
 
-    dump_impl(fd, verbose, proto);
-
     return NO_ERROR;
 }
 
 /**
  * Write debugging data about statsd in text or proto format.
  */
-void StatsService::dump_impl(int out, bool verbose, bool proto) {
+void StatsService::dumpStatsdStats(int out, bool verbose, bool proto) {
     if (proto) {
         vector<uint8_t> data;
         StatsdStats::getInstance().dumpStats(&data, false); // does not reset statsdStats.
@@ -262,6 +284,22 @@
 }
 
 /**
+ * Write stats report data in StatsDataDumpProto incident section format.
+ */
+void StatsService::dumpIncidentSection(int out) {
+    ProtoOutputStream proto;
+    for (const ConfigKey& configKey : mConfigManager->GetAllConfigKeys()) {
+        uint64_t reportsListToken =
+                proto.start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_REPORTS_LIST);
+        mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(),
+                                 true /* includeCurrentBucket */, false /* erase_data */,
+                                 ADB_DUMP, &proto);
+        proto.end(reportsListToken);
+        proto.flush(out);
+    }
+}
+
+/**
  * Implementation of the adb shell cmd stats command.
  */
 status_t StatsService::command(int in, int out, int err, Vector<String8>& args,
@@ -283,7 +321,7 @@
         }
 
         if (!args[0].compare(String8("dump-report"))) {
-            return cmd_dump_report(out, err, args);
+            return cmd_dump_report(out, args);
         }
 
         if (!args[0].compare(String8("pull-source")) && args.size() > 1) {
@@ -546,7 +584,7 @@
     return UNKNOWN_ERROR;
 }
 
-status_t StatsService::cmd_dump_report(int out, int err, const Vector<String8>& args) {
+status_t StatsService::cmd_dump_report(int out, const Vector<String8>& args) {
     if (mProcessor != nullptr) {
         int argCount = args.size();
         bool good = false;
@@ -589,14 +627,13 @@
         if (good) {
             vector<uint8_t> data;
             mProcessor->onDumpReport(ConfigKey(uid, StrToInt64(name)), getElapsedRealtimeNs(),
-                                     includeCurrentBucket, ADB_DUMP, &data);
+                                     includeCurrentBucket, true /* erase_data */, ADB_DUMP, &data);
             if (proto) {
                 for (size_t i = 0; i < data.size(); i ++) {
                     dprintf(out, "%c", data[i]);
                 }
             } else {
-                dprintf(out, "Dump report for Config [%d,%s]\n", uid, name.c_str());
-                dprintf(out, "See the StatsLogReport in logcat...\n");
+                dprintf(out, "Non-proto stats data dump not currently supported.\n");
             }
             return android::OK;
         } else {
@@ -750,21 +787,24 @@
 }
 
 Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
-                                      const vector<String16>& app) {
+                                      const vector<String16>& version_string,
+                                      const vector<String16>& app,
+                                      const vector<String16>& installer) {
     ENFORCE_UID(AID_SYSTEM);
 
     VLOG("StatsService::informAllUidData was called");
-    mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, app);
+    mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, version_string, app, installer);
     VLOG("StatsService::informAllUidData succeeded");
 
     return Status::ok();
 }
 
-Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version) {
+Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version,
+                                      const String16& version_string, const String16& installer) {
     ENFORCE_UID(AID_SYSTEM);
 
     VLOG("StatsService::informOnePackage was called");
-    mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version);
+    mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version, version_string, installer);
     return Status::ok();
 }
 
@@ -888,7 +928,7 @@
     VLOG("StatsService::getData with Pid %i, Uid %i", ipc->getCallingPid(), ipc->getCallingUid());
     ConfigKey configKey(ipc->getCallingUid(), key);
     mProcessor->onDumpReport(configKey, getElapsedRealtimeNs(), false /* include_current_bucket*/,
-                             GET_DATA_CALLED, output);
+                             true /* erase_data */, GET_DATA_CALLED, output);
     return Status::ok();
 }
 
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index cbf3429..cd4d601 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -73,8 +73,10 @@
     virtual Status informAlarmForSubscriberTriggeringFired();
 
     virtual Status informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
-                                    const vector<String16>& app);
-    virtual Status informOnePackage(const String16& app, int32_t uid, int64_t version);
+                                    const vector<String16>& version_string,
+                                    const vector<String16>& app, const vector<String16>& installer);
+    virtual Status informOnePackage(const String16& app, int32_t uid, int64_t version,
+                                    const String16& version_string, const String16& installer);
     virtual Status informOnePackageRemoved(const String16& app, int32_t uid);
     virtual Status informDeviceShutdown();
 
@@ -213,9 +215,14 @@
                                          uint32_t serial);
 
     /**
-     * Text or proto output of dumpsys.
+     * Proto output of statsd report data dumpsys, wrapped in a StatsDataDumpProto.
      */
-    void dump_impl(int outFd, bool verbose, bool proto);
+    void dumpIncidentSection(int outFd);
+
+    /**
+     * Text or proto output of statsdStats dumpsys.
+     */
+    void dumpStatsdStats(int outFd, bool verbose, bool proto);
 
     /**
      * Print usage information for the commands
@@ -240,7 +247,7 @@
     /**
      * Print the event log.
      */
-    status_t cmd_dump_report(int outFd, int err, const Vector<String8>& args);
+    status_t cmd_dump_report(int outFd, const Vector<String8>& args);
 
     /**
      * Print the mapping of uids to package names.
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index 13ab844..ee111cd 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -24,7 +24,6 @@
 #include "subscriber/IncidentdReporter.h"
 #include "subscriber/SubscriberReporter.h"
 
-#include <inttypes.h>
 #include <statslog.h>
 #include <time.h>
 
@@ -224,7 +223,7 @@
     }
 
     if (!mSubscriptions.empty()) {
-        ALOGI("An anomaly (%" PRId64 ") %s has occurred! Informing subscribers.",
+        ALOGI("An anomaly (%lld) %s has occurred! Informing subscribers.",
                 mAlert.id(), key.toString().c_str());
         informSubscribers(key);
     } else {
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 5620184..9757f32 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -27,6 +27,7 @@
 import "frameworks/base/core/proto/android/bluetooth/enums.proto";
 import "frameworks/base/core/proto/android/os/enums.proto";
 import "frameworks/base/core/proto/android/server/enums.proto";
+import "frameworks/base/core/proto/android/server/location/enums.proto";
 import "frameworks/base/core/proto/android/service/procstats_enum.proto";
 import "frameworks/base/core/proto/android/stats/enums.proto";
 import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
@@ -118,7 +119,7 @@
         ResourceConfigurationChanged resource_configuration_changed = 66;
         BluetoothEnabledStateChanged bluetooth_enabled_state_changed = 67;
         BluetoothConnectionStateChanged bluetooth_connection_state_changed = 68;
-        // 69 is blank but need not be.
+        GpsSignalQualityChanged gps_signal_quality_changed = 69;
         UsbConnectorStateChanged usb_connector_state_changed = 70;
         SpeakerImpedanceReported speaker_impedance_reported = 71;
         HardwareFailed hardware_failed = 72;
@@ -147,6 +148,14 @@
         PhoneStateChanged phone_state_changed = 95;
         UserRestrictionChanged user_restriction_changed = 96;
         SettingsUIChanged settings_ui_changed = 97;
+        ConnectivityStateChanged connectivity_state_changed = 98;
+        // TODO: service state change is very noisy shortly after boot, as well
+        // as at other transitions - coming out of doze, device plugged in, etc.
+        // Consider removing this if it becomes a problem
+        ServiceStateChanged service_state_changed = 99;
+        ServiceLaunchReported service_launch_reported = 100;
+        PhenotypeFlagStateChanged phenotype_flag_state_changed = 101;
+        BinaryPushStateChanged binary_push_state_changed = 102;
     }
 
     // Pulled events will start at field 10000.
@@ -190,6 +199,10 @@
         ProcessCpuTime process_cpu_time = 10035;
         NativeProcessMemoryState native_process_memory_state = 10036;
         CpuTimePerThreadFreq cpu_time_per_thread_freq = 10037;
+        OnDevicePowerMeasurement on_device_power_measurement = 10038;
+        DeviceCalculatedPowerUse device_calculated_power_use = 10039;
+        DeviceCalculatedPowerBlameUid device_calculated_power_blame_uid = 10040;
+        DeviceCalculatedPowerBlameOther device_calculated_power_blame_other = 10041;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -484,7 +497,6 @@
     optional State state = 3;
 }
 
-
 /**
  * Logs when GPS state changes.
  *
@@ -501,6 +513,16 @@
     optional State state = 2;
 }
 
+/**
+ * Logs when GPS signal quality.
+ *
+ * Logged from:
+ *   /frameworks/base/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+ */
+message GpsSignalQualityChanged {
+    optional android.server.location.GpsSignalQualityEnum level = 1;
+}
+
 
 /**
  * Logs when a sync manager sync state changes.
@@ -2128,6 +2150,94 @@
     optional int64 visible_millis = 16;
 }
 
+/*
+ * Logs when a flag flip state changes.
+ * Logged in P/h.
+ */
+message PhenotypeFlagStateChanged {
+    // Mendel configuration name.
+    optional string mendel_config_name = 1;
+    // State
+    enum State {
+        STATE_UNKNOWN = 0;
+        COMMITTED = 1;
+    }
+    optional State state = 2;
+}
+
+/*
+ * Logs when a binary push state changes.
+ * Logged in Play store
+ */
+message BinaryPushStateChanged {
+    // Binary package name.
+    optional string binary_name = 1;
+    // Version code.
+    optional int64 version = 2;
+    // State
+    enum State {
+        STATE_UNKNOWN = 0;
+        DOWNLOAD_START = 1;
+        DOWNLOAD_DONE = 2;
+        INSTALL_START = 3;
+        INSTALL_DONE = 4;
+        REBOOT_START = 5;
+        REBOOT_DONE = 6;
+    }
+    optional State state = 3;
+}
+
+/*
+ * Logs when a connection becomes available and lost.
+ * Logged in StatsCompanionService.java
+ */
+message ConnectivityStateChanged {
+  // Id of the network.
+  optional int32 net_id = 1;
+
+  enum State {
+    UNKNOWN = 0;
+    CONNECTED = 1;
+    DISCONNECTED = 2;
+  }
+  // Connected state of a network.
+  optional State state = 2;
+}
+
+/**
+ * Logs when a service starts and stops.
+ * Logged from:
+ *   services/core/java/com/android/server/am/ActiveServices.java
+ */
+message ServiceStateChanged {
+
+    optional int32 uid = 1 [(is_uid) = true];
+
+    optional string package_name = 2;
+
+    optional string service_name = 3;
+
+    enum State {
+        START = 1;
+        STOP = 2;
+    }
+
+    optional State state = 4;
+}
+
+/**
+ * Logs when a service is launched.
+ * Logged from:
+ *   services/core/java/com/android/server/am/ActiveServices.java
+ */
+message ServiceLaunchReported {
+
+    optional int32 uid = 1 [(is_uid) = true];
+
+    optional string package_name = 2;
+
+    optional string service_name = 3;
+}
 
 //////////////////////////////////////////////////////////////////////
 // Pulled atoms below this line //
@@ -2262,6 +2372,27 @@
 }
 
 /**
+ * Pulls on-device power measurement information.
+ * Data defined by hardware/interfaces/power/stats/1.0/types.hal.
+ * Pulled from:
+ *   frameworks/base/cmds/statsd/src/external/PowerStatsPuller.cpp
+ */
+message OnDevicePowerMeasurement {
+    // Name of the subsystem (to which the rail belongs).
+    optional string subsystem_name = 1;
+
+    // Rail name. The rail lies within the subsystem.
+    optional string rail_name = 2;
+
+    // Time (in ms since boot) at which the rail energy value was measured.
+    // This may differ slightly from the time that statsd logs this information.
+    optional uint64 measurement_timestamp_millis = 3;
+
+    // Accumulated energy used via the rail since device boot in uWs.
+    optional uint64 energy_microwatt_secs = 4;
+}
+
+/**
  * Pulls Cpu time per frequency.
  * Pulls the time the cpu spend on the frequency index. Frequency index
  * starts from highest to lowest. The value should be monotonically
@@ -3159,3 +3290,63 @@
     // Time spent in frequency in milliseconds, since thread start.
     optional uint32 time_millis = 7;
 }
+
+/**
+ * Pulls on-device BatteryStats power use calculations for the overall device.
+ */
+message DeviceCalculatedPowerUse {
+    // Power used by the device in mAh, as computed by BatteryStats, since BatteryStats last reset
+    // (i.e. roughly since device was last significantly charged).
+    // Currently, this is BatteryStatsHelper.getComputedPower() (not getTotalPower()).
+    optional float computed_power_milli_amp_hours = 1;
+}
+
+/**
+ * Pulls on-device BatteryStats power use calculations broken down by uid.
+ * This atom should be complemented by DeviceCalculatedPowerBlameOther, which contains the power use
+ * that is attributed to non-uid items. They must all be included to get the total power use.
+ */
+message DeviceCalculatedPowerBlameUid {
+    // Uid being blamed. Note: isolated uids have already been mapped to host uid.
+    optional int32 uid = 1 [(is_uid) = true];
+
+    // Power used by this uid in mAh, as computed by BatteryStats, since BatteryStats last reset
+    // (i.e. roughly since device was last significantly charged).
+    optional float power_milli_amp_hours = 2;
+}
+
+/**
+ * Pulls on-device BatteryStats power use calculations that are not due to a uid, broken down by
+ * drain type.
+ * This atom should be complemented by DeviceCalculatedPowerBlameUid, which contains the blame that
+ * is attributed uids. They must all be included to get the total power use.
+ */
+message DeviceCalculatedPowerBlameOther {
+    // The type of item whose power use is being reported.
+    enum DrainType {
+        AMBIENT_DISPLAY = 0;
+        // reserved 1; reserved "APP"; // Logged instead in DeviceCalculatedPowerBlameUid.
+        BLUETOOTH = 2;
+        CAMERA = 3;
+        // Cell-standby
+        CELL = 4;
+        FLASHLIGHT = 5;
+        IDLE = 6;
+        MEMORY = 7;
+        // Amount that total computed drain exceeded the drain estimated using the
+        // battery level changes and capacity.
+        OVERCOUNTED = 8;
+        PHONE = 9;
+        SCREEN = 10;
+        // Amount that total computed drain was below the drain estimated using the
+        // battery level changes and capacity.
+        UNACCOUNTED = 11;
+        // reserved 12; reserved "USER"; // Entire drain for a user. This is NOT supported.
+        WIFI = 13;
+    }
+    optional DrainType drain_type = 1;
+
+    // Power used by this item in mAh, as computed by BatteryStats, since BatteryStats last reset
+    // (i.e. roughly since device was last significantly charged).
+    optional float power_milli_amp_hours = 2;
+}
\ No newline at end of file
diff --git a/cmds/statsd/src/external/PowerStatsPuller.cpp b/cmds/statsd/src/external/PowerStatsPuller.cpp
new file mode 100644
index 0000000..71e5fa0
--- /dev/null
+++ b/cmds/statsd/src/external/PowerStatsPuller.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define DEBUG false  // STOPSHIP if true
+#include "Log.h"
+
+#include <android/hardware/power/stats/1.0/IPowerStats.h>
+
+#include <vector>
+
+#include "PowerStatsPuller.h"
+#include "stats_log_util.h"
+
+using android::hardware::hidl_vec;
+using android::hardware::power::stats::V1_0::IPowerStats;
+using android::hardware::power::stats::V1_0::EnergyData;
+using android::hardware::power::stats::V1_0::RailInfo;
+using android::hardware::power::stats::V1_0::Status;
+using android::hardware::Return;
+using android::hardware::Void;
+
+using std::make_shared;
+using std::shared_ptr;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+sp<android::hardware::power::stats::V1_0::IPowerStats> gPowerStatsHal = nullptr;
+std::mutex gPowerStatsHalMutex;
+bool gPowerStatsExist = true; // Initialized to ensure making a first attempt.
+std::vector<RailInfo> gRailInfo;
+
+bool getPowerStatsHal() {
+    if (gPowerStatsHal == nullptr && gPowerStatsExist) {
+        gPowerStatsHal = android::hardware::power::stats::V1_0::IPowerStats::getService();
+        if (gPowerStatsHal == nullptr) {
+            ALOGW("Couldn't load power.stats HAL service");
+            gPowerStatsExist = false;
+        }
+    }
+    return gPowerStatsHal != nullptr;
+}
+
+PowerStatsPuller::PowerStatsPuller() : StatsPuller(android::util::ON_DEVICE_POWER_MEASUREMENT) {
+}
+
+bool PowerStatsPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+    std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
+
+    if (!getPowerStatsHal()) {
+        ALOGE("power.stats Hal not loaded");
+        return false;
+    }
+
+    int64_t wallClockTimestampNs = getWallClockNs();
+    int64_t elapsedTimestampNs = getElapsedRealtimeNs();
+
+    data->clear();
+
+    // Pull getRailInfo if necessary
+    if (gRailInfo.empty()) {
+        bool resultSuccess = true;
+        Return<void> ret = gPowerStatsHal->getRailInfo(
+                [&resultSuccess](const hidl_vec<RailInfo> &list, Status status) {
+                    resultSuccess = (status == Status::SUCCESS || status == Status::NOT_SUPPORTED);
+                    if (status != Status::SUCCESS) return;
+
+                    gRailInfo.reserve(list.size());
+                    for (size_t i = 0; i < list.size(); ++i) {
+                        gRailInfo.push_back(list[i]);
+                    }
+                });
+        if (!resultSuccess || !ret.isOk()) {
+            ALOGE("power.stats getRailInfo() failed. Description: %s", ret.description().c_str());
+            gPowerStatsHal = nullptr;
+            return false;
+        }
+        // If SUCCESS but empty, or if NOT_SUPPORTED, then never try again.
+        if (gRailInfo.empty()) {
+            ALOGE("power.stats has no rail information");
+            gPowerStatsExist = false; // No rail info, so never try again.
+            return false;
+        }
+    }
+
+    // Pull getEnergyData and write the data out
+    const hidl_vec<uint32_t> desiredRailIndices; // Empty vector indicates we want all.
+    bool resultSuccess = true;
+    Return<void> ret = gPowerStatsHal->getEnergyData(desiredRailIndices,
+                [&data, wallClockTimestampNs, elapsedTimestampNs, &resultSuccess]
+                (hidl_vec<EnergyData> energyDataList, Status status) {
+                    resultSuccess = (status == Status::SUCCESS);
+                    if (!resultSuccess) return;
+
+                    for (size_t i = 0; i < energyDataList.size(); i++) {
+                        const EnergyData& energyData = energyDataList[i];
+
+                        if (energyData.index >= gRailInfo.size()) {
+                            ALOGE("power.stats getEnergyData() returned an invalid rail index %u.",
+                                    energyData.index);
+                            resultSuccess = false;
+                            return;
+                        }
+                        const RailInfo& rail = gRailInfo[energyData.index];
+
+                        auto ptr = make_shared<LogEvent>(android::util::ON_DEVICE_POWER_MEASUREMENT,
+                              wallClockTimestampNs, elapsedTimestampNs);
+                        ptr->write(rail.subsysName);
+                        ptr->write(rail.railName);
+                        ptr->write(energyData.timestamp);
+                        ptr->write(energyData.energy);
+                        ptr->init();
+                        data->push_back(ptr);
+
+                        VLOG("power.stat: %s.%s: %llu, %llu",
+                             rail.subsysName.c_str(),
+                             rail.railName.c_str(),
+                             (unsigned long long)energyData.timestamp,
+                             (unsigned long long)energyData.energy);
+                    }
+                });
+    if (!resultSuccess || !ret.isOk()) {
+        ALOGE("power.stats getEnergyData() failed. Description: %s", ret.description().c_str());
+        gPowerStatsHal = nullptr;
+        return false;
+    }
+    return true;
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/cmds/statsd/src/external/PowerStatsPuller.h
similarity index 63%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to cmds/statsd/src/external/PowerStatsPuller.h
index ede8695..dd5ff8f 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/cmds/statsd/src/external/PowerStatsPuller.h
@@ -14,8 +14,23 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+#pragma once
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+#include "StatsPuller.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+/**
+ * Reads hal for power.stats
+ */
+class PowerStatsPuller : public StatsPuller {
+public:
+    PowerStatsPuller();
+    bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
+};
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 9633980..0e131cb 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -26,6 +26,7 @@
 #include "../logd/LogEvent.h"
 #include "../stats_log_util.h"
 #include "../statscompanion_util.h"
+#include "PowerStatsPuller.h"
 #include "ResourceHealthManagerPuller.h"
 #include "ResourceThermalManagerPuller.h"
 #include "StatsCompanionServicePuller.h"
@@ -86,6 +87,9 @@
         // subsystem_sleep_state
         {android::util::SUBSYSTEM_SLEEP_STATE,
          {{}, {}, 1 * NS_PER_SEC, new SubsystemSleepStatePuller()}},
+        // on_device_power_measurement
+        {android::util::ON_DEVICE_POWER_MEASUREMENT,
+         {{}, {}, 1 * NS_PER_SEC, new PowerStatsPuller()}},
         // cpu_time_per_freq
         {android::util::CPU_TIME_PER_FREQ,
          {{3},
@@ -239,6 +243,20 @@
           {2, 3, 4, 5, 6},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}},
+        // DeviceCalculatedPowerUse.
+        {android::util::DEVICE_CALCULATED_POWER_USE,
+         {{}, {}, 1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_USE)}},
+        // DeviceCalculatedPowerBlameUid.
+        {android::util::DEVICE_CALCULATED_POWER_BLAME_UID,
+         {{}, {}, // BatteryStats already merged isolated with host ids so it's unnecessary here.
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_UID)}},
+        // DeviceCalculatedPowerBlameOther.
+        {android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER,
+         {{}, {},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER)}},
 };
 
 StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index d2919c5..6617689 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -47,11 +47,9 @@
 const int FIELD_ID_ATOM_STATS = 7;
 const int FIELD_ID_UIDMAP_STATS = 8;
 const int FIELD_ID_ANOMALY_ALARM_STATS = 9;
-// const int FIELD_ID_PULLED_ATOM_STATS = 10; // The proto is written in stats_log_util.cpp
-const int FIELD_ID_LOGGER_ERROR_STATS = 11;
 const int FIELD_ID_PERIODIC_ALARM_STATS = 12;
-// const int FIELD_ID_LOG_LOSS_STATS = 14;
 const int FIELD_ID_SYSTEM_SERVER_RESTART = 15;
+const int FIELD_ID_LOGGER_ERROR_STATS = 16;
 
 const int FIELD_ID_ATOM_STATS_TAG = 1;
 const int FIELD_ID_ATOM_STATS_COUNT = 2;
@@ -59,8 +57,9 @@
 const int FIELD_ID_ANOMALY_ALARMS_REGISTERED = 1;
 const int FIELD_ID_PERIODIC_ALARMS_REGISTERED = 1;
 
-const int FIELD_ID_LOGGER_STATS_TIME = 1;
-const int FIELD_ID_LOGGER_STATS_ERROR_CODE = 2;
+const int FIELD_ID_LOG_LOSS_STATS_TIME = 1;
+const int FIELD_ID_LOG_LOSS_STATS_COUNT = 2;
+const int FIELD_ID_LOG_LOSS_STATS_ERROR = 3;
 
 const int FIELD_ID_CONFIG_STATS_UID = 1;
 const int FIELD_ID_CONFIG_STATS_ID = 2;
@@ -181,12 +180,12 @@
     noteConfigResetInternalLocked(key);
 }
 
-void StatsdStats::noteLogLost(int32_t wallClockTimeSec, int32_t count) {
+void StatsdStats::noteLogLost(int32_t wallClockTimeSec, int32_t count, int32_t lastError) {
     lock_guard<std::mutex> lock(mLock);
     if (mLogLossStats.size() == kMaxLoggerErrors) {
         mLogLossStats.pop_front();
     }
-    mLogLossStats.push_back(std::make_pair(wallClockTimeSec, count));
+    mLogLossStats.emplace_back(wallClockTimeSec, count, lastError);
 }
 
 void StatsdStats::noteBroadcastSent(const ConfigKey& key) {
@@ -362,11 +361,17 @@
     lock_guard<std::mutex> lock(mLock);
     auto& pullStats = mPulledAtomStats[pullAtomId];
     pullStats.maxPullDelayNs = std::max(pullStats.maxPullDelayNs, pullDelayNs);
-    pullStats.avgPullDelayNs = (pullStats.avgPullDelayNs * pullStats.numPullDelay + pullDelayNs) /
-                               (pullStats.numPullDelay + 1);
+    pullStats.avgPullDelayNs =
+        (pullStats.avgPullDelayNs * pullStats.numPullDelay + pullDelayNs) /
+            (pullStats.numPullDelay + 1);
     pullStats.numPullDelay += 1;
 }
 
+void StatsdStats::notePullDataError(int pullAtomId) {
+    lock_guard<std::mutex> lock(mLock);
+    mPulledAtomStats[pullAtomId].dataError++;
+}
+
 void StatsdStats::noteAtomLogged(int atomId, int32_t timeSec) {
     lock_guard<std::mutex> lock(mLock);
 
@@ -422,6 +427,7 @@
         pullStats.second.avgPullDelayNs = 0;
         pullStats.second.maxPullDelayNs = 0;
         pullStats.second.numPullDelay = 0;
+        pullStats.second.dataError = 0;
     }
 }
 
@@ -530,11 +536,11 @@
         dprintf(out,
                 "Atom %d->(total pull)%ld, (pull from cache)%ld, (min pull interval)%ld, (average "
                 "pull time nanos)%lld, (max pull time nanos)%lld, (average pull delay nanos)%lld, "
-                "(max pull delay nanos)%lld\n",
+                "(max pull delay nanos)%lld, (data error)%ld\n",
                 (int)pair.first, (long)pair.second.totalPull, (long)pair.second.totalPullFromCache,
                 (long)pair.second.minPullIntervalSec, (long long)pair.second.avgPullTimeNs,
                 (long long)pair.second.maxPullTimeNs, (long long)pair.second.avgPullDelayNs,
-                (long long)pair.second.maxPullDelayNs);
+                (long long)pair.second.maxPullDelayNs, pair.second.dataError);
     }
 
     if (mAnomalyAlarmRegisteredStats > 0) {
@@ -557,8 +563,8 @@
     }
 
     for (const auto& loss : mLogLossStats) {
-        dprintf(out, "Log loss: %lld (wall clock sec) - %d (count)\n", (long long)loss.first,
-                loss.second);
+        dprintf(out, "Log loss: %lld (wall clock sec) - %d (count) %d (last error)\n",
+                (long long)loss.mWallClockSec, loss.mCount, loss.mLastError);
     }
 }
 
@@ -713,13 +719,11 @@
     proto.end(uidMapToken);
 
     for (const auto& error : mLogLossStats) {
-        // The logger error stats are not used anymore since we move away from logd.
-        // Temporarily use this field to log the log loss timestamp and count
-        // TODO(b/80538532) Add a dedicated field in stats_log for this.
         uint64_t token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_LOGGER_ERROR_STATS |
                                       FIELD_COUNT_REPEATED);
-        proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOGGER_STATS_TIME, error.first);
-        proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOGGER_STATS_ERROR_CODE, error.second);
+        proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_TIME, error.mWallClockSec);
+        proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_COUNT, error.mCount);
+        proto.write(FIELD_TYPE_INT32 | FIELD_ID_LOG_LOSS_STATS_ERROR, error.mLastError);
         proto.end(token);
     }
 
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 777d865..343709a 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -279,6 +279,11 @@
     void notePullFromCache(int pullAtomId);
 
     /*
+     * Notify data error for pulled atom.
+     */
+    void notePullDataError(int pullAtomId);
+
+    /*
      * Records time for actual pulling, not including those served from cache and not including
      * statsd processing delays.
      */
@@ -298,7 +303,7 @@
     /**
      * Records statsd skipped an event.
      */
-    void noteLogLost(int32_t wallClockTimeSec, int32_t count);
+    void noteLogLost(int32_t wallClockTimeSec, int32_t count, int lastError);
 
     /**
      * Reset the historical stats. Including all stats in icebox, and the tracked stats about
@@ -329,6 +334,7 @@
         int64_t avgPullDelayNs = 0;
         int64_t maxPullDelayNs = 0;
         long numPullDelay = 0;
+        long dataError = 0;
     } PulledAtomStats;
 
 private:
@@ -358,8 +364,18 @@
     // Maps PullAtomId to its stats. The size is capped by the puller atom counts.
     std::map<int, PulledAtomStats> mPulledAtomStats;
 
+    struct LogLossStats {
+        LogLossStats(int32_t sec, int32_t count, int32_t error)
+            : mWallClockSec(sec), mCount(count), mLastError(error) {
+        }
+        int32_t mWallClockSec;
+        int32_t mCount;
+        // error code defined in linux/errno.h
+        int32_t mLastError;
+    };
+
     // Timestamps when we detect log loss, and the number of logs lost.
-    std::list<std::pair<int32_t, int32_t>> mLogLossStats;
+    std::list<LogLossStats> mLogLossStats;
 
     std::list<int32_t> mSystemServerRestartSec;
 
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index febb922..625294c 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -156,9 +156,6 @@
             FieldValue(Field(mTagId, getSimpleField(1)), Value(speakerImpedance.speakerLocation)));
     mValues.push_back(
             FieldValue(Field(mTagId, getSimpleField(2)), Value(speakerImpedance.milliOhms)));
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -173,9 +170,6 @@
             FieldValue(Field(mTagId, getSimpleField(2)), Value(hardwareFailed.hardwareLocation)));
     mValues.push_back(
             FieldValue(Field(mTagId, getSimpleField(3)), Value(int32_t(hardwareFailed.errorCode))));
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -190,9 +184,6 @@
             FieldValue(Field(mTagId, getSimpleField(2)), Value(physicalDropDetected.accelPeak)));
     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)),
                                  Value(physicalDropDetected.freefallDuration)));
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -205,10 +196,6 @@
         mValues.push_back(FieldValue(Field(mTagId, getSimpleField(i + 1)),
                                      Value(chargeCycles.cycleBucket[i])));
     }
-
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -231,10 +218,6 @@
                                  Value(batteryHealthSnapshotArgs.resistanceMicroOhm)));
     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)),
                                  Value(batteryHealthSnapshotArgs.levelPercent)));
-
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs, const SlowIo& slowIo) {
@@ -247,10 +230,6 @@
             FieldValue(Field(mTagId, getSimpleField(1)), Value(int32_t(slowIo.operation))));
     pos[0]++;
     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(slowIo.count)));
-
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -261,10 +240,6 @@
 
     mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)),
                                  Value(batteryCausedShutdown.voltageMicroV)));
-
-    if (!mValues.empty()) {
-        mValues.back().mField.decorateLastPos(1);
-    }
 }
 
 LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) : LogEvent(tagId, timestampNs, 0) {}
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index 6b8c12a..eddc86e 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -82,7 +82,9 @@
 
     // Create the service
     gStatsService = new StatsService(looper);
-    if (defaultServiceManager()->addService(String16("stats"), gStatsService) != 0) {
+    if (defaultServiceManager()->addService(String16("stats"), gStatsService, false,
+                IServiceManager::DUMP_FLAG_PRIORITY_NORMAL | IServiceManager::DUMP_FLAG_PROTO)
+            != 0) {
         ALOGE("Failed to add service as AIDL service");
         return -1;
     }
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index bd94800..5ca8814 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -143,6 +143,7 @@
 
 void CountMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
                                              const bool include_current_partial_bucket,
+                                             const bool erase_data,
                                              std::set<string> *str_set,
                                              ProtoOutputStream* protoOutput) {
     if (include_current_partial_bucket) {
@@ -230,7 +231,9 @@
 
     protoOutput->end(protoToken);
 
-    mPastBuckets.clear();
+    if (erase_data) {
+        mPastBuckets.clear();
+    }
 }
 
 void CountMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.h b/cmds/statsd/src/metrics/CountMetricProducer.h
index 39d4ae2..1ac44264 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.h
+++ b/cmds/statsd/src/metrics/CountMetricProducer.h
@@ -56,6 +56,7 @@
 
     void onDumpReportLocked(const int64_t dumpTimeNs,
                             const bool include_current_partial_bucket,
+                            const bool erase_data,
                             std::set<string> *str_set,
                             android::util::ProtoOutputStream* protoOutput) override;
 
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index dd3402d..35deffe 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -453,6 +453,7 @@
 
 void DurationMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
                                                 const bool include_current_partial_bucket,
+                                                const bool erase_data,
                                                 std::set<string> *str_set,
                                                 ProtoOutputStream* protoOutput) {
     if (include_current_partial_bucket) {
@@ -541,7 +542,9 @@
     }
 
     protoOutput->end(protoToken);
-    mPastBuckets.clear();
+    if (erase_data) {
+        mPastBuckets.clear();
+    }
 }
 
 void DurationMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) {
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 12addb8..1b830a3 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -63,6 +63,7 @@
 
     void onDumpReportLocked(const int64_t dumpTimeNs,
                             const bool include_current_partial_bucket,
+                            const bool erase_data,
                             std::set<string> *str_set,
                             android::util::ProtoOutputStream* protoOutput) override;
 
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index afd8ec2..a18e406 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -105,6 +105,7 @@
 
 void EventMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
                                              const bool include_current_partial_bucket,
+                                             const bool erase_data,
                                              std::set<string> *str_set,
                                              ProtoOutputStream* protoOutput) {
     if (mProto->size() <= 0) {
@@ -120,7 +121,9 @@
     protoOutput->write(FIELD_TYPE_MESSAGE | FIELD_ID_EVENT_METRICS,
                        reinterpret_cast<char*>(buffer.get()->data()), buffer.get()->size());
 
-    mProto->clear();
+    if (erase_data) {
+        mProto->clear();
+    }
 }
 
 void EventMetricProducer::onConditionChangedLocked(const bool conditionMet,
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.h b/cmds/statsd/src/metrics/EventMetricProducer.h
index 7f7aa37..96adfdd 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.h
+++ b/cmds/statsd/src/metrics/EventMetricProducer.h
@@ -47,6 +47,7 @@
 
     void onDumpReportLocked(const int64_t dumpTimeNs,
                             const bool include_current_partial_bucket,
+                            const bool erase_data,
                             std::set<string> *str_set,
                             android::util::ProtoOutputStream* protoOutput) override;
     void clearPastBucketsLocked(const int64_t dumpTimeNs) override;
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index f5a16e9..461ad28 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -140,7 +140,7 @@
 
     // Adjust start for partial bucket
     mCurrentBucketStartTimeNs = startTimeNs;
-    if (mIsPulled) {
+    if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
         pullAndMatchEventsLocked(startTimeNs);
     }
 
@@ -182,6 +182,7 @@
 
 void GaugeMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
                                              const bool include_current_partial_bucket,
+                                             const bool erase_data,
                                              std::set<string> *str_set,
                                              ProtoOutputStream* protoOutput) {
     VLOG("Gauge metric %lld report now...", (long long)mMetricId);
@@ -226,7 +227,6 @@
                            (long long)(NanoToMillis(pair.second)));
         protoOutput->end(wrapperToken);
     }
-    mSkippedBuckets.clear();
 
     for (const auto& pair : mPastBuckets) {
         const MetricDimensionKey& dimensionKey = pair.first;
@@ -304,7 +304,11 @@
     }
     protoOutput->end(protoToken);
 
-    mPastBuckets.clear();
+
+    if (erase_data) {
+        mPastBuckets.clear();
+        mSkippedBuckets.clear();
+    }
 }
 
 void GaugeMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 99827bb..6e3530b 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -80,7 +80,7 @@
         }
         flushCurrentBucketLocked(eventTimeNs);
         mCurrentBucketStartTimeNs = eventTimeNs;
-        if (mIsPulled) {
+        if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
             pullAndMatchEventsLocked(eventTimeNs);
         }
     };
@@ -94,6 +94,7 @@
 private:
     void onDumpReportLocked(const int64_t dumpTimeNs,
                             const bool include_current_partial_bucket,
+                            const bool erase_data,
                             std::set<string> *str_set,
                             android::util::ProtoOutputStream* protoOutput) override;
     void clearPastBucketsLocked(const int64_t dumpTimeNs) override;
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index b21fd50..127cbbd 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -133,10 +133,12 @@
     // This method clears all the past buckets.
     void onDumpReport(const int64_t dumpTimeNs,
                       const bool include_current_partial_bucket,
+                      const bool erase_data,
                       std::set<string> *str_set,
                       android::util::ProtoOutputStream* protoOutput) {
         std::lock_guard<std::mutex> lock(mMutex);
-        return onDumpReportLocked(dumpTimeNs, include_current_partial_bucket, str_set, protoOutput);
+        return onDumpReportLocked(dumpTimeNs, include_current_partial_bucket, erase_data,
+                str_set, protoOutput);
     }
 
     void clearPastBuckets(const int64_t dumpTimeNs) {
@@ -210,6 +212,7 @@
                                                   const int64_t eventTime) = 0;
     virtual void onDumpReportLocked(const int64_t dumpTimeNs,
                                     const bool include_current_partial_bucket,
+                                    const bool erase_data,
                                     std::set<string> *str_set,
                                     android::util::ProtoOutputStream* protoOutput) = 0;
     virtual void clearPastBucketsLocked(const int64_t dumpTimeNs) = 0;
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index f85ba1f..ac34f47 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -77,6 +77,8 @@
             mActivationAtomTrackerToMetricMap, mMetricIndexesWithActivation, mNoReportMetricIds);
 
     mHashStringsInReport = config.hash_strings_in_metric_report();
+    mVersionStringsInReport = config.version_strings_in_metric_report();
+    mInstallerInReport = config.installer_in_metric_report();
 
     if (config.allowed_log_source_size() == 0) {
         mConfigValid = false;
@@ -197,6 +199,7 @@
 
 void MetricsManager::onDumpReport(const int64_t dumpTimeStampNs,
                                   const bool include_current_partial_bucket,
+                                  const bool erase_data,
                                   std::set<string> *str_set,
                                   ProtoOutputStream* protoOutput) {
     VLOG("=========================Metric Reports Start==========================");
@@ -206,11 +209,11 @@
             uint64_t token = protoOutput->start(
                     FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_METRICS);
             if (mHashStringsInReport) {
-                producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, str_set,
-                                       protoOutput);
+                producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, erase_data,
+                                       str_set, protoOutput);
             } else {
-                producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, nullptr,
-                                       protoOutput);
+                producer->onDumpReport(dumpTimeStampNs, include_current_partial_bucket, erase_data,
+                                       nullptr, protoOutput);
             }
             protoOutput->end(token);
         } else {
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 649222ff..a31efbd 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -83,6 +83,14 @@
         return mHashStringsInReport;
     };
 
+    inline bool versionStringsInReport() const {
+        return mVersionStringsInReport;
+    };
+
+    inline bool installerInReport() const {
+        return mInstallerInReport;
+    };
+
     void refreshTtl(const int64_t currentTimestampNs) {
         if (mTtlNs > 0) {
             mTtlEndNs = currentTimestampNs + mTtlNs;
@@ -107,6 +115,7 @@
 
     virtual void onDumpReport(const int64_t dumpTimeNs,
                               const bool include_current_partial_bucket,
+                              const bool erase_data,
                               std::set<string> *str_set,
                               android::util::ProtoOutputStream* protoOutput);
 
@@ -125,6 +134,8 @@
     bool mConfigValid = false;
 
     bool mHashStringsInReport = false;
+    bool mVersionStringsInReport = false;
+    bool mInstallerInReport = false;
 
     const int64_t mTtlNs;
     int64_t mTtlEndNs;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 192a54b..a34df8aa 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -64,21 +64,29 @@
 const int FIELD_ID_DIMENSION_LEAF_IN_WHAT = 4;
 const int FIELD_ID_DIMENSION_LEAF_IN_CONDITION = 5;
 // for ValueBucketInfo
-const int FIELD_ID_VALUE_LONG = 7;
-const int FIELD_ID_VALUE_DOUBLE = 8;
+const int FIELD_ID_VALUE_INDEX = 1;
+const int FIELD_ID_VALUE_LONG = 2;
+const int FIELD_ID_VALUE_DOUBLE = 3;
+const int FIELD_ID_VALUES = 9;
 const int FIELD_ID_BUCKET_NUM = 4;
 const int FIELD_ID_START_BUCKET_ELAPSED_MILLIS = 5;
 const int FIELD_ID_END_BUCKET_ELAPSED_MILLIS = 6;
 
 // ValueMetric has a minimum bucket size of 10min so that we don't pull too frequently
-ValueMetricProducer::ValueMetricProducer(const ConfigKey& key, const ValueMetric& metric,
+ValueMetricProducer::ValueMetricProducer(const ConfigKey& key,
+                                         const ValueMetric& metric,
                                          const int conditionIndex,
-                                         const sp<ConditionWizard>& wizard, const int pullTagId,
-                                         const int64_t timeBaseNs, const int64_t startTimeNs,
+                                         const sp<ConditionWizard>& conditionWizard,
+                                         const int whatMatcherIndex,
+                                         const sp<EventMatcherWizard>& matcherWizard,
+                                         const int pullTagId,
+                                         const int64_t timeBaseNs,
+                                         const int64_t startTimeNs,
                                          const sp<StatsPullerManager>& pullerManager)
-    : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, wizard),
+    : MetricProducer(metric.id(), key, timeBaseNs, conditionIndex, conditionWizard),
+      mWhatMatcherIndex(whatMatcherIndex),
+      mEventMatcherWizard(matcherWizard),
       mPullerManager(pullerManager),
-      mValueField(metric.value_field()),
       mPullTagId(pullTagId),
       mIsPulled(pullTagId != -1),
       mMinBucketSizeNs(metric.min_bucket_size_nanos()),
@@ -92,7 +100,9 @@
                                   : StatsdStats::kDimensionKeySizeHardLimit),
       mUseAbsoluteValueOnReset(metric.use_absolute_value_on_reset()),
       mAggregationType(metric.aggregation_type()),
-      mValueType(metric.aggregation_type() == ValueMetric::AVG ? DOUBLE : LONG) {
+      mUseDiff(metric.has_use_diff() ? metric.use_diff() : (mIsPulled ? true : false)),
+      mValueDirection(metric.value_direction()),
+      mSkipZeroDiffOutput(metric.skip_zero_diff_output()) {
     int64_t bucketSizeMills = 0;
     if (metric.has_bucket()) {
         bucketSizeMills = TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket());
@@ -101,6 +111,9 @@
     }
 
     mBucketSizeNs = bucketSizeMills * 1000000;
+
+    translateFieldMatcher(metric.value_field(), &mFieldMatchers);
+
     if (metric.has_dimensions_in_what()) {
         translateFieldMatcher(metric.dimensions_in_what(), &mDimensionsInWhat);
         mContainANYPositionInDimensionsInWhat = HasPositionANY(metric.dimensions_in_what());
@@ -120,29 +133,27 @@
         }
     }
 
-    if (mValueField.child_size() > 0) {
-        mField = mValueField.child(0).field();
-    }
     mConditionSliced = (metric.links().size() > 0) || (mDimensionsInCondition.size() > 0);
     mSliceByPositionALL = HasPositionALL(metric.dimensions_in_what()) ||
-            HasPositionALL(metric.dimensions_in_condition());
+                          HasPositionALL(metric.dimensions_in_condition());
 
     flushIfNeededLocked(startTimeNs);
-    // Kicks off the puller immediately.
+
     if (mIsPulled) {
         mPullerManager->RegisterReceiver(mPullTagId, this, getCurrentBucketEndTimeNs(),
                                          mBucketSizeNs);
     }
 
-    // TODO: Only do this for partial buckets like first bucket. All other buckets should use
+    // Only do this for partial buckets like first bucket. All other buckets should use
     // flushIfNeeded to adjust start and end to bucket boundaries.
     // Adjust start for partial bucket
     mCurrentBucketStartTimeNs = startTimeNs;
-    if (mIsPulled) {
-        pullLocked(startTimeNs);
+    // Kicks off the puller immediately if condition is true and diff based.
+    if (mIsPulled && mCondition && mUseDiff) {
+        pullAndMatchEventsLocked(startTimeNs);
     }
-    VLOG("value metric %lld created. bucket size %lld start_time: %lld",
-        (long long)metric.id(), (long long)mBucketSizeNs, (long long)mTimeBaseNs);
+    VLOG("value metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
+         (long long)mBucketSizeNs, (long long)mTimeBaseNs);
 }
 
 ValueMetricProducer::~ValueMetricProducer() {
@@ -170,6 +181,7 @@
 
 void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
                                              const bool include_current_partial_bucket,
+                                             const bool erase_data,
                                              std::set<string> *str_set,
                                              ProtoOutputStream* protoOutput) {
     VLOG("metric %lld dump report now...", (long long)mMetricId);
@@ -187,14 +199,14 @@
     // Fills the dimension path if not slicing by ALL.
     if (!mSliceByPositionALL) {
         if (!mDimensionsInWhat.empty()) {
-            uint64_t dimenPathToken = protoOutput->start(
-                    FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_WHAT);
+            uint64_t dimenPathToken =
+                    protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_WHAT);
             writeDimensionPathToProto(mDimensionsInWhat, protoOutput);
             protoOutput->end(dimenPathToken);
         }
         if (!mDimensionsInCondition.empty()) {
-            uint64_t dimenPathToken = protoOutput->start(
-                    FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_CONDITION);
+            uint64_t dimenPathToken =
+                    protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_PATH_IN_CONDITION);
             writeDimensionPathToProto(mDimensionsInCondition, protoOutput);
             protoOutput->end(dimenPathToken);
         }
@@ -211,7 +223,6 @@
                            (long long)(NanoToMillis(pair.second)));
         protoOutput->end(wrapperToken);
     }
-    mSkippedBuckets.clear();
 
     for (const auto& pair : mPastBuckets) {
         const MetricDimensionKey& dimensionKey = pair.first;
@@ -221,15 +232,15 @@
 
         // First fill dimension.
         if (mSliceByPositionALL) {
-            uint64_t dimensionToken = protoOutput->start(
-                    FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
+            uint64_t dimensionToken =
+                    protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_WHAT);
             writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), str_set, protoOutput);
             protoOutput->end(dimensionToken);
             if (dimensionKey.hasDimensionKeyInCondition()) {
-                uint64_t dimensionInConditionToken = protoOutput->start(
-                        FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION);
-                writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(),
-                                      str_set, protoOutput);
+                uint64_t dimensionInConditionToken =
+                        protoOutput->start(FIELD_TYPE_MESSAGE | FIELD_ID_DIMENSION_IN_CONDITION);
+                writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(), str_set,
+                                      protoOutput);
                 protoOutput->end(dimensionInConditionToken);
             }
         } else {
@@ -237,8 +248,8 @@
                                            FIELD_ID_DIMENSION_LEAF_IN_WHAT, str_set, protoOutput);
             if (dimensionKey.hasDimensionKeyInCondition()) {
                 writeDimensionLeafNodesToProto(dimensionKey.getDimensionKeyInCondition(),
-                                               FIELD_ID_DIMENSION_LEAF_IN_CONDITION,
-                                               str_set, protoOutput);
+                                               FIELD_ID_DIMENSION_LEAF_IN_CONDITION, str_set,
+                                               protoOutput);
             }
         }
 
@@ -256,28 +267,43 @@
                 protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_BUCKET_NUM,
                                    (long long)(getBucketNumFromEndTimeNs(bucket.mBucketEndNs)));
             }
-            if (mValueType == LONG) {
-                protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_VALUE_LONG,
-                                   (long long)bucket.mValueLong);
-            } else {
-                protoOutput->write(FIELD_TYPE_DOUBLE | FIELD_ID_VALUE_DOUBLE, bucket.mValueDouble);
+            for (int i = 0; i < (int)bucket.valueIndex.size(); i ++) {
+                int index = bucket.valueIndex[i];
+                const Value& value = bucket.values[i];
+                uint64_t valueToken = protoOutput->start(
+                        FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_VALUES);
+                protoOutput->write(FIELD_TYPE_INT32 | FIELD_ID_VALUE_INDEX,
+                                   index);
+                if (value.getType() == LONG) {
+                    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_VALUE_LONG,
+                                       (long long)value.long_value);
+                    VLOG("\t bucket [%lld - %lld] value %d: %lld", (long long)bucket.mBucketStartNs,
+                         (long long)bucket.mBucketEndNs, index, (long long)value.long_value);
+                } else if (value.getType() == DOUBLE) {
+                    protoOutput->write(FIELD_TYPE_DOUBLE | FIELD_ID_VALUE_DOUBLE,
+                                       value.double_value);
+                    VLOG("\t bucket [%lld - %lld] value %d: %.2f", (long long)bucket.mBucketStartNs,
+                         (long long)bucket.mBucketEndNs, index, value.double_value);
+                } else {
+                    VLOG("Wrong value type for ValueMetric output: %d", value.getType());
+                }
+                protoOutput->end(valueToken);
             }
             protoOutput->end(bucketInfoToken);
-            VLOG("\t bucket [%lld - %lld] count: %lld, %.2f", (long long)bucket.mBucketStartNs,
-                 (long long)bucket.mBucketEndNs, (long long)bucket.mValueLong, bucket.mValueDouble);
         }
         protoOutput->end(wrapperToken);
     }
     protoOutput->end(protoToken);
 
     VLOG("metric %lld dump report now...", (long long)mMetricId);
-    mPastBuckets.clear();
+    if (erase_data) {
+        mPastBuckets.clear();
+        mSkippedBuckets.clear();
+    }
 }
 
 void ValueMetricProducer::onConditionChangedLocked(const bool condition,
                                                    const int64_t eventTimeNs) {
-    mCondition = condition;
-
     if (eventTimeNs < mCurrentBucketStartTimeNs) {
         VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
              (long long)mCurrentBucketStartTimeNs);
@@ -286,49 +312,72 @@
 
     flushIfNeededLocked(eventTimeNs);
 
-    if (mIsPulled) {
-        pullLocked(eventTimeNs);
+    // Pull on condition changes.
+    if (mIsPulled && (mCondition != condition)) {
+        pullAndMatchEventsLocked(eventTimeNs);
     }
+
+    // when condition change from true to false, clear diff base
+    if (mUseDiff && mCondition && !condition) {
+        for (auto& slice : mCurrentSlicedBucket) {
+            for (auto& interval : slice.second) {
+                interval.hasBase = false;
+            }
+        }
+    }
+
+    mCondition = condition;
 }
 
-void ValueMetricProducer::pullLocked(const int64_t timestampNs) {
+void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
     vector<std::shared_ptr<LogEvent>> allData;
     if (mPullerManager->Pull(mPullTagId, timestampNs, &allData)) {
         if (allData.size() == 0) {
             return;
         }
         for (const auto& data : allData) {
-            onMatchedLogEventLocked(0, *data);
+            if (mEventMatcherWizard->matchLogEvent(
+                *data, mWhatMatcherIndex) == MatchingState::kMatched) {
+                onMatchedLogEventLocked(mWhatMatcherIndex, *data);
+            }
         }
     }
 }
 
+int64_t ValueMetricProducer::calcPreviousBucketEndTime(const int64_t currentTimeNs) {
+    return mTimeBaseNs + ((currentTimeNs - mTimeBaseNs) / mBucketSizeNs) * mBucketSizeNs;
+}
+
 void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData) {
     std::lock_guard<std::mutex> lock(mMutex);
-
-    if (mCondition == true || mConditionTrackerIndex < 0) {
+    if (mCondition) {
         if (allData.size() == 0) {
+            VLOG("Data pulled is empty");
             return;
         }
         // For scheduled pulled data, the effective event time is snap to the nearest
-        // bucket boundary to make bucket finalize.
+        // bucket end. In the case of waking up from a deep sleep state, we will
+        // attribute to the previous bucket end. If the sleep was long but not very long, we
+        // will be in the immediate next bucket. Previous bucket may get a larger number as
+        // we pull at a later time than real bucket end.
+        // If the sleep was very long, we skip more than one bucket before sleep. In this case,
+        // if the diff base will be cleared and this new data will serve as new diff base.
         int64_t realEventTime = allData.at(0)->GetElapsedTimestampNs();
-        int64_t eventTime = mTimeBaseNs +
-            ((realEventTime - mTimeBaseNs) / mBucketSizeNs) * mBucketSizeNs;
-
-        // close the end of the bucket
-        mCondition = false;
-        for (const auto& data : allData) {
-            data->setElapsedTimestampNs(eventTime - 1);
-            onMatchedLogEventLocked(0, *data);
+        int64_t bucketEndTime = calcPreviousBucketEndTime(realEventTime) - 1;
+        if (bucketEndTime < mCurrentBucketStartTimeNs) {
+            VLOG("Skip bucket end pull due to late arrival: %lld vs %lld", (long long)bucketEndTime,
+                 (long long)mCurrentBucketStartTimeNs);
+            return;
         }
-
-        // start a new bucket
-        mCondition = true;
         for (const auto& data : allData) {
-            data->setElapsedTimestampNs(eventTime);
-            onMatchedLogEventLocked(0, *data);
+            if (mEventMatcherWizard->matchLogEvent(*data, mWhatMatcherIndex) ==
+                MatchingState::kMatched) {
+                data->setElapsedTimestampNs(bucketEndTime);
+                onMatchedLogEventLocked(mWhatMatcherIndex, *data);
+            }
         }
+    } else {
+        VLOG("No need to commit data on condition false.");
     }
 }
 
@@ -341,10 +390,12 @@
             (unsigned long)mCurrentSlicedBucket.size());
     if (verbose) {
         for (const auto& it : mCurrentSlicedBucket) {
+          for (const auto& interval : it.second) {
             fprintf(out, "\t(what)%s\t(condition)%s  (value)%s\n",
                     it.first.getDimensionKeyInWhat().toString().c_str(),
                     it.first.getDimensionKeyInCondition().toString().c_str(),
-                    it.second.value.toString().c_str());
+                    interval.value.toString().c_str());
+          }
         }
     }
 }
@@ -360,8 +411,8 @@
         StatsdStats::getInstance().noteMetricDimensionSize(mConfigKey, mMetricId, newTupleCount);
         // 2. Don't add more tuples, we are above the allowed threshold. Drop the data.
         if (newTupleCount > mDimensionHardLimit) {
-            ALOGE("ValueMetric %lld dropping data for dimension key %s",
-                (long long)mMetricId, newKey.toString().c_str());
+            ALOGE("ValueMetric %lld dropping data for dimension key %s", (long long)mMetricId,
+                  newKey.toString().c_str());
             return true;
         }
     }
@@ -369,31 +420,35 @@
     return false;
 }
 
-const Value getDoubleOrLong(const Value& value) {
-    Value v;
-    switch (value.type) {
-        case INT:
-            v.setLong(value.int_value);
-            break;
-        case LONG:
-            v.setLong(value.long_value);
-            break;
-        case FLOAT:
-            v.setDouble(value.float_value);
-            break;
-        case DOUBLE:
-            v.setDouble(value.double_value);
-            break;
-        default:
-            break;
+bool getDoubleOrLong(const LogEvent& event, const Matcher& matcher, Value& ret) {
+    for (const FieldValue& value : event.getValues()) {
+        if (value.mField.matches(matcher)) {
+            switch (value.mValue.type) {
+                case INT:
+                    ret.setLong(value.mValue.int_value);
+                    break;
+                case LONG:
+                    ret.setLong(value.mValue.long_value);
+                    break;
+                case FLOAT:
+                    ret.setDouble(value.mValue.float_value);
+                    break;
+                case DOUBLE:
+                    ret.setDouble(value.mValue.double_value);
+                    break;
+                default:
+                    break;
+            }
+            return true;
+        }
     }
-    return v;
+    return false;
 }
 
-void ValueMetricProducer::onMatchedLogEventInternalLocked(
-        const size_t matcherIndex, const MetricDimensionKey& eventKey,
-        const ConditionKey& conditionKey, bool condition,
-        const LogEvent& event) {
+void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIndex,
+                                                          const MetricDimensionKey& eventKey,
+                                                          const ConditionKey& conditionKey,
+                                                          bool condition, const LogEvent& event) {
     int64_t eventTimeNs = event.GetElapsedTimestampNs();
     if (eventTimeNs < mCurrentBucketStartTimeNs) {
         VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
@@ -403,86 +458,101 @@
 
     flushIfNeededLocked(eventTimeNs);
 
+    // For pulled data, we already check condition when we decide to pull or
+    // in onDataPulled. So take all of them.
+    // For pushed data, just check condition.
+    if (!(mIsPulled || condition)) {
+        VLOG("ValueMetric skip event because condition is false");
+        return;
+    }
+
     if (hitGuardRailLocked(eventKey)) {
         return;
     }
-    Interval& interval = mCurrentSlicedBucket[eventKey];
-
-    if (mField > event.size()) {
-        VLOG("Failed to extract value field %d from atom %s. %d", mField, event.ToString().c_str(),
-             (int)event.size());
-        return;
+    vector<Interval>& multiIntervals = mCurrentSlicedBucket[eventKey];
+    if (multiIntervals.size() < mFieldMatchers.size()) {
+        VLOG("Resizing number of intervals to %d", (int)mFieldMatchers.size());
+        multiIntervals.resize(mFieldMatchers.size());
     }
-    Value value = getDoubleOrLong(event.getValues()[mField - 1].mValue);
 
-    Value diff;
-    bool hasDiff = false;
-    if (mIsPulled) {
-        // Always require condition for pulled events. In the case of no condition, only pull
-        // on bucket boundaries, in which we fake condition changes.
-        if (mCondition == true) {
-            if (!interval.startUpdated) {
-                interval.start = value;
-                interval.startUpdated = true;
-            } else {
-                // Skip it if there is already value recorded for the start. Happens when puller
-                // takes too long to finish. In this case we take the previous value.
-                VLOG("Already recorded value for this dimension %s", eventKey.toString().c_str());
+    for (int i = 0; i < (int)mFieldMatchers.size(); i++) {
+        const Matcher& matcher = mFieldMatchers[i];
+        Interval& interval = multiIntervals[i];
+        interval.valueIndex = i;
+        Value value;
+        if (!getDoubleOrLong(event, matcher, value)) {
+            VLOG("Failed to get value %d from event %s", i, event.ToString().c_str());
+            return;
+        }
+
+        if (mUseDiff) {
+            // no base. just update base and return.
+            if (!interval.hasBase) {
+                interval.base = value;
+                interval.hasBase = true;
+                return;
             }
-        } else {
-            // Generally we expect value to be monotonically increasing.
-            // If not, take absolute value or drop it, based on config.
-            if (interval.startUpdated) {
-                if (value >= interval.start) {
-                    diff = (value - interval.start);
-                    hasDiff = true;
-                } else {
-                    if (mUseAbsoluteValueOnReset) {
+            Value diff;
+            switch (mValueDirection) {
+                case ValueMetric::INCREASING:
+                    if (value >= interval.base) {
+                        diff = value - interval.base;
+                    } else if (mUseAbsoluteValueOnReset) {
                         diff = value;
-                        hasDiff = true;
                     } else {
-                        VLOG("Dropping data for atom %d, prev: %s, now: %s", mPullTagId,
-                             interval.start.toString().c_str(), value.toString().c_str());
+                        VLOG("Unexpected decreasing value");
+                        StatsdStats::getInstance().notePullDataError(mPullTagId);
+                        interval.base = value;
+                        return;
                     }
-                }
-                interval.startUpdated = false;
-            } else {
-                VLOG("No start for matching end %s", value.toString().c_str());
+                    break;
+                case ValueMetric::DECREASING:
+                    if (interval.base >= value) {
+                        diff = interval.base - value;
+                    } else if (mUseAbsoluteValueOnReset) {
+                        diff = value;
+                    } else {
+                        VLOG("Unexpected increasing value");
+                        StatsdStats::getInstance().notePullDataError(mPullTagId);
+                        interval.base = value;
+                        return;
+                    }
+                    break;
+                case ValueMetric::ANY:
+                    diff = value - interval.base;
+                    break;
+                default:
+                    break;
             }
+            interval.base = value;
+            value = diff;
         }
-    } else {
-        // for pushed events, only aggregate when sliced condition is true
-        if (condition == true || mConditionTrackerIndex < 0) {
-            diff = value;
-            hasDiff = true;
-        }
-    }
-    if (hasDiff) {
+
         if (interval.hasValue) {
             switch (mAggregationType) {
                 case ValueMetric::SUM:
-                // for AVG, we add up and take average when flushing the bucket
+                    // for AVG, we add up and take average when flushing the bucket
                 case ValueMetric::AVG:
-                    interval.value += diff;
+                    interval.value += value;
                     break;
                 case ValueMetric::MIN:
-                    interval.value = diff < interval.value ? diff : interval.value;
+                    interval.value = std::min(value, interval.value);
                     break;
                 case ValueMetric::MAX:
-                    interval.value = diff > interval.value ? diff : interval.value;
+                    interval.value = std::max(value, interval.value);
                     break;
                 default:
                     break;
             }
         } else {
-            interval.value = diff;
+            interval.value = value;
             interval.hasValue = true;
         }
         interval.sampleSize += 1;
     }
 
     // TODO: propgate proper values down stream when anomaly support doubles
-    long wholeBucketVal = interval.value.long_value;
+    long wholeBucketVal = multiIntervals[0].value.long_value;
     auto prev = mCurrentFullBucket.find(eventKey);
     if (prev != mCurrentFullBucket.end()) {
         wholeBucketVal += prev->second;
@@ -509,6 +579,12 @@
 
     if (numBucketsForward > 1) {
         VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
+        // take base again in future good bucket.
+        for (auto& slice : mCurrentSlicedBucket) {
+            for (auto& interval : slice.second) {
+                interval.hasBase = false;
+            }
+        }
     }
     VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
          (long long)mCurrentBucketStartTimeNs);
@@ -519,27 +595,38 @@
          (int)mCurrentSlicedBucket.size());
     int64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
 
-    ValueBucket info;
-    info.mBucketStartNs = mCurrentBucketStartTimeNs;
-    if (eventTimeNs < fullBucketEndTimeNs) {
-        info.mBucketEndNs = eventTimeNs;
-    } else {
-        info.mBucketEndNs = fullBucketEndTimeNs;
-    }
+    int64_t bucketEndTime = eventTimeNs < fullBucketEndTimeNs ? eventTimeNs : fullBucketEndTimeNs;
 
-    if (info.mBucketEndNs - mCurrentBucketStartTimeNs >= mMinBucketSizeNs) {
+    if (bucketEndTime - mCurrentBucketStartTimeNs >= mMinBucketSizeNs) {
         // The current bucket is large enough to keep.
         for (const auto& slice : mCurrentSlicedBucket) {
-            if (slice.second.hasValue) {
-                info.mValueLong = slice.second.value.long_value;
-                info.mValueDouble = (double)slice.second.value.long_value / slice.second.sampleSize;
-                // it will auto create new vector of ValuebucketInfo if the key is not found.
+            ValueBucket bucket;
+            bucket.mBucketStartNs = mCurrentBucketStartTimeNs;
+            bucket.mBucketEndNs = bucketEndTime;
+            for (const auto& interval : slice.second) {
+                if (interval.hasValue) {
+                    // skip the output if the diff is zero
+                    if (mSkipZeroDiffOutput && mUseDiff && interval.value.isZero()) {
+                        continue;
+                    }
+                    bucket.valueIndex.push_back(interval.valueIndex);
+                    if (mAggregationType != ValueMetric::AVG) {
+                        bucket.values.push_back(interval.value);
+                    } else {
+                        double sum = interval.value.type == LONG ? (double)interval.value.long_value
+                                                                 : interval.value.double_value;
+                        bucket.values.push_back(Value((double)sum / interval.sampleSize));
+                    }
+                }
+            }
+            // it will auto create new vector of ValuebucketInfo if the key is not found.
+            if (bucket.valueIndex.size() > 0) {
                 auto& bucketList = mPastBuckets[slice.first];
-                bucketList.push_back(info);
+                bucketList.push_back(bucket);
             }
         }
     } else {
-        mSkippedBuckets.emplace_back(info.mBucketStartNs, info.mBucketEndNs);
+        mSkippedBuckets.emplace_back(mCurrentBucketStartTimeNs, bucketEndTime);
     }
 
     if (eventTimeNs > fullBucketEndTimeNs) {  // If full bucket, send to anomaly tracker.
@@ -547,7 +634,7 @@
         if (mCurrentFullBucket.size() > 0) {
             for (const auto& slice : mCurrentSlicedBucket) {
                 // TODO: fix this when anomaly can accept double values
-                mCurrentFullBucket[slice.first] += slice.second.value.long_value;
+                mCurrentFullBucket[slice.first] += slice.second[0].value.long_value;
             }
             for (const auto& slice : mCurrentFullBucket) {
                 for (auto& tracker : mAnomalyTrackers) {
@@ -563,7 +650,7 @@
                 for (auto& tracker : mAnomalyTrackers) {
                     if (tracker != nullptr) {
                         // TODO: fix this when anomaly can accept double values
-                        tracker->addPastBucket(slice.first, slice.second.value.long_value,
+                        tracker->addPastBucket(slice.first, slice.second[0].value.long_value,
                                                mCurrentBucketNum);
                     }
                 }
@@ -573,12 +660,17 @@
         // Accumulate partial bucket.
         for (const auto& slice : mCurrentSlicedBucket) {
             // TODO: fix this when anomaly can accept double values
-            mCurrentFullBucket[slice.first] += slice.second.value.long_value;
+            mCurrentFullBucket[slice.first] += slice.second[0].value.long_value;
         }
     }
 
     // Reset counters
-    mCurrentSlicedBucket.clear();
+    for (auto& slice : mCurrentSlicedBucket) {
+        for (auto& interval : slice.second) {
+            interval.hasValue = false;
+            interval.sampleSize = 0;
+        }
+    }
 }
 
 size_t ValueMetricProducer::byteSizeLocked() const {
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index b2f0b6f..c3912ee 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -23,6 +23,7 @@
 #include "../condition/ConditionTracker.h"
 #include "../external/PullDataReceiver.h"
 #include "../external/StatsPullerManager.h"
+#include "../matchers/EventMatcherWizard.h"
 #include "../stats_log_util.h"
 #include "MetricProducer.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
@@ -34,14 +35,16 @@
 struct ValueBucket {
     int64_t mBucketStartNs;
     int64_t mBucketEndNs;
-    int64_t mValueLong;
-    double mValueDouble;
+    std::vector<int> valueIndex;
+    std::vector<Value> values;
 };
 
 class ValueMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
 public:
     ValueMetricProducer(const ConfigKey& key, const ValueMetric& valueMetric,
-                        const int conditionIndex, const sp<ConditionWizard>& wizard,
+                        const int conditionIndex, const sp<ConditionWizard>& conditionWizard,
+                        const int whatMatcherIndex,
+                        const sp<EventMatcherWizard>& matcherWizard,
                         const int pullTagId, const int64_t timeBaseNs, const int64_t startTimeNs,
                         const sp<StatsPullerManager>& pullerManager);
 
@@ -54,35 +57,11 @@
     void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid,
                           const int64_t version) override {
         std::lock_guard<std::mutex> lock(mMutex);
-
-        if (mIsPulled && (mCondition == true || mConditionTrackerIndex < 0)) {
-            vector<shared_ptr<LogEvent>> allData;
-            mPullerManager->Pull(mPullTagId, eventTimeNs, &allData);
-            if (allData.size() == 0) {
-                // This shouldn't happen since this valuemetric is not useful now.
-            }
-
-            // Pretend the pulled data occurs right before the app upgrade event.
-            mCondition = false;
-            for (const auto& data : allData) {
-                data->setElapsedTimestampNs(eventTimeNs - 1);
-                onMatchedLogEventLocked(0, *data);
-            }
-
-            flushCurrentBucketLocked(eventTimeNs);
-            mCurrentBucketStartTimeNs = eventTimeNs;
-
-            mCondition = true;
-            for (const auto& data : allData) {
-                data->setElapsedTimestampNs(eventTimeNs);
-                onMatchedLogEventLocked(0, *data);
-            }
-        } else {
-            // For pushed value metric or pulled metric where condition is not true,
-            // we simply flush and reset the current bucket start.
-            flushCurrentBucketLocked(eventTimeNs);
-            mCurrentBucketStartTimeNs = eventTimeNs;
+        if (mIsPulled && mCondition) {
+            pullAndMatchEventsLocked(eventTimeNs - 1);
         }
+        flushCurrentBucketLocked(eventTimeNs);
+        mCurrentBucketStartTimeNs = eventTimeNs;
     };
 
 protected:
@@ -94,6 +73,7 @@
 private:
     void onDumpReportLocked(const int64_t dumpTimeNs,
                             const bool include_current_partial_bucket,
+                            const bool erase_data,
                             std::set<string> *str_set,
                             android::util::ProtoOutputStream* protoOutput) override;
     void clearPastBucketsLocked(const int64_t dumpTimeNs) override;
@@ -116,9 +96,17 @@
 
     void dropDataLocked(const int64_t dropTimeNs) override;
 
+    // Calculate previous bucket end time based on current time.
+    int64_t calcPreviousBucketEndTime(const int64_t currentTimeNs);
+
+    const int mWhatMatcherIndex;
+
+    sp<EventMatcherWizard> mEventMatcherWizard;
+
     sp<StatsPullerManager> mPullerManager;
 
-    const FieldMatcher mValueField;
+    // Value fields for matching.
+    std::vector<Matcher> mFieldMatchers;
 
     // tagId for pulled data. -1 if this is not pulled
     const int mPullTagId;
@@ -126,15 +114,14 @@
     // if this is pulled metric
     const bool mIsPulled;
 
-    int mField;
-
-    // internal state of a bucket.
+    // internal state of an ongoing aggregation bucket.
     typedef struct {
-        // Pulled data always come in pair of <start, end>. This holds the value
-        // for start. The diff (end - start) is taken as the real value.
-        Value start;
-        // Whether the start data point is updated
-        bool startUpdated;
+        // Index in multi value aggregation.
+        int valueIndex;
+        // Holds current base value of the dimension. Take diff and update if necessary.
+        Value base;
+        // Whether there is a base to diff to.
+        bool hasBase;
         // Current value, depending on the aggregation type.
         Value value;
         // Number of samples collected.
@@ -144,7 +131,7 @@
         bool hasValue;
     } Interval;
 
-    std::unordered_map<MetricDimensionKey, Interval> mCurrentSlicedBucket;
+    std::unordered_map<MetricDimensionKey, std::vector<Interval>> mCurrentSlicedBucket;
 
     std::unordered_map<MetricDimensionKey, int64_t> mCurrentFullBucket;
 
@@ -159,7 +146,7 @@
     // Util function to check whether the specified dimension hits the guardrail.
     bool hitGuardRailLocked(const MetricDimensionKey& newKey);
 
-    void pullLocked(const int64_t timestampNs);
+    void pullAndMatchEventsLocked(const int64_t timestampNs);
 
     static const size_t kBucketSize = sizeof(ValueBucket{});
 
@@ -171,9 +158,14 @@
 
     const ValueMetric::AggregationType mAggregationType;
 
-    const Type mValueType;
+    const bool mUseDiff;
+
+    const ValueMetric::ValueDirection mValueDirection;
+
+    const bool mSkipZeroDiffOutput;
 
     FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsNoCondition);
+  FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering);
     FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset);
     FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset);
     FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition);
@@ -186,13 +178,13 @@
     FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition);
     FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition);
     FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2);
-    FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition3);
     FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateMin);
     FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateMax);
     FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateAvg);
     FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateSum);
-    FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateSumSliced);
     FRIEND_TEST(ValueMetricProducerTest, TestFirstBucket);
+    FRIEND_TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime);
+    FRIEND_TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput);
 };
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp
index 4a9b521..47b0376 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp
@@ -35,8 +35,6 @@
 #include "stats_util.h"
 #include "statslog.h"
 
-#include <inttypes.h>
-
 using std::set;
 using std::string;
 using std::unordered_map;
@@ -490,9 +488,9 @@
             }
         }
 
-        sp<MetricProducer> valueProducer =
-                new ValueMetricProducer(key, metric, conditionIndex, wizard, pullTagId,
-                                        timeBaseTimeNs, currentTimeNs, pullerManager);
+        sp<MetricProducer> valueProducer = new ValueMetricProducer(
+                key, metric, conditionIndex, wizard, trackerIndex, matcherWizard, pullTagId,
+                timeBaseTimeNs, currentTimeNs, pullerManager);
         allMetricProducers.push_back(valueProducer);
     }
 
@@ -575,7 +573,7 @@
     for (int i = 0; i < config.no_report_metric_size(); ++i) {
         const auto no_report_metric = config.no_report_metric(i);
         if (metricMap.find(no_report_metric) == metricMap.end()) {
-            ALOGW("no_report_metric %" PRId64 " not exist", no_report_metric);
+            ALOGW("no_report_metric %lld not exist", no_report_metric);
             return false;
         }
         noReportMetricIds.insert(no_report_metric);
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index 37a0067..59f3f04 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -49,6 +49,10 @@
 const int FIELD_ID_SNAPSHOT_PACKAGE_UID = 3;
 const int FIELD_ID_SNAPSHOT_PACKAGE_DELETED = 4;
 const int FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH = 5;
+const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING = 6;
+const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH = 7;
+const int FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER = 8;
+const int FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH = 9;
 const int FIELD_ID_SNAPSHOT_TIMESTAMP = 1;
 const int FIELD_ID_SNAPSHOT_PACKAGE_INFO = 2;
 const int FIELD_ID_SNAPSHOTS = 1;
@@ -60,6 +64,10 @@
 const int FIELD_ID_CHANGE_NEW_VERSION = 5;
 const int FIELD_ID_CHANGE_PREV_VERSION = 6;
 const int FIELD_ID_CHANGE_PACKAGE_HASH = 7;
+const int FIELD_ID_CHANGE_NEW_VERSION_STRING = 8;
+const int FIELD_ID_CHANGE_PREV_VERSION_STRING = 9;
+const int FIELD_ID_CHANGE_NEW_VERSION_STRING_HASH = 10;
+const int FIELD_ID_CHANGE_PREV_VERSION_STRING_HASH = 11;
 
 UidMap::UidMap() : mBytesUsed(0) {}
 
@@ -104,7 +112,8 @@
 }
 
 void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
-                       const vector<int64_t>& versionCode, const vector<String16>& packageName) {
+                       const vector<int64_t>& versionCode, const vector<String16>& versionString,
+                       const vector<String16>& packageName, const vector<String16>& installer) {
     vector<wp<PackageInfoListener>> broadcastList;
     {
         lock_guard<mutex> lock(mMutex);  // Exclusively lock for updates.
@@ -121,7 +130,9 @@
         mMap.clear();
         for (size_t j = 0; j < uid.size(); j++) {
             string package = string(String8(packageName[j]).string());
-            mMap[std::make_pair(uid[j], package)] = AppData(versionCode[j]);
+            mMap[std::make_pair(uid[j], package)] =
+                    AppData(versionCode[j], string(String8(versionString[j]).string()),
+                            string(String8(installer[j]).string()));
         }
 
         for (const auto& kv : deletedApps) {
@@ -150,23 +161,30 @@
 }
 
 void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid,
-                       const int64_t& versionCode) {
+                       const int64_t& versionCode, const String16& versionString,
+                       const String16& installer) {
     vector<wp<PackageInfoListener>> broadcastList;
     string appName = string(String8(app_16).string());
     {
         lock_guard<mutex> lock(mMutex);
         int32_t prevVersion = 0;
+        string prevVersionString = "";
+        string newVersionString = string(String8(versionString).string());
         bool found = false;
         auto it = mMap.find(std::make_pair(uid, appName));
         if (it != mMap.end()) {
             found = true;
             prevVersion = it->second.versionCode;
+            prevVersionString = it->second.versionString;
             it->second.versionCode = versionCode;
+            it->second.versionString = newVersionString;
+            it->second.installer = string(String8(installer).string());
             it->second.deleted = false;
         }
         if (!found) {
             // Otherwise, we need to add an app at this uid.
-            mMap[std::make_pair(uid, appName)] = AppData(versionCode);
+            mMap[std::make_pair(uid, appName)] =
+                    AppData(versionCode, newVersionString, string(String8(installer).string()));
         } else {
             // Only notify the listeners if this is an app upgrade. If this app is being installed
             // for the first time, then we don't notify the listeners.
@@ -174,7 +192,8 @@
             // app after deletion.
             getListenerListCopyLocked(&broadcastList);
         }
-        mChanges.emplace_back(false, timestamp, appName, uid, versionCode, prevVersion);
+        mChanges.emplace_back(false, timestamp, appName, uid, versionCode, newVersionString,
+                              prevVersion, prevVersionString);
         mBytesUsed += kBytesChangeRecord;
         ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
@@ -226,10 +245,12 @@
         lock_guard<mutex> lock(mMutex);
 
         int64_t prevVersion = 0;
+        string prevVersionString = "";
         auto key = std::make_pair(uid, app);
         auto it = mMap.find(key);
         if (it != mMap.end() && !it->second.deleted) {
             prevVersion = it->second.versionCode;
+            prevVersionString = it->second.versionString;
             it->second.deleted = true;
             mDeletedApps.push_back(key);
         }
@@ -240,7 +261,7 @@
             mMap.erase(oldest);
             StatsdStats::getInstance().noteUidMapAppDeletionDropped();
         }
-        mChanges.emplace_back(true, timestamp, app, uid, 0, prevVersion);
+        mChanges.emplace_back(true, timestamp, app, uid, 0, "", prevVersion, prevVersionString);
         mBytesUsed += kBytesChangeRecord;
         ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
@@ -315,8 +336,9 @@
     return mBytesUsed;
 }
 
-void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key,
-                          std::set<string> *str_set, ProtoOutputStream* proto) {
+void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::set<string>* str_set,
+                          bool includeVersionStrings, bool includeInstaller,
+                          ProtoOutputStream* proto) {
     lock_guard<mutex> lock(mMutex);  // Lock for updates
 
     for (const ChangeRecord& record : mChanges) {
@@ -330,8 +352,22 @@
                 str_set->insert(record.package);
                 proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_PACKAGE_HASH,
                              (long long)Hash64(record.package));
+                if (includeVersionStrings) {
+                    str_set->insert(record.versionString);
+                    proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_NEW_VERSION_STRING_HASH,
+                                 (long long)Hash64(record.versionString));
+                    str_set->insert(record.prevVersionString);
+                    proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_PREV_VERSION_STRING_HASH,
+                                 (long long)Hash64(record.prevVersionString));
+                }
             } else {
                 proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PACKAGE, record.package);
+                if (includeVersionStrings) {
+                    proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_NEW_VERSION_STRING,
+                                 record.versionString);
+                    proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PREV_VERSION_STRING,
+                                 record.prevVersionString);
+                }
             }
 
             proto->write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_UID, (int)record.uid);
@@ -354,8 +390,26 @@
             str_set->insert(kv.first.second);
             proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH,
                          (long long)Hash64(kv.first.second));
+            if (includeVersionStrings) {
+                str_set->insert(kv.second.versionString);
+                proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH,
+                             (long long)Hash64(kv.second.versionString));
+            }
+            if (includeInstaller) {
+                str_set->insert(kv.second.installer);
+                proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH,
+                             (long long)Hash64(kv.second.installer));
+            }
         } else {
             proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, kv.first.second);
+            if (includeVersionStrings) {
+                proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING,
+                             kv.second.versionString);
+            }
+            if (includeInstaller) {
+                proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER,
+                             kv.second.installer);
+            }
         }
 
         proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
@@ -391,8 +445,9 @@
 
     for (const auto& kv : mMap) {
         if (!kv.second.deleted) {
-            dprintf(out, "%s, v%" PRId64 " (%i)\n", kv.first.second.c_str(), kv.second.versionCode,
-                    kv.first.first);
+            dprintf(out, "%s, v%" PRId64 ", %s, %s (%i)\n", kv.first.second.c_str(),
+                    kv.second.versionCode, kv.second.versionString.c_str(),
+                    kv.second.installer.c_str(), kv.first.first);
         }
     }
 }
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 4598369..75ff507 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -44,12 +44,16 @@
 
 struct AppData {
     int64_t versionCode;
+    string versionString;
+    string installer;
     bool deleted;
 
     // Empty constructor needed for unordered map.
     AppData() {
     }
-    AppData(const int64_t v) : versionCode(v), deleted(false){};
+
+    AppData(const int64_t v, const string& versionString, const string& installer)
+        : versionCode(v), versionString(versionString), installer(installer), deleted(false){};
 };
 
 // When calling appendUidMap, we retrieve all the ChangeRecords since the last
@@ -61,15 +65,20 @@
     const int32_t uid;
     const int64_t version;
     const int64_t prevVersion;
+    const string versionString;
+    const string prevVersionString;
 
     ChangeRecord(const bool isDeletion, const int64_t timestampNs, const string& package,
-                 const int32_t uid, const int64_t version, const int64_t prevVersion)
+                 const int32_t uid, const int64_t version, const string versionString,
+                 const int64_t prevVersion, const string prevVersionString)
         : deletion(isDeletion),
           timestampNs(timestampNs),
           package(package),
           uid(uid),
           version(version),
-          prevVersion(prevVersion) {
+          prevVersion(prevVersion),
+          versionString(versionString),
+          prevVersionString(prevVersionString) {
     }
 };
 
@@ -87,10 +96,12 @@
      * tuple, ie. uid[j] corresponds to packageName[j] with versionCode[j].
      */
     void updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
-                   const vector<int64_t>& versionCode, const vector<String16>& packageName);
+                   const vector<int64_t>& versionCode, const vector<String16>& versionString,
+                   const vector<String16>& packageName, const vector<String16>& installer);
 
     void updateApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid,
-                   const int64_t& versionCode);
+                   const int64_t& versionCode, const String16& versionString,
+                   const String16& installer);
     void removeApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid);
 
     // Returns true if the given uid contains the specified app (eg. com.google.android.gms).
@@ -127,8 +138,9 @@
     // Gets all snapshots and changes that have occurred since the last output.
     // If every config key has received a change or snapshot record, then this
     // record is deleted.
-    void appendUidMap(const int64_t& timestamp, const ConfigKey& key,
-                      std::set<string> *str_set, util::ProtoOutputStream* proto);
+    void appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::set<string>* str_set,
+                      bool includeVersionStrings, bool includeInstaller,
+                      util::ProtoOutputStream* proto);
 
     // Forces the output to be cleared. We still generate a snapshot based on the current state.
     // This results in extra data uploaded but helps us reconstruct the uid mapping on the server
diff --git a/cmds/statsd/src/socket/StatsSocketListener.cpp b/cmds/statsd/src/socket/StatsSocketListener.cpp
index 9b0691b..6bb8cda 100755
--- a/cmds/statsd/src/socket/StatsSocketListener.cpp
+++ b/cmds/statsd/src/socket/StatsSocketListener.cpp
@@ -40,7 +40,6 @@
 namespace statsd {
 
 static const int kLogMsgHeaderSize = 28;
-static const int kLibLogTag = 1006;
 
 StatsSocketListener::StatsSocketListener(const sp<LogListener>& listener)
     : SocketListener(getLogSocket(), false /*start listen*/), mListener(listener) {
@@ -109,10 +108,11 @@
     // TODO(b/80538532): In addition to log it in StatsdStats, we should properly reset the config.
     if (n == sizeof(android_log_event_int_t)) {
         android_log_event_int_t* int_event = reinterpret_cast<android_log_event_int_t*>(ptr);
-        if (int_event->header.tag == kLibLogTag && int_event->payload.type == EVENT_TYPE_INT) {
-            ALOGE("Found dropped events: %d", int_event->payload.data);
+        if (int_event->payload.type == EVENT_TYPE_INT) {
+            ALOGE("Found dropped events: %d error %d", int_event->payload.data,
+                  int_event->header.tag);
             StatsdStats::getInstance().noteLogLost((int32_t)getWallClockSec(),
-                                                   int_event->payload.data);
+                                                   int_event->payload.data, int_event->header.tag);
             return true;
         }
     }
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 8bfa360..32ee5af 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -108,12 +108,22 @@
 
   optional int64 value = 3 [deprecated = true];
 
-  oneof values {
-      int64 value_long = 7;
+  oneof single_value {
+      int64 value_long = 7 [deprecated = true];
 
-      double value_double = 8;
+      double value_double = 8 [deprecated = true];
   }
 
+  message Value {
+      optional int32 index = 1;
+      oneof value {
+          int64 value_long = 2;
+          double value_double = 3;
+      }
+  }
+
+  repeated Value values = 9;
+
   optional int64 bucket_num = 4;
 
   optional int64 start_bucket_elapsed_millis = 5;
@@ -223,6 +233,14 @@
             optional bool deleted = 4;
 
             optional uint64 name_hash = 5;
+
+            optional string version_string = 6;
+
+            optional uint64 version_string_hash = 7;
+
+            optional string installer = 8;
+
+            optional uint64 installer_hash = 9;
         }
         optional int64 elapsed_timestamp_nanos = 1;
 
@@ -240,6 +258,10 @@
         optional int64 new_version = 5;
         optional int64 prev_version = 6;
         optional uint64 app_hash = 7;
+        optional string new_version_string = 8;
+        optional string prev_version_string = 9;
+        optional uint64 new_version_string_hash = 10;
+        optional uint64 prev_version_string_hash = 11;
     }
     repeated Change changes = 2;
 }
@@ -374,6 +396,7 @@
         optional int64 max_pull_time_nanos = 6;
         optional int64 average_pull_delay_nanos = 7;
         optional int64 max_pull_delay_nanos = 8;
+        optional int64 data_error = 9;
     }
     repeated PulledAtomStats pulled_atom_stats = 10;
 
@@ -397,4 +420,11 @@
     repeated int64 log_loss_stats = 14;
 
     repeated int32 system_restart_sec = 15;
+
+    message LogLossStats {
+        optional int32 detected_time_sec = 1;
+        optional int32 count = 2;
+        optional int32 last_error = 3;
+    }
+    repeated LogLossStats detected_log_loss = 16;
 }
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 44fa72e..504c586 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -63,6 +63,7 @@
 const int FIELD_ID_MAX_PULL_TIME_NANOS = 6;
 const int FIELD_ID_AVERAGE_PULL_DELAY_NANOS = 7;
 const int FIELD_ID_MAX_PULL_DELAY_NANOS = 8;
+const int FIELD_ID_DATA_ERROR = 9;
 
 namespace {
 
@@ -446,6 +447,7 @@
                        (long long)pair.second.avgPullDelayNs);
     protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_MAX_PULL_DELAY_NANOS,
                        (long long)pair.second.maxPullDelayNs);
+    protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_DATA_ERROR, (long long)pair.second.dataError);
     protoOutput->end(token);
 }
 
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index b8f6850..61f31eb 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -21,6 +21,7 @@
 #include "HashableDimensionKey.h"
 #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
 #include "guardrail/StatsdStats.h"
+#include "statslog.h"
 
 namespace android {
 namespace os {
@@ -87,6 +88,10 @@
 // Returns the truncated timestamp.
 int64_t truncateTimestampNsToFiveMinutes(int64_t timestampNs);
 
+inline bool isPushedAtom(int atomId) {
+    return atomId <= util::kMaxPushedAtomId && atomId > 1;
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index d5f81a59..f955df2 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -270,6 +270,18 @@
   optional int64 min_bucket_size_nanos = 10;
 
   optional bool use_absolute_value_on_reset = 11 [default = false];
+
+  optional bool use_diff = 12;
+
+  enum ValueDirection {
+      UNKNOWN = 0;
+      INCREASING = 1;
+      DECREASING = 2;
+      ANY = 3;
+  }
+  optional ValueDirection value_direction = 13 [default = INCREASING];
+
+  optional bool skip_zero_diff_output = 14 [default = true];
 }
 
 message Alert {
@@ -397,6 +409,10 @@
 
   repeated MetricActivation metric_activation = 17;
 
+  optional bool version_strings_in_metric_report = 18;
+
+  optional bool installer_in_metric_report = 19;
+
   // Field number 1000 is reserved for later use.
   reserved 1000;
 }
diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp
index 4c6671d..2b9528f 100644
--- a/cmds/statsd/tests/LogEntryMatcher_test.cpp
+++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp
@@ -148,8 +148,12 @@
 
     uidMap.updateMap(
             1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+            {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+             android::String16("v1"), android::String16("v2")},
             {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
-             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
+             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+            {android::String16(""), android::String16(""), android::String16(""),
+             android::String16(""), android::String16("")});
 
     EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
     attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
@@ -297,8 +301,12 @@
     UidMap uidMap;
     uidMap.updateMap(
             1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+            {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+             android::String16("v1"), android::String16("v2")},
             {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
-             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
+             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+            {android::String16(""), android::String16(""), android::String16(""),
+             android::String16(""), android::String16("")});
 
     AttributionNodeInternal attribution_node1;
     attribution_node1.set_uid(1111);
@@ -372,8 +380,12 @@
     UidMap uidMap;
     uidMap.updateMap(
             1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+            {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+             android::String16("v1"), android::String16("v2")},
             {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
-             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
+             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+            {android::String16(""), android::String16(""), android::String16(""),
+             android::String16(""), android::String16("")});
 
     AttributionNodeInternal attribution_node1;
     attribution_node1.set_uid(1067);
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index b6f635c..355df29 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -153,7 +153,8 @@
     // Setup simple config key corresponding to empty config.
     sp<UidMap> m = new UidMap();
     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    m->updateMap(1, {1, 2}, {1, 2}, {String16("p1"), String16("p2")});
+    m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
+                 {String16("p1"), String16("p2")}, {String16(""), String16("")});
     sp<AlarmMonitor> anomalyAlarmMonitor;
     sp<AlarmMonitor> subscriberAlarmMonitor;
     int broadcastCount = 0;
@@ -168,7 +169,7 @@
 
     // Expect to get no metrics, but snapshot specified above in uidmap.
     vector<uint8_t> bytes;
-    p.onDumpReport(key, 1, false, ADB_DUMP, &bytes);
+    p.onDumpReport(key, 1, false, true, ADB_DUMP, &bytes);
 
     ConfigMetricsReportList output;
     output.ParseFromArray(bytes.data(), bytes.size());
@@ -182,7 +183,8 @@
     // Setup simple config key corresponding to empty config.
     sp<UidMap> m = new UidMap();
     sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    m->updateMap(1, {1, 2}, {1, 2}, {String16("p1"), String16("p2")});
+    m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
+                 {String16("p1"), String16("p2")}, {String16(""), String16("")});
     sp<AlarmMonitor> anomalyAlarmMonitor;
     sp<AlarmMonitor> subscriberAlarmMonitor;
     int broadcastCount = 0;
@@ -197,7 +199,7 @@
 
     // Expect to get no metrics, but snapshot specified above in uidmap.
     vector<uint8_t> bytes;
-    p.onDumpReport(key, 1, false, ADB_DUMP, &bytes);
+    p.onDumpReport(key, 1, false, true, ADB_DUMP, &bytes);
 
     ConfigMetricsReportList output;
     output.ParseFromArray(bytes.data(), bytes.size());
@@ -227,7 +229,7 @@
 
     // Expect to get no metrics, but snapshot specified above in uidmap.
     vector<uint8_t> bytes;
-    p.onDumpReport(key, 1, false, ADB_DUMP, &bytes);
+    p.onDumpReport(key, 1, false, true, ADB_DUMP, &bytes);
 
     ConfigMetricsReportList output;
     output.ParseFromArray(bytes.data(), bytes.size());
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index 99082cc..f0d9cf1 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -71,14 +71,20 @@
     vector<int32_t> uids;
     vector<int64_t> versions;
     vector<String16> apps;
+    vector<String16> versionStrings;
+    vector<String16> installers;
 
     uids.push_back(1000);
     uids.push_back(1000);
+    versionStrings.push_back(String16("v1"));
+    versionStrings.push_back(String16("v1"));
+    installers.push_back(String16(""));
+    installers.push_back(String16(""));
     apps.push_back(String16(kApp1.c_str()));
     apps.push_back(String16(kApp2.c_str()));
     versions.push_back(4);
     versions.push_back(5);
-    m.updateMap(1, uids, versions, apps);
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
     EXPECT_TRUE(m.hasApp(1000, kApp1));
     EXPECT_TRUE(m.hasApp(1000, kApp2));
     EXPECT_FALSE(m.hasApp(1000, "not.app"));
@@ -97,14 +103,20 @@
     vector<int32_t> uids;
     vector<int64_t> versions;
     vector<String16> apps;
+    vector<String16> versionStrings;
+    vector<String16> installers;
 
     uids.push_back(1000);
     uids.push_back(1000);
+    versionStrings.push_back(String16("v1"));
+    versionStrings.push_back(String16("v1"));
+    installers.push_back(String16(""));
+    installers.push_back(String16(""));
     apps.push_back(String16(kApp1.c_str()));
     apps.push_back(String16(kApp2.c_str()));
     versions.push_back(4);
     versions.push_back(5);
-    m.updateMap(1, uids, versions, apps);
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
     std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
     EXPECT_EQ(name_set.size(), 2u);
@@ -112,7 +124,7 @@
     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
 
     // Update the app1 version.
-    m.updateApp(2, String16(kApp1.c_str()), 1000, 40);
+    m.updateApp(2, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
     EXPECT_EQ(40, m.getAppVersion(1000, kApp1));
 
     name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
@@ -138,14 +150,15 @@
 
 TEST(UidMapTest, TestUpdateApp) {
     UidMap m;
-    m.updateMap(1, {1000, 1000}, {4, 5}, {String16(kApp1.c_str()), String16(kApp2.c_str())});
+    m.updateMap(1, {1000, 1000}, {4, 5}, {String16("v4"), String16("v5")},
+                {String16(kApp1.c_str()), String16(kApp2.c_str())}, {String16(""), String16("")});
     std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
     EXPECT_EQ(name_set.size(), 2u);
     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
     EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
 
     // Adds a new name for uid 1000.
-    m.updateApp(2, String16("NeW_aPP1_NAmE"), 1000, 40);
+    m.updateApp(2, String16("NeW_aPP1_NAmE"), 1000, 40, String16("v40"), String16(""));
     name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
     EXPECT_EQ(name_set.size(), 3u);
     EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
@@ -154,7 +167,7 @@
     EXPECT_TRUE(name_set.find("new_app1_name") != name_set.end());
 
     // This name is also reused by another uid 2000.
-    m.updateApp(3, String16("NeW_aPP1_NAmE"), 2000, 1);
+    m.updateApp(3, String16("NeW_aPP1_NAmE"), 2000, 1, String16("v1"), String16(""));
     name_set = m.getAppNamesFromUid(2000, true /* returnNormalized */);
     EXPECT_EQ(name_set.size(), 1u);
     EXPECT_TRUE(name_set.find("NeW_aPP1_NAmE") == name_set.end());
@@ -185,21 +198,26 @@
     vector<int32_t> uids;
     vector<int64_t> versions;
     vector<String16> apps;
+    vector<String16> versionStrings;
+    vector<String16> installers;
     uids.push_back(1000);
     apps.push_back(String16(kApp2.c_str()));
+    versionStrings.push_back(String16("v1"));
+    installers.push_back(String16(""));
     versions.push_back(5);
-    m.updateMap(1, uids, versions, apps);
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
     // Set the last timestamp for this config key to be newer.
     m.mLastUpdatePerConfigKey[config1] = 2;
 
     ProtoOutputStream proto;
-    m.appendUidMap(3, config1, nullptr, &proto);
+    m.appendUidMap(3, config1, nullptr, true, true, &proto);
 
     // Check there's still a uidmap attached this one.
     UidMapping results;
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(1, results.snapshots_size());
+    EXPECT_EQ("v1", results.snapshots(0).package_info(0).version_string());
 }
 
 TEST(UidMapTest, TestRemovedAppRetained) {
@@ -209,15 +227,19 @@
     m.OnConfigUpdated(config1);
     vector<int32_t> uids;
     vector<int64_t> versions;
+    vector<String16> versionStrings;
+    vector<String16> installers;
     vector<String16> apps;
     uids.push_back(1000);
     apps.push_back(String16(kApp2.c_str()));
     versions.push_back(5);
-    m.updateMap(1, uids, versions, apps);
+    versionStrings.push_back(String16("v5"));
+    installers.push_back(String16(""));
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
     m.removeApp(2, String16(kApp2.c_str()), 1000);
 
     ProtoOutputStream proto;
-    m.appendUidMap(3, config1, nullptr, &proto);
+    m.appendUidMap(3, config1, nullptr, true, true, &proto);
 
     // Snapshot should still contain this item as deleted.
     UidMapping results;
@@ -233,30 +255,34 @@
     m.OnConfigUpdated(config1);
     vector<int32_t> uids;
     vector<int64_t> versions;
+    vector<String16> versionStrings;
+    vector<String16> installers;
     vector<String16> apps;
     const int maxDeletedApps = StatsdStats::kMaxDeletedAppsInUidMap;
     for (int j = 0; j < maxDeletedApps + 10; j++) {
         uids.push_back(j);
         apps.push_back(String16(kApp1.c_str()));
         versions.push_back(j);
+        versionStrings.push_back(String16("v"));
+        installers.push_back(String16(""));
     }
-    m.updateMap(1, uids, versions, apps);
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
     // First, verify that we have the expected number of items.
     UidMapping results;
     ProtoOutputStream proto;
-    m.appendUidMap(3, config1, nullptr, &proto);
+    m.appendUidMap(3, config1, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(maxDeletedApps + 10, results.snapshots(0).package_info_size());
 
     // Now remove all the apps.
-    m.updateMap(1, uids, versions, apps);
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
     for (int j = 0; j < maxDeletedApps + 10; j++) {
         m.removeApp(4, String16(kApp1.c_str()), j);
     }
 
     proto.clear();
-    m.appendUidMap(5, config1, nullptr, &proto);
+    m.appendUidMap(5, config1, nullptr, true, true, &proto);
     // Snapshot drops the first nine items.
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(maxDeletedApps, results.snapshots(0).package_info_size());
@@ -272,6 +298,8 @@
 
     vector<int32_t> uids;
     vector<int64_t> versions;
+    vector<String16> versionStrings;
+    vector<String16> installers;
     vector<String16> apps;
     uids.push_back(1000);
     uids.push_back(1000);
@@ -279,45 +307,49 @@
     apps.push_back(String16(kApp2.c_str()));
     versions.push_back(4);
     versions.push_back(5);
-    m.updateMap(1, uids, versions, apps);
+    versionStrings.push_back(String16("v4"));
+    versionStrings.push_back(String16("v5"));
+    installers.push_back(String16(""));
+    installers.push_back(String16(""));
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
     ProtoOutputStream proto;
-    m.appendUidMap(2, config1, nullptr, &proto);
+    m.appendUidMap(2, config1, nullptr, true, true, &proto);
     UidMapping results;
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(1, results.snapshots_size());
 
     // We have to keep at least one snapshot in memory at all times.
     proto.clear();
-    m.appendUidMap(2, config1, nullptr, &proto);
+    m.appendUidMap(2, config1, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(1, results.snapshots_size());
 
     // Now add another configuration.
     m.OnConfigUpdated(config2);
-    m.updateApp(5, String16(kApp1.c_str()), 1000, 40);
+    m.updateApp(5, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
     EXPECT_EQ(1U, m.mChanges.size());
     proto.clear();
-    m.appendUidMap(6, config1, nullptr, &proto);
+    m.appendUidMap(6, config1, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(1, results.snapshots_size());
     EXPECT_EQ(1, results.changes_size());
     EXPECT_EQ(1U, m.mChanges.size());
 
     // Add another delta update.
-    m.updateApp(7, String16(kApp2.c_str()), 1001, 41);
+    m.updateApp(7, String16(kApp2.c_str()), 1001, 41, String16("v41"), String16(""));
     EXPECT_EQ(2U, m.mChanges.size());
 
     // We still can't remove anything.
     proto.clear();
-    m.appendUidMap(8, config1, nullptr, &proto);
+    m.appendUidMap(8, config1, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(1, results.snapshots_size());
     EXPECT_EQ(1, results.changes_size());
     EXPECT_EQ(2U, m.mChanges.size());
 
     proto.clear();
-    m.appendUidMap(9, config2, nullptr, &proto);
+    m.appendUidMap(9, config2, nullptr, true, true, &proto);
     protoOutputStreamToUidMapping(&proto, &results);
     EXPECT_EQ(1, results.snapshots_size());
     EXPECT_EQ(2, results.changes_size());
@@ -335,19 +367,23 @@
     vector<int32_t> uids;
     vector<int64_t> versions;
     vector<String16> apps;
+    vector<String16> versionStrings;
+    vector<String16> installers;
     uids.push_back(1000);
     apps.push_back(String16(kApp1.c_str()));
     versions.push_back(1);
-    m.updateMap(1, uids, versions, apps);
+    versionStrings.push_back(String16("v1"));
+    installers.push_back(String16(""));
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
-    m.updateApp(3, String16(kApp1.c_str()), 1000, 40);
+    m.updateApp(3, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
 
     ProtoOutputStream proto;
     vector<uint8_t> bytes;
-    m.appendUidMap(2, config1, nullptr, &proto);
+    m.appendUidMap(2, config1, nullptr, true, true, &proto);
     size_t prevBytes = m.mBytesUsed;
 
-    m.appendUidMap(4, config1, nullptr, &proto);
+    m.appendUidMap(4, config1, nullptr, true, true, &proto);
     EXPECT_TRUE(m.mBytesUsed < prevBytes);
 }
 
@@ -361,21 +397,27 @@
     size_t startBytes = m.mBytesUsed;
     vector<int32_t> uids;
     vector<int64_t> versions;
+    vector<String16> versionStrings;
+    vector<String16> installers;
     vector<String16> apps;
     for (int i = 0; i < 100; i++) {
         uids.push_back(1);
         buf = "EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY." + to_string(i);
         apps.push_back(String16(buf.c_str()));
         versions.push_back(1);
+        versionStrings.push_back(String16("v1"));
+        installers.push_back(String16(""));
     }
-    m.updateMap(1, uids, versions, apps);
+    m.updateMap(1, uids, versions, versionStrings, apps, installers);
 
-    m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2);
+    m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2,
+                String16("v2"), String16(""));
     EXPECT_EQ(1U, m.mChanges.size());
 
     // Now force deletion by limiting the memory to hold one delta change.
-    m.maxBytesOverride = 80; // Since the app string alone requires >45 characters.
-    m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4);
+    m.maxBytesOverride = 120; // Since the app string alone requires >45 characters.
+    m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4,
+                String16("v4"), String16(""));
     EXPECT_EQ(1U, m.mChanges.size());
 }
 
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index a8fcc81..a9841c9 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -69,8 +69,10 @@
     // Here it assumes that GMS core has two uids.
     processor->getUidMap()->updateMap(
             1, {222, 444, 111, 333}, {1, 1, 2, 2},
+            {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
             {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
-             String16("APP3")});
+             String16("APP3")},
+            {String16(""), String16(""), String16(""), String16("")});
 
     // GMS core node is in the middle.
     std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
@@ -144,8 +146,8 @@
     }
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -215,8 +217,10 @@
     // Here it assumes that GMS core has two uids.
     processor->getUidMap()->updateMap(
             1, {222, 444, 111, 333}, {1, 1, 2, 2},
+            {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
             {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
-             String16("APP3")});
+             String16("APP3")},
+            {String16(""), String16(""), String16(""), String16("")});
 
     // GMS core node is in the middle.
     std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
@@ -290,8 +294,8 @@
     }
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
index 75bd40f..a8914da 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp
@@ -212,7 +212,7 @@
                 ConfigMetricsReportList reports;
                 vector<uint8_t> buffer;
                 processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
-                                        ADB_DUMP, &buffer);
+                                        true, ADB_DUMP, &buffer);
                 EXPECT_TRUE(buffer.size() > 0);
                 EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
                 backfillDimensionPath(&reports);
@@ -548,7 +548,7 @@
             ConfigMetricsReportList reports;
             vector<uint8_t> buffer;
             processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
-                                    ADB_DUMP, &buffer);
+                                    true, ADB_DUMP, &buffer);
             EXPECT_TRUE(buffer.size() > 0);
             EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
             backfillDimensionPath(&reports);
@@ -798,7 +798,7 @@
             ConfigMetricsReportList reports;
             vector<uint8_t> buffer;
             processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
-                                    ADB_DUMP, &buffer);
+                                    true, ADB_DUMP, &buffer);
             EXPECT_TRUE(buffer.size() > 0);
             EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
             backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
index c5a8a2e..621b6ed 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp
@@ -130,8 +130,8 @@
 
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -346,8 +346,8 @@
 
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -530,8 +530,8 @@
 
         ConfigMetricsReportList reports;
         vector<uint8_t> buffer;
-        processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP,
-                                &buffer);
+        processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+                                ADB_DUMP, &buffer);
         EXPECT_TRUE(buffer.size() > 0);
         EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
         backfillDimensionPath(&reports);
@@ -732,8 +732,8 @@
 
         ConfigMetricsReportList reports;
         vector<uint8_t> buffer;
-        processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP,
-                                &buffer);
+        processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+                                ADB_DUMP, &buffer);
         EXPECT_TRUE(buffer.size() > 0);
         EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
         backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
index 5bcc9ee..9f8acaf 100644
--- a/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
+++ b/cmds/statsd/tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp
@@ -143,7 +143,7 @@
             ConfigMetricsReportList reports;
             vector<uint8_t> buffer;
             processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
-                                    ADB_DUMP, &buffer);
+                                    true, ADB_DUMP, &buffer);
             EXPECT_TRUE(buffer.size() > 0);
             EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
             backfillDimensionPath(&reports);
@@ -438,7 +438,7 @@
             ConfigMetricsReportList reports;
             vector<uint8_t> buffer;
             processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false,
-                                    ADB_DUMP, &buffer);
+                                    true, ADB_DUMP, &buffer);
             EXPECT_TRUE(buffer.size() > 0);
             EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
             backfillDimensionPath(&reports);
@@ -658,8 +658,8 @@
 
         ConfigMetricsReportList reports;
         vector<uint8_t> buffer;
-        processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP,
-                                &buffer);
+        processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+                                ADB_DUMP, &buffer);
         EXPECT_TRUE(buffer.size() > 0);
         EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
         backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index d7b9c11..2d090e0 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -123,8 +123,8 @@
 
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -246,8 +246,8 @@
 
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -350,8 +350,8 @@
 
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
index 5c1ef01..71afedf 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -149,8 +149,8 @@
         }
         ConfigMetricsReportList reports;
         vector<uint8_t> buffer;
-        processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, ADB_DUMP,
-                                &buffer);
+        processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, true,
+                                ADB_DUMP, &buffer);
         EXPECT_TRUE(buffer.size() > 0);
         EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
         backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
index 0f13a4a..29e86f3 100644
--- a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
@@ -167,8 +167,8 @@
 
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index cc8894b..9349c85 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -199,8 +199,8 @@
     }
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -318,8 +318,8 @@
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
 
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index 67acd61..2b0285b 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -46,7 +46,7 @@
     IPCThreadState* ipc = IPCThreadState::self();
     ConfigKey configKey(ipc->getCallingUid(), kConfigKey);
     processor->onDumpReport(configKey, timestamp, include_current /* include_current_bucket*/,
-                            ADB_DUMP, &output);
+                            true /* erase_data */, ADB_DUMP, &output);
     ConfigMetricsReportList reports;
     reports.ParseFromArray(output.data(), output.size());
     EXPECT_EQ(1, reports.reports_size());
@@ -132,7 +132,8 @@
     service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
     // This is a new installation, so there shouldn't be a split (should be same as the without
     // split case).
-    service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2);
+    service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
+                               String16(""));
     // Goes into the second bucket.
     service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
 
@@ -145,11 +146,13 @@
     SendConfig(service, MakeConfig());
     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
                                              // initialized with.
-    service.mUidMap->updateMap(start, {1}, {1}, {String16(kApp1.c_str())});
+    service.mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
+                               {String16("")});
 
     // Force the uidmap to update at timestamp 2.
     service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
-    service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2);
+    service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
+                               String16(""));
     // Goes into the second bucket.
     service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
 
@@ -168,7 +171,8 @@
     SendConfig(service, MakeConfig());
     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
                                              // initialized with.
-    service.mUidMap->updateMap(start, {1}, {1}, {String16(kApp1.c_str())});
+    service.mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
+                               {String16("")});
 
     // Force the uidmap to update at timestamp 2.
     service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
@@ -189,13 +193,14 @@
 TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
     StatsService service(nullptr);
     // Partial buckets don't occur when app is first installed.
-    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
+    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
     SendConfig(service, MakeValueMetricConfig(0));
     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
                                              // initialized with.
 
     service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
-    service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2);
+    service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2,
+                               String16("v2"), String16(""));
 
     ConfigMetricsReport report =
             GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100, true);
@@ -206,14 +211,15 @@
 TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
     StatsService service(nullptr);
     // Partial buckets don't occur when app is first installed.
-    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
+    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
     SendConfig(service, MakeValueMetricConfig(60 * NS_PER_SEC /* One minute */));
     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
                                              // initialized with.
 
     const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2;
     service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
-    service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2);
+    service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
+                               String16(""));
 
     ConfigMetricsReport report =
             GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC, true);
@@ -229,13 +235,14 @@
 TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
     StatsService service(nullptr);
     // Partial buckets don't occur when app is first installed.
-    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
+    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
     SendConfig(service, MakeGaugeMetricConfig(0));
     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
                                              // initialized with.
 
     service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
-    service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2);
+    service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2,
+                               String16("v2"), String16(""));
 
     ConfigMetricsReport report =
             GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100, true);
@@ -246,14 +253,15 @@
 TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
     StatsService service(nullptr);
     // Partial buckets don't occur when app is first installed.
-    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
+    service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
     SendConfig(service, MakeGaugeMetricConfig(60 * NS_PER_SEC /* One minute */));
     int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
                                              // initialized with.
 
     const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2;
     service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
-    service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2);
+    service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
+                               String16(""));
 
     ConfigMetricsReport report =
             GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC, true);
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index f2e8f58..abf1ab1 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -49,6 +49,7 @@
         CreateDimensions(android::util::TEMPERATURE, {2/* sensor name field */ });
     valueMetric->set_bucket(FIVE_MINUTES);
     valueMetric->set_use_absolute_value_on_reset(true);
+    valueMetric->set_skip_zero_diff_output(false);
     return config;
 }
 
@@ -117,8 +118,8 @@
 
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -141,23 +142,23 @@
 
     EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(0).has_value_long());
+    EXPECT_EQ(1, data.bucket_info(0).values_size());
 
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(1).has_value_long());
+    EXPECT_EQ(1, data.bucket_info(1).values_size());
 
     EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(2).has_value_long());
+    EXPECT_EQ(1, data.bucket_info(2).values_size());
 
     EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(3).has_value_long());
+    EXPECT_EQ(1, data.bucket_info(3).values_size());
 
     EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(4).has_value_long());
+    EXPECT_EQ(1, data.bucket_info(4).values_size());
 }
 
 TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
@@ -224,8 +225,8 @@
 
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -248,15 +249,15 @@
 
     EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(0).has_value_long());
+    EXPECT_EQ(1, data.bucket_info(0).values_size());
 
     EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(1).has_value_long());
+    EXPECT_EQ(1, data.bucket_info(1).values_size());
 
     EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
     EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(2).has_value_long());
+    EXPECT_EQ(1, data.bucket_info(2).values_size());
 }
 
 #else
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index b9d0c62..6d1317c 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -127,8 +127,8 @@
     FeedEvents(config, processor);
     vector<uint8_t> buffer;
     ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -164,8 +164,8 @@
     FeedEvents(config, processor);
     vector<uint8_t> buffer;
     ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -215,8 +215,8 @@
         processor->OnLogEvent(event.get());
     }
 
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -248,8 +248,8 @@
     FeedEvents(config, processor);
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
 
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
@@ -277,8 +277,8 @@
     FeedEvents(config, processor);
     ConfigMetricsReportList reports;
     vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
@@ -323,8 +323,8 @@
         processor->OnLogEvent(event.get());
     }
 
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, ADB_DUMP,
-                            &buffer);
+    processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
+                            ADB_DUMP, &buffer);
     EXPECT_TRUE(buffer.size() > 0);
     EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
     backfillDimensionPath(&reports);
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 60bd4a7..737408d 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -608,15 +608,6 @@
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3);
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Invoke([](int tagId, int64_t timeNs,
-                                vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
                 shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
                 event->write(4);
                 event->init();
@@ -631,7 +622,8 @@
                 event->init();
                 data->push_back(event);
                 return true;
-            }));
+            }))
+            .WillOnce(Return(true));
 
     int triggerId = 5;
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
@@ -640,43 +632,28 @@
                                       pullerManager);
 
     vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
 
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
     LogEvent trigger(triggerId, bucketStartTimeNs + 10);
     trigger.init();
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
     trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-    EXPECT_EQ(3UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+    trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1);
+    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
 
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(10);
-    event->init();
-    allData.push_back(event);
-
-    gaugeProducer.onDataPulled(allData);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
-    EXPECT_EQ(INT, it->mValue.getType());
-    EXPECT_EQ(10, it->mValue.int_value);
     EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(3UL, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.size());
-    EXPECT_EQ(3, gaugeProducer.mPastBuckets.begin()
+    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.size());
+    EXPECT_EQ(4, gaugeProducer.mPastBuckets.begin()
                          ->second.back()
                          .mGaugeAtoms[0]
                          .mFields->begin()
                          ->mValue.int_value);
-    EXPECT_EQ(4, gaugeProducer.mPastBuckets.begin()
-                         ->second.back()
-                         .mGaugeAtoms[1]
-                         .mFields->begin()
-                         ->mValue.int_value);
     EXPECT_EQ(5, gaugeProducer.mPastBuckets.begin()
                          ->second.back()
-                         .mGaugeAtoms[2]
+                         .mGaugeAtoms[1]
                          .mFields->begin()
                          ->mValue.int_value);
 }
@@ -731,7 +708,8 @@
                 event->init();
                 data->push_back(event);
                 return true;
-            }));
+            }))
+            .WillOnce(Return(true));
 
     int triggerId = 5;
     GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
@@ -740,30 +718,21 @@
                                       pullerManager);
 
     vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
 
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    LogEvent trigger(triggerId, bucketStartTimeNs + 10);
+    LogEvent trigger(triggerId, bucketStartTimeNs + 3);
     trigger.init();
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+    trigger.setElapsedTimestampNs(bucketStartTimeNs + 10);
+    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
     EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->size());
     EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
     trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
     gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
     EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+    trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1);
+    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
 
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(4);
-    event->write(11);
-    event->init();
-    allData.push_back(event);
-
-    gaugeProducer.onDataPulled(allData);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
-    EXPECT_EQ(INT, it->mValue.getType());
-    EXPECT_EQ(11, it->mValue.int_value);
     EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.size());
     auto bucketIt = gaugeProducer.mPastBuckets.begin();
     EXPECT_EQ(1UL, bucketIt->second.back().mGaugeAtoms.size());
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 57aab97..44aa00b 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "src/matchers/SimpleLogMatchingTracker.h"
 #include "src/metrics/ValueMetricProducer.h"
 #include "src/stats_log_util.h"
 #include "metrics_test_helper.h"
@@ -40,6 +41,8 @@
 const ConfigKey kConfigKey(0, 12345);
 const int tagId = 1;
 const int64_t metricId = 123;
+const int64_t atomMatcherId = 678;
+const int logEventMatcherIndex = 0;
 const int64_t bucketStartTimeNs = 10000000000;
 const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
 const int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
@@ -47,7 +50,41 @@
 const int64_t bucket4StartTimeNs = bucketStartTimeNs + 3 * bucketSizeNs;
 const int64_t bucket5StartTimeNs = bucketStartTimeNs + 4 * bucketSizeNs;
 const int64_t bucket6StartTimeNs = bucketStartTimeNs + 5 * bucketSizeNs;
-const int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+double epsilon = 0.001;
+
+/*
+ * Tests that the first bucket works correctly
+ */
+TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+
+    int64_t startTimeBase = 11;
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+
+    // statsd started long ago.
+    // The metric starts in the middle of the bucket
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase,
+                                      22, pullerManager);
+
+    EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
+    EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
+    EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
+              valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
+    EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
+              valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
+}
 
 /*
  * Tests that the first bucket works correctly
@@ -59,13 +96,20 @@
     metric.mutable_value_field()->set_field(tagId);
     metric.mutable_value_field()->add_child()->set_field(2);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
 
     // statsd started long ago.
     // The metric starts in the middle of the bucket
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      -1, 5, 600 * NS_PER_SEC + NS_PER_SEC/2, pullerManager);
+                                      logEventMatcherIndex, eventMatcherWizard, -1, 5,
+                                      600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
 
     EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
     EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
@@ -82,6 +126,12 @@
     metric.mutable_value_field()->set_field(tagId);
     metric.mutable_value_field()->add_child()->set_field(2);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
@@ -90,7 +140,7 @@
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
                 event->write(tagId);
                 event->write(3);
                 event->init();
@@ -99,7 +149,8 @@
             }));
 
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+                                      logEventMatcherIndex, eventMatcherWizard, tagId,
+                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -112,14 +163,13 @@
     valueProducer.onDataPulled(allData);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
 
-    // startUpdated:true sum:0 start:11
-    EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(11, curInterval.start.long_value);
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(11, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(8, curInterval.value.long_value);
+    EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     allData.clear();
     event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
@@ -130,13 +180,15 @@
     valueProducer.onDataPulled(allData);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // tartUpdated:false sum:12
-    EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(false, curInterval.hasValue);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(23, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(12, curInterval.value.long_value);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
 
     allData.clear();
     event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -146,13 +198,111 @@
     allData.push_back(event);
     valueProducer.onDataPulled(allData);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false sum:12
-    EXPECT_EQ(true, curInterval.startUpdated);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(36, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(13, curInterval.value.long_value);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+    EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+}
+
+/*
+ * Tests pulled atoms with filtering
+ */
+TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
+    ValueMetric metric;
+    metric.set_id(metricId);
+    metric.set_bucket(ONE_MINUTE);
+    metric.mutable_value_field()->set_field(tagId);
+    metric.mutable_value_field()->add_child()->set_field(2);
+
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    auto keyValue = atomMatcher.add_field_value_matcher();
+    keyValue->set_field(1);
+    keyValue->set_eq_int(3);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+    EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
+            .WillOnce(Invoke([](int tagId, int64_t timeNs,
+                                vector<std::shared_ptr<LogEvent>>* data) {
+                data->clear();
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+                event->write(3);
+                event->write(3);
+                event->init();
+                data->push_back(event);
+                return true;
+            }));
+
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+                                      logEventMatcherIndex, eventMatcherWizard, tagId,
+                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+
+    vector<shared_ptr<LogEvent>> allData;
+    allData.clear();
+    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+    event->write(3);
+    event->write(11);
+    event->init();
+    allData.push_back(event);
+
+    valueProducer.onDataPulled(allData);
+    // has one slice
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    ValueMetricProducer::Interval curInterval =
+            valueProducer.mCurrentSlicedBucket.begin()->second[0];
+
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(11, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(8, curInterval.value.long_value);
+    EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+
+    allData.clear();
+    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+    event->write(4);
+    event->write(23);
+    event->init();
+    allData.push_back(event);
+    valueProducer.onDataPulled(allData);
+    // has one slice
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(11, curInterval.base.long_value);
+    // no events caused flush of bucket
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(8, curInterval.value.long_value);
+    EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+
+    allData.clear();
+    event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+    event->write(3);
+    event->write(36);
+    event->init();
+    allData.push_back(event);
+    valueProducer.onDataPulled(allData);
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+
+    // the base was reset
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(36, curInterval.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(3UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
 }
 
 /*
@@ -166,14 +316,21 @@
     metric.mutable_value_field()->add_child()->set_field(2);
     metric.set_use_absolute_value_on_reset(true);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
+    EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(true));
 
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+                                      logEventMatcherIndex, eventMatcherWizard, tagId,
+                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -186,11 +343,11 @@
     valueProducer.onDataPulled(allData);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
 
-    EXPECT_EQ(true, curInterval.startUpdated);
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(11, curInterval.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(11, curInterval.start.long_value);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     allData.clear();
@@ -202,12 +359,12 @@
     valueProducer.onDataPulled(allData);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(10, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(10, curInterval.value.long_value);
+    EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     allData.clear();
     event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -217,12 +374,14 @@
     allData.push_back(event);
     valueProducer.onDataPulled(allData);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(false, curInterval.hasValue);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(36, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(26, curInterval.value.long_value);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+    EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
 }
 
 /*
@@ -235,6 +394,12 @@
     metric.mutable_value_field()->set_field(tagId);
     metric.mutable_value_field()->add_child()->set_field(2);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
@@ -242,7 +407,8 @@
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
 
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+                                      logEventMatcherIndex, eventMatcherWizard, tagId,
+                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
@@ -255,11 +421,11 @@
     valueProducer.onDataPulled(allData);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
 
-    EXPECT_EQ(true, curInterval.startUpdated);
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(11, curInterval.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(11, curInterval.start.long_value);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     allData.clear();
@@ -271,8 +437,9 @@
     valueProducer.onDataPulled(allData);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(true, curInterval.startUpdated);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(10, curInterval.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
@@ -284,12 +451,12 @@
     allData.push_back(event);
     valueProducer.onDataPulled(allData);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(36, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(26, curInterval.value.long_value);
+    EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 }
 
 /*
@@ -303,27 +470,22 @@
     metric.mutable_value_field()->add_child()->set_field(2);
     metric.set_condition(StringToId("SCREEN_ON"));
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
 
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
-            // should not take effect
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write(tagId);
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Invoke([](int tagId, int64_t timeNs,
-                                vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
                 event->write(tagId);
                 event->write(100);
                 event->init();
@@ -333,7 +495,7 @@
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
                 event->write(tagId);
                 event->write(120);
                 event->init();
@@ -341,16 +503,17 @@
                 return true;
             }));
 
-    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
+    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
     valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     // startUpdated:false sum:0 start:100
-    EXPECT_EQ(100, curInterval.start.long_value);
-    EXPECT_EQ(true, curInterval.startUpdated);
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(100, curInterval.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
@@ -365,21 +528,21 @@
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false sum:0 start:110
-    EXPECT_EQ(110, curInterval.start.long_value);
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(110, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(10, curInterval.value.long_value);
+    EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false sum:0 start:110
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasValue);
     EXPECT_EQ(10, curInterval.value.long_value);
-    EXPECT_EQ(false, curInterval.startUpdated);
+    EXPECT_EQ(false, curInterval.hasBase);
 }
 
 TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
@@ -389,10 +552,17 @@
     metric.mutable_value_field()->set_field(tagId);
     metric.mutable_value_field()->add_child()->set_field(2);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+                                      pullerManager);
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -401,9 +571,9 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
 
-    valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    valueProducer.notifyAppUpgrade(bucketStartTimeNs + 150, "ANY.APP", 1, 1);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
 
     shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
     event2->write(1);
@@ -411,7 +581,7 @@
     event2->init();
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
 
     // Next value should create a new bucket.
     shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
@@ -430,28 +600,35 @@
     metric.mutable_value_field()->set_field(tagId);
     metric.mutable_value_field()->add_child()->set_field(2);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
-            .WillOnce(Return(false))
+            .WillOnce(Return(true))
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 149);
                 event->write(tagId);
                 event->write(120);
                 event->init();
                 data->push_back(event);
                 return true;
             }));
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, tagId, bucketStartTimeNs,
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
 
     vector<shared_ptr<LogEvent>> allData;
     allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
     event->write(tagId);
     event->write(100);
     event->init();
@@ -460,21 +637,21 @@
     valueProducer.onDataPulled(allData);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
 
-    valueProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+    valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(eventUpgradeTimeNs, valueProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValueLong);
+    EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
 
     allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
     event->write(tagId);
     event->write(150);
     event->init();
     allData.push_back(event);
     valueProducer.onDataPulled(allData);
-    EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(30L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mValueLong);
+    EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+    EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+    EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
 }
 
 TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
@@ -485,16 +662,21 @@
     metric.mutable_value_field()->add_child()->set_field(2);
     metric.set_condition(StringToId("SCREEN_ON"));
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
-            .WillOnce(Return(false))
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
                 event->write(tagId);
                 event->write(100);
                 event->init();
@@ -504,14 +686,15 @@
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
                 event->write(tagId);
                 event->write(120);
                 event->init();
                 data->push_back(event);
                 return true;
             }));
-    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
+    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
     valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
 
@@ -523,7 +706,7 @@
     EXPECT_EQ(bucket2StartTimeNs-50, valueProducer.mCurrentBucketStartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
     EXPECT_EQ(bucketStartTimeNs, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
-    EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mValueLong);
+    EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
     EXPECT_FALSE(valueProducer.mCondition);
 }
 
@@ -534,11 +717,18 @@
     metric.mutable_value_field()->set_field(tagId);
     metric.mutable_value_field()->add_child()->set_field(2);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
 
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+                                      pullerManager);
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -551,7 +741,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(10, curInterval.value.long_value);
     EXPECT_EQ(true, curInterval.hasValue);
 
@@ -559,13 +749,13 @@
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(30, curInterval.value.long_value);
 
     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
 }
 
 TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
@@ -575,11 +765,18 @@
     metric.mutable_value_field()->set_field(tagId);
     metric.mutable_value_field()->add_child()->set_field(2);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
 
-    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, -1, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
+    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+                                      pullerManager);
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -587,9 +784,7 @@
     event1->init();
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
     // has 1 slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(false, curInterval.hasValue);
+    EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
 
     valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
     shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
@@ -600,7 +795,8 @@
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(20, curInterval.value.long_value);
 
     shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 30);
@@ -611,7 +807,7 @@
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(50, curInterval.value.long_value);
 
     valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
@@ -623,13 +819,13 @@
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(50, curInterval.value.long_value);
 
     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(50, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    EXPECT_EQ(50, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
 }
 
 TEST(ValueMetricProducerTest, TestAnomalyDetection) {
@@ -648,11 +844,17 @@
     metric.mutable_value_field()->set_field(tagId);
     metric.mutable_value_field()->add_child()->set_field(2);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      -1 /*not pulled*/, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
+                                      logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
+                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
 
     sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
 
@@ -723,14 +925,21 @@
     metric.mutable_value_field()->set_field(tagId);
     metric.mutable_value_field()->add_child()->set_field(2);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(false));
+    EXPECT_CALL(*pullerManager, Pull(tagId, _, _)).WillOnce(Return(true));
 
     ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+                                      logEventMatcherIndex, eventMatcherWizard, tagId,
+                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
 
     vector<shared_ptr<LogEvent>> allData;
     // pull 1
@@ -744,12 +953,12 @@
     valueProducer.onDataPulled(allData);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
 
     // startUpdated:true sum:0 start:11
-    EXPECT_EQ(true, curInterval.startUpdated);
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(11, curInterval.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(11, curInterval.start.long_value);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // pull 2 at correct time
@@ -762,13 +971,13 @@
     valueProducer.onDataPulled(allData);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     // tartUpdated:false sum:12
-    EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(23, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(12, curInterval.value.long_value);
+    EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // pull 3 come late.
     // The previous bucket gets closed with error. (Has start value 23, no ending)
@@ -782,14 +991,14 @@
     allData.push_back(event);
     valueProducer.onDataPulled(allData);
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     // startUpdated:false sum:12
-    EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(36, curInterval.start.long_value);
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(36, curInterval.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
 }
 
 /*
@@ -804,18 +1013,23 @@
     metric.mutable_value_field()->add_child()->set_field(2);
     metric.set_condition(StringToId("SCREEN_ON"));
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
 
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
-            .WillOnce(Return(false))
             // condition becomes true
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
                 event->write(tagId);
                 event->write(100);
                 event->init();
@@ -826,7 +1040,7 @@
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
                 event->write(tagId);
                 event->write(120);
                 event->init();
@@ -834,24 +1048,25 @@
                 return true;
             }));
 
-    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
+    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
     valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false sum:0 start:100
-    EXPECT_EQ(100, curInterval.start.long_value);
-    EXPECT_EQ(true, curInterval.startUpdated);
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(100, curInterval.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // pull on bucket boundary come late, condition change happens before it
     valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(false, curInterval.startUpdated);
-    EXPECT_EQ(false, curInterval.hasValue);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(false, curInterval.hasBase);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(20, curInterval.value.long_value);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // Now the alarm is delivered.
@@ -865,9 +1080,10 @@
     allData.push_back(event);
     valueProducer.onDataPulled(allData);
 
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(false, curInterval.startUpdated);
-    EXPECT_EQ(false, curInterval.hasValue);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(false, curInterval.hasBase);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(20, curInterval.value.long_value);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 }
 
@@ -883,18 +1099,23 @@
     metric.mutable_value_field()->add_child()->set_field(2);
     metric.set_condition(StringToId("SCREEN_ON"));
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
     EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillRepeatedly(Return());
     EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
 
     EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
-            .WillOnce(Return(false))
             // condition becomes true
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
                 event->write(tagId);
                 event->write(100);
                 event->init();
@@ -905,7 +1126,7 @@
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
                 event->write(tagId);
                 event->write(120);
                 event->init();
@@ -916,7 +1137,7 @@
             .WillOnce(Invoke([](int tagId, int64_t timeNs,
                                 vector<std::shared_ptr<LogEvent>>* data) {
                 data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 30);
+                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 25);
                 event->write(tagId);
                 event->write(130);
                 event->init();
@@ -924,32 +1145,35 @@
                 return true;
             }));
 
-    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
+    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, tagId, bucketStartTimeNs,
                                       bucketStartTimeNs, pullerManager);
     valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     // startUpdated:false sum:0 start:100
-    EXPECT_EQ(100, curInterval.start.long_value);
-    EXPECT_EQ(true, curInterval.startUpdated);
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(100, curInterval.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // pull on bucket boundary come late, condition change happens before it
     valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(false, curInterval.startUpdated);
-    EXPECT_EQ(false, curInterval.hasValue);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(false, curInterval.hasBase);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(20, curInterval.value.long_value);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // condition changed to true again, before the pull alarm is delivered
     valueProducer.onConditionChanged(true, bucket2StartTimeNs + 25);
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(130, curInterval.start.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(130, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(20, curInterval.value.long_value);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 
     // Now the alarm is delivered, but it is considered late, it has no effect
@@ -962,90 +1186,11 @@
     allData.push_back(event);
     valueProducer.onDataPulled(allData);
 
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(130, curInterval.start.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
-}
-
-/*
- * Test pulled event with non sliced condition. The pull on boundary come late because the puller is
- * very slow.
- */
-TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition3) {
-    ValueMetric metric;
-    metric.set_id(metricId);
-    metric.set_bucket(ONE_MINUTE);
-    metric.mutable_value_field()->set_field(tagId);
-    metric.mutable_value_field()->add_child()->set_field(2);
-    metric.set_condition(StringToId("SCREEN_ON"));
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
-    EXPECT_CALL(*pullerManager, Pull(tagId, _, _))
-            .WillOnce(Return(false))
-            // condition becomes true
-            .WillOnce(Invoke([](int tagId, int64_t timeNs,
-                                vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write(tagId);
-                event->write(100);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // condition becomes false
-            .WillOnce(Invoke([](int tagId, int64_t timeNs,
-                                vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 20);
-                event->write(tagId);
-                event->write(120);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, tagId, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
-    valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    // startUpdated:false sum:0 start:100
-    EXPECT_EQ(100, curInterval.start.long_value);
-    EXPECT_EQ(true, curInterval.startUpdated);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
-
-    // pull on bucket boundary come late, condition change happens before it.
-    // But puller is very slow in this one, so the data come after bucket finish
-    valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(false, curInterval.startUpdated);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
-
-    // Alarm is delivered in time, but the pull is very slow, and pullers are called in order,
-    // so this one comes even later
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 30);
-    event->write(1);
-    event->write(110);
-    event->init();
-    allData.push_back(event);
-    valueProducer.onDataPulled(allData);
-
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(false, curInterval.startUpdated);
-    EXPECT_EQ(false, curInterval.hasValue);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(130, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(20, curInterval.value.long_value);
     EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
 }
 
@@ -1057,11 +1202,18 @@
     metric.mutable_value_field()->add_child()->set_field(2);
     metric.set_aggregation_type(ValueMetric::MIN);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
 
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+                                      pullerManager);
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -1074,7 +1226,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(10, curInterval.value.long_value);
     EXPECT_EQ(true, curInterval.hasValue);
 
@@ -1082,13 +1234,13 @@
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(10, curInterval.value.long_value);
 
     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
 }
 
 TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
@@ -1099,11 +1251,18 @@
     metric.mutable_value_field()->add_child()->set_field(2);
     metric.set_aggregation_type(ValueMetric::MAX);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
 
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+                                      pullerManager);
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -1116,7 +1275,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(10, curInterval.value.long_value);
     EXPECT_EQ(true, curInterval.hasValue);
 
@@ -1124,13 +1283,13 @@
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(20, curInterval.value.long_value);
 
     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
 }
 
 TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
@@ -1141,11 +1300,18 @@
     metric.mutable_value_field()->add_child()->set_field(2);
     metric.set_aggregation_type(ValueMetric::AVG);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
 
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+                                      pullerManager);
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -1159,7 +1325,7 @@
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
     ValueMetricProducer::Interval curInterval;
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(10, curInterval.value.long_value);
     EXPECT_EQ(true, curInterval.hasValue);
     EXPECT_EQ(1, curInterval.sampleSize);
@@ -1168,14 +1334,14 @@
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(25, curInterval.value.long_value);
     EXPECT_EQ(2, curInterval.sampleSize);
 
     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(12.5, valueProducer.mPastBuckets.begin()->second.back().mValueDouble);
+    EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value - 12.5) < epsilon);
 }
 
 TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
@@ -1186,11 +1352,18 @@
     metric.mutable_value_field()->add_child()->set_field(2);
     metric.set_aggregation_type(ValueMetric::SUM);
 
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
 
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, -1, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+                                      pullerManager);
 
     shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
     event1->write(1);
@@ -1203,7 +1376,7 @@
     valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(10, curInterval.value.long_value);
     EXPECT_EQ(true, curInterval.hasValue);
 
@@ -1211,73 +1384,88 @@
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
     EXPECT_EQ(25, curInterval.value.long_value);
 
     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(25, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    EXPECT_EQ(25, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
 }
 
-TEST(ValueMetricProducerTest, TestPushedAggregateSumSliced) {
-    string slicedConditionName = "UID";
-    const int conditionTagId = 2;
+TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
     ValueMetric metric;
     metric.set_id(metricId);
     metric.set_bucket(ONE_MINUTE);
     metric.mutable_value_field()->set_field(tagId);
-    metric.mutable_value_field()->add_child()->set_field(1);
-    metric.set_aggregation_type(ValueMetric::SUM);
+    metric.mutable_value_field()->add_child()->set_field(2);
+    metric.set_aggregation_type(ValueMetric::MIN);
+    metric.set_use_diff(true);
 
-    metric.set_condition(StringToId(slicedConditionName));
-    MetricConditionLink* link = metric.add_links();
-    link->set_condition(StringToId(slicedConditionName));
-    buildSimpleAtomFieldMatcher(tagId, 2, link->mutable_fields_in_what());
-    buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
-
-    LogEvent event1(tagId, bucketStartTimeNs + 10);
-    event1.write(10);  // value
-    event1.write("111"); // uid
-    event1.init();
-    ConditionKey key1;
-    key1[StringToId(slicedConditionName)] =
-        {getMockedDimensionKey(conditionTagId, 2, "111")};
-
-    LogEvent event2(tagId, bucketStartTimeNs + 20);
-    event2.write(15);
-    event2.write("222");
-    event2.init();
-    ConditionKey key2;
-    key2[StringToId(slicedConditionName)] =
-        {getMockedDimensionKey(conditionTagId, 2, "222")};
-
+    UidMap uidMap;
+    SimpleAtomMatcher atomMatcher;
+    atomMatcher.set_atom_id(tagId);
+    sp<EventMatcherWizard> eventMatcherWizard =
+            new EventMatcherWizard({new SimpleLogMatchingTracker(
+                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
     sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    EXPECT_CALL(*wizard, query(_, key1, _, _, _, _)).WillOnce(Return(ConditionState::kFalse));
-    EXPECT_CALL(*wizard, query(_, key2, _, _, _, _)).WillOnce(Return(ConditionState::kTrue));
-
     sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
 
-    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, -1, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
+    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+                                      pullerManager);
 
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
-
+    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+    event1->write(1);
+    event1->write(10);
+    event1->init();
+    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+    event2->write(1);
+    event2->write(15);
+    event2->init();
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+    // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
+    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(10, curInterval.base.long_value);
     EXPECT_EQ(false, curInterval.hasValue);
 
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
 
     // has one slice
     EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second;
-    EXPECT_EQ(15, curInterval.value.long_value);
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasValue);
+    EXPECT_EQ(5, curInterval.value.long_value);
+
+    // no change in data.
+    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
+    event3->write(1);
+    event3->write(15);
+    event3->init();
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(15, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
+
+    shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
+    event4->write(1);
+    event4->write(15);
+    event4->init();
+    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+    EXPECT_EQ(true, curInterval.hasBase);
+    EXPECT_EQ(15, curInterval.base.long_value);
+    EXPECT_EQ(true, curInterval.hasValue);
 
     valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
     EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(15, valueProducer.mPastBuckets.begin()->second.back().mValueLong);
+    EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
 }
 
 }  // namespace statsd
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index ff436f1..e5764f0 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -24213,7 +24213,90 @@
 HSPLandroid/icu/util/CharsTrie;->next(I)Landroid/icu/util/BytesTrie$Result;
 HSPLandroid/icu/util/CharsTrie;->nextImpl(II)Landroid/icu/util/BytesTrie$Result;
 HSPLandroid/icu/util/CharsTrie;->readValue(Ljava/lang/CharSequence;II)I
-HSPLandroid/icu/util/Currency$1;-><init>()V
+HSPLandroid/icu/util/CodePointTrie$Small8;->fromBinary(Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Small8;
+HSPLandroid/icu/util/CodePointTrie$Small32;->fromBinary(Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Small32;
+HSPLandroid/icu/util/CodePointTrie$Small16;->fromBinary(Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Small16;
+HSPLandroid/icu/util/CodePointTrie$Fast8;->fromBinary(Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Fast8;
+HSPLandroid/icu/util/CodePointTrie$Fast8;->bmpGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast8;->get(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast8;->suppGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast32;->fromBinary(Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Fast32;
+HSPLandroid/icu/util/CodePointTrie$Fast32;->bmpGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast32;->get(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast32;->suppGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast16;->fromBinary(Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Fast16;
+HSPLandroid/icu/util/CodePointTrie$Fast16;->bmpGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast16;->get(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast16;->suppGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Small;->fromBinary(Landroid/icu/util/CodePointTrie$ValueWidth;Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Small;
+HSPLandroid/icu/util/CodePointTrie$Small;->cpIndex(I)I
+HSPLandroid/icu/util/CodePointTrie$Small;->getType()Landroid/icu/util/CodePointTrie$Type;
+HSPLandroid/icu/util/CodePointTrie$Small;->stringIterator(Ljava/lang/CharSequence;I)Landroid/icu/util/CodePointMap$StringIterator;
+HSPLandroid/icu/util/CodePointTrie$Fast;->fromBinary(Landroid/icu/util/CodePointTrie$ValueWidth;Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie$Fast;
+HSPLandroid/icu/util/CodePointTrie$Fast;->bmpGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast;->cpIndex(I)I
+HSPLandroid/icu/util/CodePointTrie$Fast;->getType()Landroid/icu/util/CodePointTrie$Type;
+HSPLandroid/icu/util/CodePointTrie$Fast;->stringIterator(Ljava/lang/CharSequence;I)Landroid/icu/util/CodePointMap$StringIterator;
+HSPLandroid/icu/util/CodePointTrie$Fast;->suppGet(I)I
+HSPLandroid/icu/util/CodePointTrie$Data8;->getDataLength()I
+HSPLandroid/icu/util/CodePointTrie$Data8;->getFromIndex(I)I
+HSPLandroid/icu/util/CodePointTrie$Data8;->getValueWidth()Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie$Data8;->write(Ljava/io/DataOutputStream;)I
+HSPLandroid/icu/util/CodePointTrie$Data32;->getDataLength()I
+HSPLandroid/icu/util/CodePointTrie$Data32;->getFromIndex(I)I
+HSPLandroid/icu/util/CodePointTrie$Data32;->getValueWidth()Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie$Data32;->write(Ljava/io/DataOutputStream;)I
+HSPLandroid/icu/util/CodePointTrie$Data16;->getDataLength()I
+HSPLandroid/icu/util/CodePointTrie$Data16;->getFromIndex(I)I
+HSPLandroid/icu/util/CodePointTrie$Data16;->getValueWidth()Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie$Data16;->write(Ljava/io/DataOutputStream;)I
+HSPLandroid/icu/util/CodePointTrie$Data;->getDataLength()I
+HSPLandroid/icu/util/CodePointTrie$Data;->getFromIndex(I)I
+HSPLandroid/icu/util/CodePointTrie$Data;->getValueWidth()Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie$Data;->write(Ljava/io/DataOutputStream;)I
+HSPLandroid/icu/util/CodePointTrie$ValueWidth;->valueOf(Ljava/lang/String;)Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie$ValueWidth;->values()[Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie$Type;->valueOf(Ljava/lang/String;)Landroid/icu/util/CodePointTrie$Type;
+HSPLandroid/icu/util/CodePointTrie$Type;->values()[Landroid/icu/util/CodePointTrie$Type;
+HSPLandroid/icu/util/CodePointTrie;->fromBinary(Landroid/icu/util/CodePointTrie$Type;Landroid/icu/util/CodePointTrie$ValueWidth;Ljava/nio/ByteBuffer;)Landroid/icu/util/CodePointTrie;
+HSPLandroid/icu/util/CodePointTrie;->internalSmallIndex(Landroid/icu/util/CodePointTrie$Type;I)I
+HSPLandroid/icu/util/CodePointTrie;->maybeFilterValue(IIILandroid/icu/util/CodePointMap$ValueFilter;)I
+HSPLandroid/icu/util/CodePointTrie;->asciiGet(I)I
+HSPLandroid/icu/util/CodePointTrie;->cpIndex(I)I
+HSPLandroid/icu/util/CodePointTrie;->fastIndex(I)I
+HSPLandroid/icu/util/CodePointTrie;->get(I)I
+HSPLandroid/icu/util/CodePointTrie;->getRange(ILandroid/icu/util/CodePointMap$ValueFilter;Landroid/icu/util/CodePointMap$Range;)Z
+HSPLandroid/icu/util/CodePointTrie;->getType()Landroid/icu/util/CodePointTrie$Type;
+HSPLandroid/icu/util/CodePointTrie;->getValueWidth()Landroid/icu/util/CodePointTrie$ValueWidth;
+HSPLandroid/icu/util/CodePointTrie;->smallIndex(Landroid/icu/util/CodePointTrie$Type;I)I
+HSPLandroid/icu/util/CodePointTrie;->toBinary(Ljava/io/OutputStream;)I
+HSPLandroid/icu/util/CodePointMap$StringIterator;->getCodePoint()I
+HSPLandroid/icu/util/CodePointMap$StringIterator;->getIndex()I
+HSPLandroid/icu/util/CodePointMap$StringIterator;->getValue()I
+HSPLandroid/icu/util/CodePointMap$StringIterator;->next()Z
+HSPLandroid/icu/util/CodePointMap$StringIterator;->previous()Z
+HSPLandroid/icu/util/CodePointMap$StringIterator;->reset(Ljava/lang/CharSequence;I)V
+HSPLandroid/icu/util/CodePointMap$RangeIterator;->hasNext()Z
+HSPLandroid/icu/util/CodePointMap$RangeIterator;->next()Landroid/icu/util/CodePointMap$Range;
+HSPLandroid/icu/util/CodePointMap$RangeIterator;->next()Ljava/lang/Object;
+HSPLandroid/icu/util/CodePointMap$RangeIterator;->remove()V
+HSPLandroid/icu/util/CodePointMap$Range;->access$000(Landroid/icu/util/CodePointMap$Range;)I
+HSPLandroid/icu/util/CodePointMap$Range;->access$002(Landroid/icu/util/CodePointMap$Range;I)I
+HSPLandroid/icu/util/CodePointMap$Range;->access$100(Landroid/icu/util/CodePointMap$Range;)I
+HSPLandroid/icu/util/CodePointMap$Range;->access$102(Landroid/icu/util/CodePointMap$Range;I)I
+HSPLandroid/icu/util/CodePointMap$Range;->access$202(Landroid/icu/util/CodePointMap$Range;I)I
+HSPLandroid/icu/util/CodePointMap$Range;->getEnd()I
+HSPLandroid/icu/util/CodePointMap$Range;->getStart()I
+HSPLandroid/icu/util/CodePointMap$Range;->getValue()I
+HSPLandroid/icu/util/CodePointMap$Range;->set(III)V
+HSPLandroid/icu/util/CodePointMap$ValueFilter;->apply(I)I
+HSPLandroid/icu/util/CodePointMap$RangeOption;->valueOf(Ljava/lang/String;)Landroid/icu/util/CodePointMap$RangeOption;
+HSPLandroid/icu/util/CodePointMap$RangeOption;->values()[Landroid/icu/util/CodePointMap$RangeOption;
+HSPLandroid/icu/util/CodePointMap;->get(I)I
+HSPLandroid/icu/util/CodePointMap;->getRange(ILandroid/icu/util/CodePointMap$RangeOption;ILandroid/icu/util/CodePointMap$ValueFilter;Landroid/icu/util/CodePointMap$Range;)Z
+HSPLandroid/icu/util/CodePointMap;->getRange(ILandroid/icu/util/CodePointMap$ValueFilter;Landroid/icu/util/CodePointMap$Range;)Z
+HSPLandroid/icu/util/CodePointMap;->iterator()Ljava/util/Iterator;
+HSPLandroid/icu/util/CodePointMap;->stringIterator(Ljava/lang/CharSequence;I)Landroid/icu/util/CodePointMap$StringIterator;HSPLandroid/icu/util/Currency$1;-><init>()V
 HSPLandroid/icu/util/Currency$1;->createInstance(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 HSPLandroid/icu/util/Currency$1;->createInstance(Ljava/lang/String;Ljava/lang/Void;)Landroid/icu/util/Currency;
 HSPLandroid/icu/util/Currency$CurrencyUsage;-><init>(Ljava/lang/String;I)V
@@ -24259,6 +24342,61 @@
 HSPLandroid/icu/util/MeasureUnit;->equals(Ljava/lang/Object;)Z
 HSPLandroid/icu/util/MeasureUnit;->hashCode()I
 HSPLandroid/icu/util/MeasureUnit;->internalGetInstance(Ljava/lang/String;Ljava/lang/String;)Landroid/icu/util/MeasureUnit;
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->addEntry([I[CIII)V
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->findEntry([III)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->findEntry([I[C[I[CII)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->makeHashCode(I)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->makeHashCode([CI)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->makeHashCode([II)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->modulo(II)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->nextIndex(II)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->extend([CIII)V
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->extend([IIII)V
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->findAllSameBlock([II)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->findBlock([C[CI)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->findBlock([C[II)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->findBlock([I[II)I
+HSPLandroid/icu/util/MutableCodePointTrie$MixedBlocks;->init(II)V
+HSPLandroid/icu/util/MutableCodePointTrie$AllSameBlocks;->add(III)V
+HSPLandroid/icu/util/MutableCodePointTrie$AllSameBlocks;->findMostUsed()I
+HSPLandroid/icu/util/MutableCodePointTrie$AllSameBlocks;->findOrAdd(III)I
+HSPLandroid/icu/util/MutableCodePointTrie;->access$000([II[III)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->access$100([CI[III)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->access$200([CI[CII)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->access$300([IIII)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->allValuesSameAs([IIII)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->allocDataBlock(I)I
+HSPLandroid/icu/util/MutableCodePointTrie;->build(Landroid/icu/util/CodePointTrie$Type;Landroid/icu/util/CodePointTrie$ValueWidth;)Landroid/icu/util/CodePointTrie;
+HSPLandroid/icu/util/MutableCodePointTrie;->clear()V
+HSPLandroid/icu/util/MutableCodePointTrie;->compactData(I[IILandroid/icu/util/MutableCodePointTrie$MixedBlocks;)I
+HSPLandroid/icu/util/MutableCodePointTrie;->compactIndex(ILandroid/icu/util/MutableCodePointTrie$MixedBlocks;)I
+HSPLandroid/icu/util/MutableCodePointTrie;->compactTrie(I)I
+HSPLandroid/icu/util/MutableCodePointTrie;->compactWholeDataBlocks(ILandroid/icu/util/MutableCodePointTrie$AllSameBlocks;)I
+HSPLandroid/icu/util/MutableCodePointTrie;->ensureHighStart(I)V
+HSPLandroid/icu/util/MutableCodePointTrie;->equalBlocks([CI[CII)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->equalBlocks([CI[III)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->equalBlocks([II[III)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->fillBlock(IIII)V
+HSPLandroid/icu/util/MutableCodePointTrie;->findAllSameBlock([IIIII)I
+HSPLandroid/icu/util/MutableCodePointTrie;->findHighStart()I
+HSPLandroid/icu/util/MutableCodePointTrie;->findSameBlock([CII[CII)I
+HSPLandroid/icu/util/MutableCodePointTrie;->fromCodePointMap(Landroid/icu/util/CodePointMap;)Landroid/icu/util/MutableCodePointTrie;
+HSPLandroid/icu/util/MutableCodePointTrie;->getAllSameOverlap([IIII)I
+HSPLandroid/icu/util/MutableCodePointTrie;->getDataBlock(I)I
+HSPLandroid/icu/util/MutableCodePointTrie;->getOverlap([CI[CII)I
+HSPLandroid/icu/util/MutableCodePointTrie;->getOverlap([CI[III)I
+HSPLandroid/icu/util/MutableCodePointTrie;->getOverlap([II[III)I
+HSPLandroid/icu/util/MutableCodePointTrie;->isStartOfSomeFastBlock(I[II)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->maskValues(I)V
+HSPLandroid/icu/util/MutableCodePointTrie;->maybeFilterValue(IIILandroid/icu/util/CodePointMap$ValueFilter;)I
+HSPLandroid/icu/util/MutableCodePointTrie;->writeBlock(II)V
+HSPLandroid/icu/util/MutableCodePointTrie;->buildImmutable(Landroid/icu/util/CodePointTrie$Type;Landroid/icu/util/CodePointTrie$ValueWidth;)Landroid/icu/util/CodePointTrie;
+HSPLandroid/icu/util/MutableCodePointTrie;->clone()Landroid/icu/util/MutableCodePointTrie;
+HSPLandroid/icu/util/MutableCodePointTrie;->clone()Ljava/lang/Object;
+HSPLandroid/icu/util/MutableCodePointTrie;->get(I)I
+HSPLandroid/icu/util/MutableCodePointTrie;->getRange(ILandroid/icu/util/CodePointMap$ValueFilter;Landroid/icu/util/CodePointMap$Range;)Z
+HSPLandroid/icu/util/MutableCodePointTrie;->set(II)V
+HSPLandroid/icu/util/MutableCodePointTrie;->setRange(III)V
 HSPLandroid/icu/util/SimpleTimeZone;-><init>(ILjava/lang/String;IIIIIIIIIII)V
 HSPLandroid/icu/util/SimpleTimeZone;->clone()Ljava/lang/Object;
 HSPLandroid/icu/util/SimpleTimeZone;->cloneAsThawed()Landroid/icu/util/TimeZone;
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 43e926f..39b327c 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1,4 +1,6 @@
 Landroid/accessibilityservice/IAccessibilityServiceConnection$Stub;->asInterface(Landroid/os/IBinder;)Landroid/accessibilityservice/IAccessibilityServiceConnection;
+Landroid/accounts/AccountManager$AmsTask;-><init>(Landroid/accounts/AccountManager;Landroid/app/Activity;Landroid/os/Handler;Landroid/accounts/AccountManagerCallback;)V
+Landroid/accounts/AccountManager$Future2Task;-><init>(Landroid/accounts/AccountManager;Landroid/os/Handler;Landroid/accounts/AccountManagerCallback;)V
 Landroid/accounts/IAccountAuthenticator$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/accounts/IAccountAuthenticator$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/accounts/IAccountAuthenticator$Stub;-><init>()V
@@ -30,6 +32,7 @@
 Landroid/app/ActivityManagerNative;-><init>()V
 Landroid/app/ActivityThread$AppBindData;-><init>()V
 Landroid/app/ActivityThread$CreateServiceData;-><init>()V
+Landroid/app/ActivityThread$H;-><init>(Landroid/app/ActivityThread;)V
 Landroid/app/admin/IDevicePolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/admin/IDevicePolicyManager;
 Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_packageHasActiveAdmins:I
 Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_removeActiveAdmin:I
@@ -212,6 +215,7 @@
 Landroid/app/job/IJobService;->stopJob(Landroid/app/job/JobParameters;)V
 Landroid/app/PackageDeleteObserver;-><init>()V
 Landroid/app/PackageInstallObserver;-><init>()V
+Landroid/app/ReceiverRestrictedContext;-><init>(Landroid/content/Context;)V
 Landroid/app/ResourcesManager$ActivityResources;-><init>()V
 Landroid/app/ResourcesManager;-><init>()V
 Landroid/app/TaskStackListener;-><init>()V
@@ -262,6 +266,7 @@
 Landroid/bluetooth/IBluetoothManagerCallback$Stub;-><init>()V
 Landroid/bluetooth/IBluetoothPbap$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothPbap;
 Landroid/bluetooth/IBluetoothStateChangeCallback$Stub;-><init>()V
+Landroid/content/ContentProviderProxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/IClipboard$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard;
 Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -415,9 +420,14 @@
 Landroid/content/res/ConfigurationBoundResourceCache;-><init>()V
 Landroid/content/res/DrawableCache;-><init>()V
 Landroid/content/UndoManager;-><init>()V
+Landroid/database/BulkCursorProxy;->mRemote:Landroid/os/IBinder;
 Landroid/database/IContentObserver$Stub;-><init>()V
 Landroid/database/IContentObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/database/IContentObserver;
 Landroid/database/IContentObserver;->onChange(ZLandroid/net/Uri;I)V
+Landroid/database/sqlite/SQLiteConnectionPool;->$assertionsDisabled:Z
+Landroid/database/sqlite/SQLiteDatabase;->$assertionsDisabled:Z
+Landroid/filterfw/GraphEnvironment;->addReferences([Ljava/lang/Object;)V
+Landroid/hardware/camera2/utils/HashCodeHelpers;->hashCode([I)I
 Landroid/hardware/display/IDisplayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/display/IDisplayManager;
 Landroid/hardware/display/IDisplayManager;->getDisplayInfo(I)Landroid/view/DisplayInfo;
 Landroid/hardware/fingerprint/IFingerprintService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -431,37 +441,8 @@
 Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService;
 Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager;
-Landroid/icu/impl/CurrencyData;-><init>()V
-Landroid/icu/text/ArabicShaping;-><init>(I)V
-Landroid/icu/text/ArabicShaping;->isAlefMaksouraChar(C)Z
-Landroid/icu/text/ArabicShaping;->isSeenTailFamilyChar(C)I
-Landroid/icu/text/ArabicShaping;->isTailChar(C)Z
-Landroid/icu/text/ArabicShaping;->isYehHamzaChar(C)Z
-Landroid/icu/text/ArabicShaping;->shape(Ljava/lang/String;)Ljava/lang/String;
-Landroid/icu/text/DateFormatSymbols;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/text/DateIntervalFormat;-><init>()V
-Landroid/icu/text/DateTimePatternGenerator$DistanceInfo;-><init>()V
-Landroid/icu/text/DecimalFormatSymbols;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/text/RuleBasedCollator;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/text/SpoofChecker$ScriptSet;-><init>()V
-Landroid/icu/text/SpoofChecker$ScriptSet;->and(I)V
-Landroid/icu/text/SpoofChecker$ScriptSet;->isFull()Z
-Landroid/icu/text/SpoofChecker$ScriptSet;->setAll()V
-Landroid/icu/text/TimeZoneNames$DefaultTimeZoneNames$FactoryImpl;-><init>()V
-Landroid/icu/text/Transliterator;->createFromRules(Ljava/lang/String;Ljava/lang/String;I)Landroid/icu/text/Transliterator;
-Landroid/icu/text/Transliterator;->getInstance(Ljava/lang/String;)Landroid/icu/text/Transliterator;
-Landroid/icu/text/Transliterator;->getInstance(Ljava/lang/String;I)Landroid/icu/text/Transliterator;
-Landroid/icu/text/Transliterator;->transliterate(Landroid/icu/text/Replaceable;Landroid/icu/text/Transliterator$Position;Ljava/lang/String;)V
-Landroid/icu/text/Transliterator;->transliterate(Ljava/lang/String;)Ljava/lang/String;
-Landroid/icu/text/UFormat;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/util/Calendar;->getLocale(Landroid/icu/util/ULocale$Type;)Landroid/icu/util/ULocale;
-Landroid/icu/util/PersianCalendar;-><init>(Ljava/util/Locale;)V
-Landroid/icu/util/UResourceBundle;->getBundleInstance(Ljava/lang/String;Landroid/icu/util/ULocale;)Landroid/icu/util/UResourceBundle;
-Landroid/icu/util/UResourceBundle;->getKey()Ljava/lang/String;
-Landroid/icu/util/UResourceBundle;->getString()Ljava/lang/String;
-Landroid/icu/util/UResourceBundle;->getType()I
-Landroid/icu/util/UResourceBundleIterator;->hasNext()Z
-Landroid/icu/util/UResourceBundleIterator;->next()Landroid/icu/util/UResourceBundle;
+Landroid/inputmethodservice/IInputMethodSessionWrapper;->mCaller:Lcom/android/internal/os/HandlerCaller;
+Landroid/inputmethodservice/IInputMethodWrapper;->mCaller:Lcom/android/internal/os/HandlerCaller;
 Landroid/location/ICountryDetector$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ICountryDetector;
 Landroid/location/ICountryListener$Stub;-><init>()V
 Landroid/location/IGeocodeProvider$Stub;-><init>()V
@@ -479,9 +460,11 @@
 Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager;
 Landroid/location/ILocationManager$Stub;->TRANSACTION_getAllProviders:I
 Landroid/location/ILocationManager;->getAllProviders()Ljava/util/List;
+Landroid/location/LocationManager$ListenerTransport;-><init>(Landroid/location/LocationManager;Landroid/location/LocationListener;Landroid/os/Looper;)V
 Landroid/Manifest$permission;->CAPTURE_SECURE_VIDEO_OUTPUT:Ljava/lang/String;
 Landroid/Manifest$permission;->CAPTURE_VIDEO_OUTPUT:Ljava/lang/String;
 Landroid/Manifest$permission;->READ_FRAME_BUFFER:Ljava/lang/String;
+Landroid/media/effect/SingleFilterEffect;-><init>(Landroid/media/effect/EffectContext;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
 Landroid/media/IAudioFocusDispatcher;->dispatchAudioFocusChange(ILjava/lang/String;)V
 Landroid/media/IAudioRoutesObserver$Stub;-><init>()V
 Landroid/media/IAudioService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -500,6 +483,7 @@
 Landroid/media/IRingtonePlayer;->play(Landroid/os/IBinder;Landroid/net/Uri;Landroid/media/AudioAttributes;FZ)V
 Landroid/media/IVolumeController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IVolumeController;
 Landroid/media/MediaFile;-><init>()V
+Landroid/media/MediaScanner$MyMediaScannerClient;-><init>(Landroid/media/MediaScanner;)V
 Landroid/media/projection/IMediaProjectionManager;->hasProjectionPermission(ILjava/lang/String;)Z
 Landroid/media/session/ISessionManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/session/ISessionManager;
 Landroid/net/IConnectivityManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -547,6 +531,7 @@
 Landroid/net/MobileLinkQualityInfo;-><init>()V
 Landroid/net/nsd/INsdManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/nsd/INsdManager;
 Landroid/net/nsd/INsdManager;->getMessenger()Landroid/os/Messenger;
+Landroid/net/sip/ISipSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/sip/ISipSession;
 Landroid/net/SntpClient;-><init>()V
 Landroid/net/wifi/IWifiManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/net/wifi/IWifiManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/wifi/IWifiManager;
@@ -637,6 +622,7 @@
 Landroid/os/BatteryStats;->computeBatteryTimeRemaining(J)J
 Landroid/os/BatteryStats;->computeBatteryUptime(JI)J
 Landroid/os/BatteryStats;->computeChargeTimeRemaining(J)J
+Landroid/os/BatteryStats;->dumpLine(Ljava/io/PrintWriter;ILjava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
 Landroid/os/BatteryStats;->getBatteryUptime(J)J
 Landroid/os/BatteryStats;->getGlobalWifiRunningTime(JI)J
 Landroid/os/BatteryStats;->getMobileRadioActiveTime(JI)J
@@ -725,6 +711,7 @@
 Landroid/os/Environment;->buildExternalStorageAppFilesDirs(Ljava/lang/String;)[Ljava/io/File;
 Landroid/os/Environment;->buildExternalStorageAppMediaDirs(Ljava/lang/String;)[Ljava/io/File;
 Landroid/os/Environment;->buildExternalStorageAppObbDirs(Ljava/lang/String;)[Ljava/io/File;
+Landroid/os/Environment;->buildPaths([Ljava/io/File;[Ljava/lang/String;)[Ljava/io/File;
 Landroid/os/Environment;->getDataSystemDirectory()Ljava/io/File;
 Landroid/os/Environment;->getLegacyExternalStorageObbDirectory()Ljava/io/File;
 Landroid/os/Environment;->initForCurrentUser()V
@@ -930,6 +917,8 @@
 Landroid/os/ServiceManager;->sCache:Ljava/util/Map;
 Landroid/os/ServiceManager;->sServiceManager:Landroid/os/IServiceManager;
 Landroid/os/ServiceManagerNative;->asInterface(Landroid/os/IBinder;)Landroid/os/IServiceManager;
+Landroid/os/ServiceManagerProxy;->getService(Ljava/lang/String;)Landroid/os/IBinder;
+Landroid/os/ServiceManagerProxy;->mRemote:Landroid/os/IBinder;
 Landroid/os/ServiceSpecificException;-><init>(ILjava/lang/String;)V
 Landroid/os/SharedMemory;->getFd()I
 Landroid/os/ShellCommand;->peekNextArg()Ljava/lang/String;
@@ -1064,6 +1053,7 @@
 Landroid/os/WorkSource;->updateLocked(Landroid/os/WorkSource;ZZ)Z
 Landroid/os/ZygoteStartFailedEx;-><init>(Ljava/lang/String;)V
 Landroid/os/ZygoteStartFailedEx;-><init>(Ljava/lang/Throwable;)V
+Landroid/preference/PreferenceGroupAdapter;->getItem(I)Landroid/preference/Preference;
 Landroid/R$styleable;->ActionBar:[I
 Landroid/R$styleable;->ActionBar_background:I
 Landroid/R$styleable;->ActionBar_backgroundSplit:I
@@ -1330,22 +1320,28 @@
 Landroid/security/Credentials;->convertToPem([Ljava/security/cert/Certificate;)[B
 Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService;
 Landroid/security/IKeyChainService;->requestPrivateKey(Ljava/lang/String;)Ljava/lang/String;
-Landroid/security/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeystoreService;
-Landroid/security/IKeystoreService;->clear_uid(J)I
-Landroid/security/IKeystoreService;->del(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->exist(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->generateKey(Ljava/lang/String;Landroid/security/keymaster/KeymasterArguments;[BIILandroid/security/keymaster/KeyCharacteristics;)I
-Landroid/security/IKeystoreService;->get(Ljava/lang/String;I)[B
-Landroid/security/IKeystoreService;->getState(I)I
-Landroid/security/IKeystoreService;->get_pubkey(Ljava/lang/String;)[B
-Landroid/security/IKeystoreService;->import_key(Ljava/lang/String;[BII)I
-Landroid/security/IKeystoreService;->insert(Ljava/lang/String;[BII)I
-Landroid/security/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
-Landroid/security/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
-Landroid/security/IKeystoreService;->reset()I
-Landroid/security/IKeystoreService;->sign(Ljava/lang/String;[B)[B
-Landroid/security/IKeystoreService;->ungrant(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->verify(Ljava/lang/String;[B[B)I
+Landroid/security/keymaster/KeymasterBlobArgument;-><init>(ILandroid/os/Parcel;)V
+Landroid/security/keymaster/KeymasterBlobArgument;-><init>(I[B)V
+Landroid/security/keymaster/KeymasterBlobArgument;->blob:[B
+Landroid/security/keymaster/KeymasterBooleanArgument;-><init>(ILandroid/os/Parcel;)V
+Landroid/security/keymaster/KeymasterDateArgument;-><init>(ILandroid/os/Parcel;)V
+Landroid/security/keymaster/KeymasterIntArgument;-><init>(II)V
+Landroid/security/keymaster/KeymasterIntArgument;-><init>(ILandroid/os/Parcel;)V
+Landroid/security/keymaster/KeymasterIntArgument;->value:I
+Landroid/security/keymaster/KeymasterLongArgument;-><init>(IJ)V
+Landroid/security/keymaster/KeymasterLongArgument;-><init>(ILandroid/os/Parcel;)V
+Landroid/security/keymaster/KeymasterLongArgument;->value:J
+Landroid/security/keystore/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/keystore/IKeystoreService;
+Landroid/security/keystore/IKeystoreService;->clear_uid(J)I
+Landroid/security/keystore/IKeystoreService;->del(Ljava/lang/String;I)I
+Landroid/security/keystore/IKeystoreService;->exist(Ljava/lang/String;I)I
+Landroid/security/keystore/IKeystoreService;->get(Ljava/lang/String;I)[B
+Landroid/security/keystore/IKeystoreService;->getState(I)I
+Landroid/security/keystore/IKeystoreService;->insert(Ljava/lang/String;[BII)I
+Landroid/security/keystore/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
+Landroid/security/keystore/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
+Landroid/security/keystore/IKeystoreService;->reset()I
+Landroid/security/keystore/IKeystoreService;->ungrant(Ljava/lang/String;I)I
 Landroid/service/carrier/ICarrierMessagingCallback$Stub;-><init>()V
 Landroid/service/carrier/ICarrierMessagingService;->filterSms(Landroid/service/carrier/MessagePdu;Ljava/lang/String;IILandroid/service/carrier/ICarrierMessagingCallback;)V
 Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
@@ -1383,9 +1379,42 @@
 Landroid/service/wallpaper/IWallpaperEngine;->setVisibility(Z)V
 Landroid/service/wallpaper/IWallpaperService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/wallpaper/IWallpaperService;
 Landroid/speech/IRecognitionListener;->onEvent(ILandroid/os/Bundle;)V
+Landroid/telecom/Log;->i(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
+Landroid/telecom/Log;->w(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
 Landroid/telephony/CarrierMessagingServiceManager;-><init>()V
+Landroid/telephony/JapanesePhoneNumberFormatter;->format(Landroid/text/Editable;)V
+Landroid/telephony/SmsCbCmasInfo;->getCategory()I
+Landroid/telephony/SmsCbCmasInfo;->getCertainty()I
+Landroid/telephony/SmsCbCmasInfo;->getMessageClass()I
+Landroid/telephony/SmsCbCmasInfo;->getResponseType()I
+Landroid/telephony/SmsCbCmasInfo;->getSeverity()I
+Landroid/telephony/SmsCbCmasInfo;->getUrgency()I
+Landroid/telephony/SmsCbEtwsInfo;->getWarningType()I
+Landroid/telephony/SmsCbLocation;-><init>(Ljava/lang/String;)V
+Landroid/telephony/SmsCbLocation;-><init>(Ljava/lang/String;II)V
+Landroid/telephony/SmsCbLocation;->getCid()I
+Landroid/telephony/SmsCbLocation;->getLac()I
+Landroid/telephony/SmsCbLocation;->getPlmn()Ljava/lang/String;
+Landroid/telephony/SmsCbMessage;-><init>(Landroid/os/Parcel;)V
+Landroid/telephony/SmsCbMessage;->getCmasWarningInfo()Landroid/telephony/SmsCbCmasInfo;
+Landroid/telephony/SmsCbMessage;->getEtwsWarningInfo()Landroid/telephony/SmsCbEtwsInfo;
+Landroid/telephony/SmsCbMessage;->getGeographicalScope()I
+Landroid/telephony/SmsCbMessage;->getLanguageCode()Ljava/lang/String;
+Landroid/telephony/SmsCbMessage;->getLocation()Landroid/telephony/SmsCbLocation;
+Landroid/telephony/SmsCbMessage;->getMessageBody()Ljava/lang/String;
+Landroid/telephony/SmsCbMessage;->getMessageFormat()I
+Landroid/telephony/SmsCbMessage;->getSerialNumber()I
+Landroid/telephony/SmsCbMessage;->getServiceCategory()I
+Landroid/telephony/SmsCbMessage;->isCmasMessage()Z
+Landroid/telephony/SmsCbMessage;->isEmergencyMessage()Z
 Landroid/telephony/TelephonyManager$MultiSimVariants;->values()[Landroid/telephony/TelephonyManager$MultiSimVariants;
+Landroid/test/AndroidTestCase;->getTestContext()Landroid/content/Context;
+Landroid/test/AndroidTestCase;->setTestContext(Landroid/content/Context;)V
+Landroid/test/InstrumentationTestCase;->runMethod(Ljava/lang/reflect/Method;I)V
+Landroid/test/RepetitiveTest;->numIterations()I
 Landroid/util/Singleton;-><init>()V
+Landroid/util/XmlPullAttributes;-><init>(Lorg/xmlpull/v1/XmlPullParser;)V
+Landroid/util/XmlPullAttributes;->mParser:Lorg/xmlpull/v1/XmlPullParser;
 Landroid/view/accessibility/IAccessibilityInteractionConnectionCallback;->setFindAccessibilityNodeInfoResult(Landroid/view/accessibility/AccessibilityNodeInfo;I)V
 Landroid/view/accessibility/IAccessibilityInteractionConnectionCallback;->setFindAccessibilityNodeInfosResult(Ljava/util/List;I)V
 Landroid/view/accessibility/IAccessibilityInteractionConnectionCallback;->setPerformAccessibilityActionResult(ZI)V
@@ -1443,7 +1472,9 @@
 Landroid/view/IWindowSession;->setTransparentRegion(Landroid/view/IWindow;Landroid/graphics/Region;)V
 Landroid/view/IWindowSession;->wallpaperCommandComplete(Landroid/os/IBinder;Landroid/os/Bundle;)V
 Landroid/view/IWindowSession;->wallpaperOffsetsComplete(Landroid/os/IBinder;)V
+Landroid/view/RenderNodeAnimator;->setDuration(J)Landroid/view/RenderNodeAnimator;
 Landroid/view/View$AttachInfo$InvalidateInfo;-><init>()V
+Landroid/view/View$CheckForLongPress;-><init>(Landroid/view/View;)V
 Landroid/view/View$ListenerInfo;-><init>()V
 Landroid/view/ViewTreeObserver$InternalInsetsInfo;-><init>()V
 Landroid/webkit/CacheManager$CacheResult;-><init>()V
@@ -1453,9 +1484,102 @@
 Landroid/webkit/IWebViewUpdateService;->getCurrentWebViewPackageName()Ljava/lang/String;
 Landroid/webkit/IWebViewUpdateService;->getValidWebViewPackages()[Landroid/webkit/WebViewProviderInfo;
 Landroid/webkit/IWebViewUpdateService;->isFallbackPackage(Ljava/lang/String;)Z
+Landroid/widget/DigitalClock$FormatChangeObserver;-><init>(Landroid/widget/DigitalClock;)V
+Landroid/widget/QuickContactBadge$QueryHandler;-><init>(Landroid/widget/QuickContactBadge;Landroid/content/ContentResolver;)V
 Landroid/widget/RelativeLayout$DependencyGraph$Node;-><init>()V
 Landroid/widget/ScrollBarDrawable;-><init>()V
+Lcom/android/i18n/phonenumbers/AsYouTypeFormatter;->clear()V
+Lcom/android/i18n/phonenumbers/AsYouTypeFormatter;->getRememberedPosition()I
+Lcom/android/i18n/phonenumbers/AsYouTypeFormatter;->inputDigit(C)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/AsYouTypeFormatter;->inputDigitAndRememberPosition(C)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder;->getDescriptionForNumber(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;Ljava/util/Locale;)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder;->getInstance()Lcom/android/i18n/phonenumbers/geocoding/PhoneNumberOfflineGeocoder;
+Lcom/android/i18n/phonenumbers/NumberParseException;->getErrorType()Lcom/android/i18n/phonenumbers/NumberParseException$ErrorType;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->getDomesticCarrierCodeFormattingRule()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->getFormat()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->getLeadingDigitsPattern(I)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->getNationalPrefixFormattingRule()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->getPattern()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$NumberFormat;->leadingDigitsPatternSize()I
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->getCountryCode()I
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->getGeneralDesc()Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneNumberDesc;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->getNationalPrefixForParsing()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->getNationalPrefixTransformRule()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->getPreferredExtnPrefix()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->hasNationalPrefix()Z
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->hasPreferredExtnPrefix()Z
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->intlNumberFormats()Ljava/util/List;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadata;->numberFormats()Ljava/util/List;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadataCollection;-><init>()V
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneMetadataCollection;->getMetadataList()Ljava/util/List;
+Lcom/android/i18n/phonenumbers/Phonemetadata$PhoneNumberDesc;->getNationalNumberPattern()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;->FROM_DEFAULT_COUNTRY:Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;->FROM_NUMBER_WITHOUT_PLUS_SIGN:Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;->FROM_NUMBER_WITH_IDD:Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;->FROM_NUMBER_WITH_PLUS_SIGN:Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;->values()[Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->clearCountryCode()Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->getCountryCode()I
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->getCountryCodeSource()Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber$CountryCodeSource;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->getExtension()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->getNationalNumber()J
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->hasCountryCode()Z
+Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;->hasExtension()Z
+Lcom/android/i18n/phonenumbers/PhoneNumberMatch;->end()I
+Lcom/android/i18n/phonenumbers/PhoneNumberMatch;->number()Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;
+Lcom/android/i18n/phonenumbers/PhoneNumberMatch;->rawString()Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/PhoneNumberMatch;->start()I
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$Leniency;->POSSIBLE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$Leniency;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;->EXACT_MATCH:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;->NOT_A_NUMBER:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;->NO_MATCH:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;->NSN_MATCH:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;->SHORT_NSN_MATCH:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;->values()[Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;->E164:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;->INTERNATIONAL:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;->NATIONAL:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;->RFC3966:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;->values()[Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->FIXED_LINE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->FIXED_LINE_OR_MOBILE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->MOBILE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->PAGER:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->PERSONAL_NUMBER:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->PREMIUM_RATE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->SHARED_COST:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->TOLL_FREE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->UAN:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->values()[Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->VOICEMAIL:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;->VOIP:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$ValidationResult;->IS_POSSIBLE:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$ValidationResult;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil$ValidationResult;->TOO_LONG:Lcom/android/i18n/phonenumbers/PhoneNumberUtil$ValidationResult;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->findNumbers(Ljava/lang/CharSequence;Ljava/lang/String;Lcom/android/i18n/phonenumbers/PhoneNumberUtil$Leniency;J)Ljava/lang/Iterable;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->format(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberFormat;)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->formatInOriginalFormat(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->getAsYouTypeFormatter(Ljava/lang/String;)Lcom/android/i18n/phonenumbers/AsYouTypeFormatter;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->getCountryCodeForRegion(Ljava/lang/String;)I
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->getInstance()Lcom/android/i18n/phonenumbers/PhoneNumberUtil;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->getNationalSignificantNumber(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->getNumberType(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Lcom/android/i18n/phonenumbers/PhoneNumberUtil$PhoneNumberType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->getRegionCodeForNumber(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Ljava/lang/String;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->isNumberMatch(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Lcom/android/i18n/phonenumbers/PhoneNumberUtil$MatchType;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->isPossibleNumber(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Z
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->isPossibleNumberWithReason(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Lcom/android/i18n/phonenumbers/PhoneNumberUtil$ValidationResult;
+Lcom/android/i18n/phonenumbers/PhoneNumberUtil;->isValidNumber(Lcom/android/i18n/phonenumbers/Phonenumber$PhoneNumber;)Z
+Lcom/android/ims/ImsCall;->deflect(Ljava/lang/String;)V
+Lcom/android/ims/ImsCall;->isMultiparty()Z
+Lcom/android/ims/ImsCall;->reject(I)V
+Lcom/android/ims/ImsCall;->terminate(I)V
 Lcom/android/ims/ImsConfigListener$Stub;-><init>()V
+Lcom/android/ims/ImsEcbm;->exitEmergencyCallbackMode()V
+Lcom/android/ims/ImsManager;->getConfigInterface()Lcom/android/ims/ImsConfig;
+Lcom/android/ims/ImsManager;->getInstance(Landroid/content/Context;I)Lcom/android/ims/ImsManager;
+Lcom/android/ims/ImsManager;->isEnhanced4gLteModeSettingEnabledByUser(Landroid/content/Context;)Z
+Lcom/android/ims/ImsManager;->isNonTtyOrTtyOnVolteEnabled(Landroid/content/Context;)Z
+Lcom/android/ims/ImsManager;->isVolteEnabledByPlatform(Landroid/content/Context;)Z
+Lcom/android/ims/ImsUtInterface;->queryCallForward(ILjava/lang/String;Landroid/os/Message;)V
 Lcom/android/ims/internal/IImsCallSession$Stub;-><init>()V
 Lcom/android/ims/internal/IImsCallSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/ims/internal/IImsCallSession;
 Lcom/android/ims/internal/IImsConfig$Stub;-><init>()V
@@ -1473,7 +1597,15 @@
 Lcom/android/ims/internal/IImsVideoCallCallback;->receiveSessionModifyResponse(ILandroid/telecom/VideoProfile;Landroid/telecom/VideoProfile;)V
 Lcom/android/ims/internal/IImsVideoCallProvider$Stub;-><init>()V
 Lcom/android/ims/internal/IImsVideoCallProvider;->setCallback(Lcom/android/ims/internal/IImsVideoCallCallback;)V
+Lcom/android/ims/internal/ImsVideoCallProviderWrapper;-><init>(Lcom/android/ims/internal/IImsVideoCallProvider;)V
 Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V
+Lcom/android/internal/app/AlertActivity;-><init>()V
+Lcom/android/internal/app/AlertActivity;->mAlert:Lcom/android/internal/app/AlertController;
+Lcom/android/internal/app/AlertActivity;->mAlertParams:Lcom/android/internal/app/AlertController$AlertParams;
+Lcom/android/internal/app/AlertActivity;->setupAlert()V
+Lcom/android/internal/app/AssistUtils;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/app/AssistUtils;->getAssistComponentForUser(I)Landroid/content/ComponentName;
+Lcom/android/internal/app/ChooserActivity;-><init>()V
 Lcom/android/internal/app/IAppOpsCallback$Stub;-><init>()V
 Lcom/android/internal/app/IAppOpsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/app/IAppOpsService$Stub$Proxy;->checkOperation(IILjava/lang/String;)I
@@ -1508,9 +1640,35 @@
 Lcom/android/internal/app/IBatteryStats;->getStatistics()[B
 Lcom/android/internal/app/IBatteryStats;->isCharging()Z
 Lcom/android/internal/app/IMediaContainerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IMediaContainerService;
+Lcom/android/internal/app/IntentForwarderActivity;->TAG:Ljava/lang/String;
 Lcom/android/internal/app/IVoiceInteractionManagerService$Stub$Proxy;->showSessionFromSession(Landroid/os/IBinder;Landroid/os/Bundle;I)Z
 Lcom/android/internal/app/IVoiceInteractionManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/app/IVoiceInteractionManagerService;
 Lcom/android/internal/app/IVoiceInteractionManagerService;->getKeyphraseSoundModel(ILjava/lang/String;)Landroid/hardware/soundtrigger/SoundTrigger$KeyphraseSoundModel;
+Lcom/android/internal/app/LocaleHelper$LocaleInfoComparator;-><init>(Ljava/util/Locale;Z)V
+Lcom/android/internal/app/LocaleHelper$LocaleInfoComparator;->compare(Lcom/android/internal/app/LocaleStore$LocaleInfo;Lcom/android/internal/app/LocaleStore$LocaleInfo;)I
+Lcom/android/internal/app/LocaleHelper;->getDisplayCountry(Ljava/util/Locale;Ljava/util/Locale;)Ljava/lang/String;
+Lcom/android/internal/app/LocaleHelper;->getDisplayName(Ljava/util/Locale;Ljava/util/Locale;Z)Ljava/lang/String;
+Lcom/android/internal/app/LocaleHelper;->normalizeForSearch(Ljava/lang/String;Ljava/util/Locale;)Ljava/lang/String;
+Lcom/android/internal/app/LocalePicker$LocaleInfo;->getLocale()Ljava/util/Locale;
+Lcom/android/internal/app/LocalePicker;->getLocales()Landroid/os/LocaleList;
+Lcom/android/internal/app/LocalePicker;->updateLocale(Ljava/util/Locale;)V
+Lcom/android/internal/app/LocalePicker;->updateLocales(Landroid/os/LocaleList;)V
+Lcom/android/internal/app/LocaleStore$LocaleInfo;->getFullNameInUiLanguage()Ljava/lang/String;
+Lcom/android/internal/app/LocaleStore$LocaleInfo;->getFullNameNative()Ljava/lang/String;
+Lcom/android/internal/app/LocaleStore$LocaleInfo;->getId()Ljava/lang/String;
+Lcom/android/internal/app/LocaleStore$LocaleInfo;->getLocale()Ljava/util/Locale;
+Lcom/android/internal/app/LocaleStore$LocaleInfo;->getParent()Ljava/util/Locale;
+Lcom/android/internal/app/LocaleStore;->fillCache(Landroid/content/Context;)V
+Lcom/android/internal/app/LocaleStore;->getLevelLocales(Landroid/content/Context;Ljava/util/Set;Lcom/android/internal/app/LocaleStore$LocaleInfo;Z)Ljava/util/Set;
+Lcom/android/internal/app/LocaleStore;->getLocaleInfo(Ljava/util/Locale;)Lcom/android/internal/app/LocaleStore$LocaleInfo;
+Lcom/android/internal/app/NetInitiatedActivity;->handleNIVerify(Landroid/content/Intent;)V
+Lcom/android/internal/app/ResolverActivity;-><init>()V
+Lcom/android/internal/app/ResolverActivity;->mAdapter:Lcom/android/internal/app/ResolverActivity$ResolveListAdapter;
+Lcom/android/internal/app/ResolverActivity;->mPm:Landroid/content/pm/PackageManager;
+Lcom/android/internal/app/ResolverActivity;->onCreate(Landroid/os/Bundle;Landroid/content/Intent;Ljava/lang/CharSequence;[Landroid/content/Intent;Ljava/util/List;Z)V
+Lcom/android/internal/app/WindowDecorActionBar$TabImpl;->mCallback:Landroid/app/ActionBar$TabListener;
+Lcom/android/internal/app/WindowDecorActionBar;->mTabScrollView:Lcom/android/internal/widget/ScrollingTabContainerView;
+Lcom/android/internal/app/WindowDecorActionBar;->setShowHideAnimationEnabled(Z)V
 Lcom/android/internal/appwidget/IAppWidgetService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/appwidget/IAppWidgetService;
 Lcom/android/internal/appwidget/IAppWidgetService$Stub;->TRANSACTION_bindAppWidgetId:I
 Lcom/android/internal/appwidget/IAppWidgetService;->bindAppWidgetId(Ljava/lang/String;IILandroid/content/ComponentName;Landroid/os/Bundle;)Z
@@ -1518,17 +1676,80 @@
 Lcom/android/internal/appwidget/IAppWidgetService;->getAppWidgetIds(Landroid/content/ComponentName;)[I
 Lcom/android/internal/appwidget/IAppWidgetService;->getAppWidgetViews(Ljava/lang/String;I)Landroid/widget/RemoteViews;
 Lcom/android/internal/backup/IBackupTransport$Stub;-><init>()V
+Lcom/android/internal/database/SortCursor;-><init>([Landroid/database/Cursor;Ljava/lang/String;)V
+Lcom/android/internal/database/SortCursor;->mCursor:Landroid/database/Cursor;
+Lcom/android/internal/database/SortCursor;->mCursors:[Landroid/database/Cursor;
+Lcom/android/internal/http/HttpDateTime;->parse(Ljava/lang/String;)J
+Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;-><init>()V
+Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->requestorId:Ljava/lang/String;
+Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->requestorIdEncoding:I
+Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->text:Ljava/lang/String;
+Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;->textEncoding:I
+Lcom/android/internal/location/GpsNetInitiatedHandler;->decodeString(Ljava/lang/String;ZI)Ljava/lang/String;
+Lcom/android/internal/location/GpsNetInitiatedHandler;->handleNiNotification(Lcom/android/internal/location/GpsNetInitiatedHandler$GpsNiNotification;)V
+Lcom/android/internal/location/GpsNetInitiatedHandler;->mIsHexInput:Z
 Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V
 Lcom/android/internal/logging/MetricsLogger;-><init>()V
 Lcom/android/internal/net/LegacyVpnInfo;-><init>()V
 Lcom/android/internal/net/VpnConfig;-><init>()V
+Lcom/android/internal/os/AndroidPrintStream;-><init>(ILjava/lang/String;)V
+Lcom/android/internal/os/BaseCommand;-><init>()V
+Lcom/android/internal/os/BaseCommand;->mArgs:Landroid/os/ShellCommand;
 Lcom/android/internal/os/BatterySipper$DrainType;->values()[Lcom/android/internal/os/BatterySipper$DrainType;
+Lcom/android/internal/os/BinderInternal;->getContextObject()Landroid/os/IBinder;
+Lcom/android/internal/os/BinderInternal;->handleGc()V
+Lcom/android/internal/os/ClassLoaderFactory;->createClassloaderNamespace(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZZ)Ljava/lang/String;
 Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService;
 Lcom/android/internal/os/IDropBoxManagerService;->getNextEntry(Ljava/lang/String;JLjava/lang/String;)Landroid/os/DropBoxManager$Entry;
+Lcom/android/internal/os/ProcessCpuTracker$Stats;->name:Ljava/lang/String;
+Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_stime:I
+Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_uptime:J
+Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_utime:I
+Lcom/android/internal/os/ProcessCpuTracker;-><init>(Z)V
+Lcom/android/internal/os/ProcessCpuTracker;->countWorkingStats()I
+Lcom/android/internal/os/ProcessCpuTracker;->getWorkingStats(I)Lcom/android/internal/os/ProcessCpuTracker$Stats;
+Lcom/android/internal/os/ProcessCpuTracker;->update()V
+Lcom/android/internal/os/RuntimeInit;->commonInit()V
+Lcom/android/internal/os/RuntimeInit;->getApplicationObject()Landroid/os/IBinder;
+Lcom/android/internal/os/RuntimeInit;->initialized:Z
+Lcom/android/internal/os/RuntimeInit;->main([Ljava/lang/String;)V
+Lcom/android/internal/os/RuntimeInit;->mApplicationObject:Landroid/os/IBinder;
+Lcom/android/internal/os/ZygoteConnection$Arguments;-><init>([Ljava/lang/String;)V
+Lcom/android/internal/os/ZygoteConnection$Arguments;->effectiveCapabilities:J
+Lcom/android/internal/os/ZygoteConnection$Arguments;->gid:I
+Lcom/android/internal/os/ZygoteConnection$Arguments;->gids:[I
+Lcom/android/internal/os/ZygoteConnection$Arguments;->permittedCapabilities:J
+Lcom/android/internal/os/ZygoteConnection$Arguments;->remainingArgs:[Ljava/lang/String;
+Lcom/android/internal/os/ZygoteConnection$Arguments;->rlimits:Ljava/util/ArrayList;
+Lcom/android/internal/os/ZygoteConnection$Arguments;->uid:I
+Lcom/android/internal/os/ZygoteConnection;->applyUidSecurityPolicy(Lcom/android/internal/os/ZygoteConnection$Arguments;Landroid/net/Credentials;)V
+Lcom/android/internal/os/ZygoteConnection;->closeSocket()V
+Lcom/android/internal/os/ZygoteConnection;->getFileDesciptor()Ljava/io/FileDescriptor;
+Lcom/android/internal/os/ZygoteConnection;->intArray2d:[[I
+Lcom/android/internal/os/ZygoteConnection;->mSocket:Landroid/net/LocalSocket;
+Lcom/android/internal/os/ZygoteConnection;->mSocketOutStream:Ljava/io/DataOutputStream;
+Lcom/android/internal/os/ZygoteConnection;->peer:Landroid/net/Credentials;
+Lcom/android/internal/os/ZygoteConnection;->readArgumentList()[Ljava/lang/String;
+Lcom/android/internal/os/ZygoteInit;->main([Ljava/lang/String;)V
+Lcom/android/internal/os/ZygoteInit;->mResources:Landroid/content/res/Resources;
+Lcom/android/internal/os/ZygoteSecurityException;-><init>(Ljava/lang/String;)V
+Lcom/android/internal/policy/DecorView;->mLastBottomInset:I
+Lcom/android/internal/policy/DecorView;->mLastLeftInset:I
+Lcom/android/internal/policy/DecorView;->mLastRightInset:I
+Lcom/android/internal/policy/DecorView;->mWindow:Lcom/android/internal/policy/PhoneWindow;
 Lcom/android/internal/policy/IKeyguardService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardService;
 Lcom/android/internal/policy/IKeyguardService;->doKeyguardTimeout(Landroid/os/Bundle;)V
 Lcom/android/internal/policy/IKeyguardService;->setKeyguardEnabled(Z)V
 Lcom/android/internal/policy/IKeyguardStateCallback$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardStateCallback;
+Lcom/android/internal/policy/PhoneFallbackEventHandler;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/policy/PhoneFallbackEventHandler;->mContext:Landroid/content/Context;
+Lcom/android/internal/policy/PhoneFallbackEventHandler;->mView:Landroid/view/View;
+Lcom/android/internal/policy/PhoneFallbackEventHandler;->onKeyDown(ILandroid/view/KeyEvent;)Z
+Lcom/android/internal/policy/PhoneFallbackEventHandler;->onKeyUp(ILandroid/view/KeyEvent;)Z
+Lcom/android/internal/policy/PhoneFallbackEventHandler;->startCallActivity()V
+Lcom/android/internal/policy/PhoneWindow;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/policy/PhoneWindow;->mTitle:Ljava/lang/CharSequence;
+Lcom/android/internal/preference/YesNoPreference;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
 Lcom/android/internal/R$anim;->fade_in:I
 Lcom/android/internal/R$array;->config_autoBrightnessLcdBacklightValues:I
 Lcom/android/internal/R$array;->config_autoBrightnessLevels:I
@@ -1996,9 +2217,961 @@
 Lcom/android/internal/statusbar/IStatusBarService;->setIconVisibility(Ljava/lang/String;Z)V
 Lcom/android/internal/telecom/ITelecomService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telecom/ITelecomService;
 Lcom/android/internal/telecom/ITelecomService;->getCallState()I
+Lcom/android/internal/telephony/BaseCommands;->mCallStateRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mCallWaitingInfoRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mCatCallSetUpRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mCatCcAlphaRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mCatEventRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mCatProCmdRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mCatSessionEndRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mCdmaPrlChangedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mCdmaSmsRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mCdmaSubscriptionChangedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/BaseCommands;->mEmergencyCallbackModeRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mExitEmergencyCallbackModeRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mGsmBroadcastSmsRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mGsmSmsRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mHardwareConfigChangeRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mIccRefreshRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mIccSmsFullRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mIccStatusChangedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mImsNetworkStateChangedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mNITZTimeRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mOtaProvisionRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mPhoneRadioCapabilityChangedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mPhoneType:I
+Lcom/android/internal/telephony/BaseCommands;->mPreferredNetworkType:I
+Lcom/android/internal/telephony/BaseCommands;->mResendIncallMuteRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mRestrictedStateRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mRilCellInfoListRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mRingbackToneRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mRingRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mSignalStrengthRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mSmsOnSimRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mSmsStatusRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mSrvccStateRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mSsnRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mSsRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mStateMonitor:Ljava/lang/Object;
+Lcom/android/internal/telephony/BaseCommands;->mSubscriptionStatusRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/BaseCommands;->mUnsolOemHookRawRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mUSSDRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/BaseCommands;->mVoiceRadioTechChangedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/Call$State;->ACTIVE:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->ALERTING:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->DIALING:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->DISCONNECTED:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->DISCONNECTING:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->HOLDING:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->IDLE:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->INCOMING:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->isAlive()Z
+Lcom/android/internal/telephony/Call$State;->isRinging()Z
+Lcom/android/internal/telephony/Call$State;->values()[Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call$State;->WAITING:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call;-><init>()V
+Lcom/android/internal/telephony/Call;->getConnections()Ljava/util/List;
+Lcom/android/internal/telephony/Call;->getEarliestConnection()Lcom/android/internal/telephony/Connection;
+Lcom/android/internal/telephony/Call;->getLatestConnection()Lcom/android/internal/telephony/Connection;
+Lcom/android/internal/telephony/Call;->getPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/Call;->getState()Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Call;->hangup()V
+Lcom/android/internal/telephony/Call;->isIdle()Z
+Lcom/android/internal/telephony/Call;->isMultiparty()Z
+Lcom/android/internal/telephony/Call;->mConnections:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/Call;->mState:Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/CallerInfoAsyncQuery$CallerInfoAsyncQueryHandler;-><init>(Lcom/android/internal/telephony/CallerInfoAsyncQuery;Landroid/content/Context;)V
+Lcom/android/internal/telephony/CallerInfoAsyncQuery$CookieWrapper;-><init>()V
+Lcom/android/internal/telephony/CallerInfoAsyncQuery;->release()V
+Lcom/android/internal/telephony/CallForwardInfo;-><init>()V
+Lcom/android/internal/telephony/CallForwardInfo;->number:Ljava/lang/String;
+Lcom/android/internal/telephony/CallForwardInfo;->reason:I
+Lcom/android/internal/telephony/CallForwardInfo;->serviceClass:I
+Lcom/android/internal/telephony/CallForwardInfo;->status:I
+Lcom/android/internal/telephony/CallForwardInfo;->timeSeconds:I
+Lcom/android/internal/telephony/CallForwardInfo;->toa:I
+Lcom/android/internal/telephony/CallManager;->canConference(Lcom/android/internal/telephony/Call;I)Z
+Lcom/android/internal/telephony/CallManager;->canDial(Lcom/android/internal/telephony/Phone;)Z
+Lcom/android/internal/telephony/CallManager;->conference(Lcom/android/internal/telephony/Call;)V
+Lcom/android/internal/telephony/CallManager;->getActiveFgCall(I)Lcom/android/internal/telephony/Call;
+Lcom/android/internal/telephony/CallManager;->getActiveFgCallState(I)Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/CallManager;->getBackgroundCalls()Ljava/util/List;
+Lcom/android/internal/telephony/CallManager;->getBgCallConnections()Ljava/util/List;
+Lcom/android/internal/telephony/CallManager;->getBgPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/CallManager;->getContext()Landroid/content/Context;
+Lcom/android/internal/telephony/CallManager;->getDefaultPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/CallManager;->getFgCallConnections()Ljava/util/List;
+Lcom/android/internal/telephony/CallManager;->getFgPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/CallManager;->getFgPhone(I)Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/CallManager;->getFirstActiveBgCall()Lcom/android/internal/telephony/Call;
+Lcom/android/internal/telephony/CallManager;->getFirstActiveBgCall(I)Lcom/android/internal/telephony/Call;
+Lcom/android/internal/telephony/CallManager;->getFirstActiveRingingCall()Lcom/android/internal/telephony/Call;
+Lcom/android/internal/telephony/CallManager;->getFirstActiveRingingCall(I)Lcom/android/internal/telephony/Call;
+Lcom/android/internal/telephony/CallManager;->getInstance()Lcom/android/internal/telephony/CallManager;
+Lcom/android/internal/telephony/CallManager;->getPhoneInCall()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/CallManager;->getRingingCalls()Ljava/util/List;
+Lcom/android/internal/telephony/CallManager;->getRingingPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/CallManager;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/CallManager;->getState(I)Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/CallManager;->hasActiveBgCall()Z
+Lcom/android/internal/telephony/CallManager;->hasActiveBgCall(I)Z
+Lcom/android/internal/telephony/CallManager;->hasActiveFgCall()Z
+Lcom/android/internal/telephony/CallManager;->hasActiveFgCall(I)Z
+Lcom/android/internal/telephony/CallManager;->hasActiveRingingCall(I)Z
+Lcom/android/internal/telephony/CallManager;->hasMoreThanOneRingingCall()Z
+Lcom/android/internal/telephony/CallManager;->hasMoreThanOneRingingCall(I)Z
+Lcom/android/internal/telephony/CallManager;->mBackgroundCalls:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/CallManager;->mEmptyConnections:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/CallManager;->mForegroundCalls:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/CallManager;->mPhones:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/CallManager;->mRingingCalls:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/CallManager;->registerForDisconnect(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CallManager;->registerForNewRingingConnection(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CallManager;->registerForPreciseCallStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CallManager;->registerPhone(Lcom/android/internal/telephony/Phone;)Z
+Lcom/android/internal/telephony/CallManager;->unregisterForDisconnect(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CallManager;->unregisterForNewRingingConnection(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CallManager;->unregisterForPreciseCallStateChanged(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CallManager;->unregisterPhone(Lcom/android/internal/telephony/Phone;)V
+Lcom/android/internal/telephony/CallStateException;-><init>(Ljava/lang/String;)V
+Lcom/android/internal/telephony/CallTracker;-><init>()V
+Lcom/android/internal/telephony/CallTracker;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/CallTracker;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/CallTracker;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/CallTracker;->mNeedsPoll:Z
+Lcom/android/internal/telephony/CallTracker;->mNumberConverted:Z
+Lcom/android/internal/telephony/CallTracker;->mPendingOperations:I
+Lcom/android/internal/telephony/CallTracker;->registerForVoiceCallEnded(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CarrierServiceBindHelper;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/CarrierServiceBindHelper;->mHandler:Landroid/os/Handler;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->CLOSE_CHANNEL:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->DISPLAY_TEXT:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->fromInt(I)Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->GET_CHANNEL_STATUS:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->GET_INKEY:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->GET_INPUT:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->LANGUAGE_NOTIFICATION:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->LAUNCH_BROWSER:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->OPEN_CHANNEL:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->PLAY_TONE:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->PROVIDE_LOCAL_INFORMATION:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->RECEIVE_DATA:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->REFRESH:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SELECT_ITEM:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_DATA:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_DTMF:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_SMS:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_SS:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SEND_USSD:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SET_UP_CALL:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SET_UP_EVENT_LIST:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SET_UP_IDLE_MODE_TEXT:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->SET_UP_MENU:Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/AppInterface$CommandType;->values()[Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/CatCmdMessage$CallSettings;->callMsg:Lcom/android/internal/telephony/cat/TextMessage;
+Lcom/android/internal/telephony/cat/CatCmdMessage$CallSettings;->confirmMsg:Lcom/android/internal/telephony/cat/TextMessage;
+Lcom/android/internal/telephony/cat/CatCmdMessage$SetupEventListSettings;->eventList:[I
+Lcom/android/internal/telephony/cat/CatCmdMessage;->getCallSettings()Lcom/android/internal/telephony/cat/CatCmdMessage$CallSettings;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->getCmdType()Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->geTextMessage()Lcom/android/internal/telephony/cat/TextMessage;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->getSetEventList()Lcom/android/internal/telephony/cat/CatCmdMessage$SetupEventListSettings;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->hasIconLoadFailed()Z
+Lcom/android/internal/telephony/cat/CatCmdMessage;->mCallSettings:Lcom/android/internal/telephony/cat/CatCmdMessage$CallSettings;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->mCmdDet:Lcom/android/internal/telephony/cat/CommandDetails;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->mInput:Lcom/android/internal/telephony/cat/Input;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->mMenu:Lcom/android/internal/telephony/cat/Menu;
+Lcom/android/internal/telephony/cat/CatCmdMessage;->mTextMsg:Lcom/android/internal/telephony/cat/TextMessage;
+Lcom/android/internal/telephony/cat/CatLog;->d(Ljava/lang/Object;Ljava/lang/String;)V
+Lcom/android/internal/telephony/cat/CatLog;->d(Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/internal/telephony/cat/CatLog;->e(Ljava/lang/Object;Ljava/lang/String;)V
+Lcom/android/internal/telephony/cat/CatResponseMessage;->setEventDownload(I[B)V
+Lcom/android/internal/telephony/cat/CatService;->dispose()V
+Lcom/android/internal/telephony/cat/CatService;->isStkAppInstalled()Z
+Lcom/android/internal/telephony/cat/CatService;->mCmdIf:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/cat/CatService;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/cat/CatService;->mCurrntCmd:Lcom/android/internal/telephony/cat/CatCmdMessage;
+Lcom/android/internal/telephony/cat/CatService;->mHandlerThread:Landroid/os/HandlerThread;
+Lcom/android/internal/telephony/cat/CatService;->mMenuCmd:Lcom/android/internal/telephony/cat/CatCmdMessage;
+Lcom/android/internal/telephony/cat/CatService;->mMsgDecoder:Lcom/android/internal/telephony/cat/RilMessageDecoder;
+Lcom/android/internal/telephony/cat/CatService;->mSlotId:I
+Lcom/android/internal/telephony/cat/CatService;->mStkAppInstalled:Z
+Lcom/android/internal/telephony/cat/CatService;->mUiccController:Lcom/android/internal/telephony/uicc/UiccController;
+Lcom/android/internal/telephony/cat/CatService;->sendTerminalResponse(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/ResultCode;ZILcom/android/internal/telephony/cat/ResponseData;)V
+Lcom/android/internal/telephony/cat/CatService;->sInstance:[Lcom/android/internal/telephony/cat/CatService;
+Lcom/android/internal/telephony/cat/CatService;->sInstanceLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/cat/CommandDetails;->commandNumber:I
+Lcom/android/internal/telephony/cat/CommandDetails;->commandQualifier:I
+Lcom/android/internal/telephony/cat/CommandDetails;->compRequired:Z
+Lcom/android/internal/telephony/cat/CommandDetails;->typeOfCommand:I
+Lcom/android/internal/telephony/cat/CommandParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;)V
+Lcom/android/internal/telephony/cat/CommandParams;->getCommandType()Lcom/android/internal/telephony/cat/AppInterface$CommandType;
+Lcom/android/internal/telephony/cat/CommandParams;->mCmdDet:Lcom/android/internal/telephony/cat/CommandDetails;
+Lcom/android/internal/telephony/cat/CommandParamsFactory;->dispose()V
+Lcom/android/internal/telephony/cat/CommandParamsFactory;->mIconLoader:Lcom/android/internal/telephony/cat/IconLoader;
+Lcom/android/internal/telephony/cat/CommandParamsFactory;->searchForNextTag(Lcom/android/internal/telephony/cat/ComprehensionTlvTag;Ljava/util/Iterator;)Lcom/android/internal/telephony/cat/ComprehensionTlv;
+Lcom/android/internal/telephony/cat/CommandParamsFactory;->searchForTag(Lcom/android/internal/telephony/cat/ComprehensionTlvTag;Ljava/util/List;)Lcom/android/internal/telephony/cat/ComprehensionTlv;
+Lcom/android/internal/telephony/cat/ComprehensionTlv;->getLength()I
+Lcom/android/internal/telephony/cat/ComprehensionTlv;->getRawValue()[B
+Lcom/android/internal/telephony/cat/ComprehensionTlv;->getTag()I
+Lcom/android/internal/telephony/cat/ComprehensionTlv;->getValueIndex()I
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->ADDRESS:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->ALPHA_ID:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->COMMAND_DETAILS:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->DEVICE_IDENTITIES:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->ICON_ID:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->RESULT:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->SMS_TPDU:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->TEXT_ATTRIBUTE:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->TEXT_STRING:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->USSD_STRING:Lcom/android/internal/telephony/cat/ComprehensionTlvTag;
+Lcom/android/internal/telephony/cat/ComprehensionTlvTag;->value()I
+Lcom/android/internal/telephony/cat/DeviceIdentities;->destinationId:I
+Lcom/android/internal/telephony/cat/DisplayTextParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/TextMessage;)V
+Lcom/android/internal/telephony/cat/DisplayTextParams;->mTextMsg:Lcom/android/internal/telephony/cat/TextMessage;
+Lcom/android/internal/telephony/cat/Duration$TimeUnit;->value()I
+Lcom/android/internal/telephony/cat/Duration;->timeInterval:I
+Lcom/android/internal/telephony/cat/Duration;->timeUnit:Lcom/android/internal/telephony/cat/Duration$TimeUnit;
+Lcom/android/internal/telephony/cat/GetInputParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/Input;)V
+Lcom/android/internal/telephony/cat/IconId;->recordNumber:I
+Lcom/android/internal/telephony/cat/IconLoader;->loadIcon(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/cat/Menu;->titleAttrs:Ljava/util/List;
+Lcom/android/internal/telephony/cat/PlayToneParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/TextMessage;Lcom/android/internal/telephony/cat/Tone;Lcom/android/internal/telephony/cat/Duration;Z)V
+Lcom/android/internal/telephony/cat/ResponseData;-><init>()V
+Lcom/android/internal/telephony/cat/ResponseData;->format(Ljava/io/ByteArrayOutputStream;)V
+Lcom/android/internal/telephony/cat/ResultCode;->BACKWARD_MOVE_BY_USER:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->BEYOND_TERMINAL_CAPABILITY:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->BIP_ERROR:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->CMD_DATA_NOT_UNDERSTOOD:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->HELP_INFO_REQUIRED:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->LAUNCH_BROWSER_ERROR:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->NETWORK_CRNTLY_UNABLE_TO_PROCESS:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->NO_RESPONSE_FROM_USER:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->OK:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_ICON_NOT_DISPLAYED:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_LIMITED_SERVICE:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_MODIFIED_BY_NAA:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_NAA_NOT_ACTIVE:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_TONE_NOT_PLAYED:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_WITH_ADDITIONAL_EFS_READ:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_WITH_MISSING_INFO:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_WITH_MODIFICATION:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->PRFRMD_WITH_PARTIAL_COMPREHENSION:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->REQUIRED_VALUES_MISSING:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->TERMINAL_CRNTLY_UNABLE_TO_PROCESS:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->UICC_SESSION_TERM_BY_USER:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->USER_NOT_ACCEPT:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->USIM_CALL_CONTROL_PERMANENT:Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultCode;->value()I
+Lcom/android/internal/telephony/cat/ResultCode;->values()[Lcom/android/internal/telephony/cat/ResultCode;
+Lcom/android/internal/telephony/cat/ResultException;-><init>(Lcom/android/internal/telephony/cat/ResultCode;)V
+Lcom/android/internal/telephony/cat/RilMessage;-><init>(ILjava/lang/String;)V
+Lcom/android/internal/telephony/cat/RilMessage;->mData:Ljava/lang/Object;
+Lcom/android/internal/telephony/cat/RilMessage;->mId:I
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->getInstance(Landroid/os/Handler;Lcom/android/internal/telephony/uicc/IccFileHandler;I)Lcom/android/internal/telephony/cat/RilMessageDecoder;
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->mCmdParamsFactory:Lcom/android/internal/telephony/cat/CommandParamsFactory;
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->mCurrentRilMessage:Lcom/android/internal/telephony/cat/RilMessage;
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->mInstance:[Lcom/android/internal/telephony/cat/RilMessageDecoder;
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->mStateStart:Lcom/android/internal/telephony/cat/RilMessageDecoder$StateStart;
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->sendCmdForExecution(Lcom/android/internal/telephony/cat/RilMessage;)V
+Lcom/android/internal/telephony/cat/RilMessageDecoder;->sendStartDecodingMessageParams(Lcom/android/internal/telephony/cat/RilMessage;)V
+Lcom/android/internal/telephony/cat/SelectItemParams;-><init>(Lcom/android/internal/telephony/cat/CommandDetails;Lcom/android/internal/telephony/cat/Menu;Z)V
+Lcom/android/internal/telephony/cat/TextMessage;-><init>()V
+Lcom/android/internal/telephony/cat/TextMessage;->iconSelfExplanatory:Z
+Lcom/android/internal/telephony/cat/TextMessage;->text:Ljava/lang/String;
+Lcom/android/internal/telephony/cat/ValueObject;-><init>()V
+Lcom/android/internal/telephony/cat/ValueParser;->retrieveAlphaId(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Ljava/lang/String;
+Lcom/android/internal/telephony/cat/ValueParser;->retrieveDeviceIdentities(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Lcom/android/internal/telephony/cat/DeviceIdentities;
+Lcom/android/internal/telephony/cat/ValueParser;->retrieveTextAttribute(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Ljava/util/List;
+Lcom/android/internal/telephony/cat/ValueParser;->retrieveTextString(Lcom/android/internal/telephony/cat/ComprehensionTlv;)Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/CdmaCallWaitingNotification;->number:Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/CdmaMmiCode;->makeEmptyNull(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/CdmaMmiCode;->mSc:Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/CdmaSMSDispatcher;->getFormat()Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/CdmaSMSDispatcher;->handleCdmaStatusReport(Lcom/android/internal/telephony/cdma/SmsMessage;)V
+Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager;->getCdmaSubscriptionSource()I
+Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager;->getInstance(Landroid/content/Context;Lcom/android/internal/telephony/CommandsInterface;Landroid/os/Handler;ILjava/lang/Object;)Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager;
+Lcom/android/internal/telephony/cdma/EriManager$EriDisplayInformation;->mEriIconText:Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/EriManager;->getEriDisplayInformation(II)Lcom/android/internal/telephony/cdma/EriManager$EriDisplayInformation;
+Lcom/android/internal/telephony/cdma/sms/BearerData$CodingException;-><init>(Ljava/lang/String;)V
+Lcom/android/internal/telephony/cdma/sms/BearerData$TimeStamp;-><init>()V
+Lcom/android/internal/telephony/cdma/sms/BearerData;-><init>()V
+Lcom/android/internal/telephony/cdma/sms/BearerData;->countAsciiSeptets(Ljava/lang/CharSequence;Z)I
+Lcom/android/internal/telephony/cdma/sms/BearerData;->decodeUserDataPayload(Lcom/android/internal/telephony/cdma/sms/UserData;Z)V
+Lcom/android/internal/telephony/cdma/sms/BearerData;->displayMode:I
+Lcom/android/internal/telephony/cdma/sms/BearerData;->encode(Lcom/android/internal/telephony/cdma/sms/BearerData;)[B
+Lcom/android/internal/telephony/cdma/sms/BearerData;->encode7bitAscii(Ljava/lang/String;Z)[B
+Lcom/android/internal/telephony/cdma/sms/BearerData;->getBitsForNumFields(II)I
+Lcom/android/internal/telephony/cdma/sms/BearerData;->hasUserDataHeader:Z
+Lcom/android/internal/telephony/cdma/sms/BearerData;->messageId:I
+Lcom/android/internal/telephony/cdma/sms/BearerData;->msgCenterTimeStamp:Lcom/android/internal/telephony/cdma/sms/BearerData$TimeStamp;
+Lcom/android/internal/telephony/cdma/sms/BearerData;->priority:I
+Lcom/android/internal/telephony/cdma/sms/BearerData;->priorityIndicatorSet:Z
+Lcom/android/internal/telephony/cdma/sms/BearerData;->userData:Lcom/android/internal/telephony/cdma/sms/UserData;
+Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;-><init>()V
+Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->digitMode:I
+Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->numberMode:I
+Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->numberOfDigits:I
+Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->numberPlan:I
+Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;->parse(Ljava/lang/String;)Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;
+Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;-><init>()V
+Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;->bearerData:[B
+Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;->serviceCategory:I
+Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;->teleService:I
+Lcom/android/internal/telephony/cdma/sms/UserData;-><init>()V
+Lcom/android/internal/telephony/cdma/sms/UserData;->charToAscii:Landroid/util/SparseIntArray;
+Lcom/android/internal/telephony/cdma/sms/UserData;->msgEncoding:I
+Lcom/android/internal/telephony/cdma/sms/UserData;->msgEncodingSet:Z
+Lcom/android/internal/telephony/cdma/sms/UserData;->numFields:I
+Lcom/android/internal/telephony/cdma/sms/UserData;->payload:[B
+Lcom/android/internal/telephony/cdma/sms/UserData;->payloadStr:Ljava/lang/String;
+Lcom/android/internal/telephony/cdma/sms/UserData;->userDataHeader:Lcom/android/internal/telephony/SmsHeader;
+Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;-><init>()V
+Lcom/android/internal/telephony/cdma/SmsMessage;-><init>()V
+Lcom/android/internal/telephony/cdma/SmsMessage;->calculateLength(Ljava/lang/CharSequence;ZZ)Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;
+Lcom/android/internal/telephony/cdma/SmsMessage;->createFromEfRecord(I[B)Lcom/android/internal/telephony/cdma/SmsMessage;
+Lcom/android/internal/telephony/cdma/SmsMessage;->createFromPdu([B)Lcom/android/internal/telephony/cdma/SmsMessage;
+Lcom/android/internal/telephony/cdma/SmsMessage;->getIncomingSmsFingerprint()[B
+Lcom/android/internal/telephony/cdma/SmsMessage;->getMessageType()I
+Lcom/android/internal/telephony/cdma/SmsMessage;->getNextMessageId()I
+Lcom/android/internal/telephony/cdma/SmsMessage;->getNumOfVoicemails()I
+Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Lcom/android/internal/telephony/cdma/sms/UserData;Z)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Lcom/android/internal/telephony/cdma/sms/UserData;ZI)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;I[BZ)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLcom/android/internal/telephony/SmsHeader;)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/cdma/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLcom/android/internal/telephony/SmsHeader;I)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/cdma/SmsMessage;->getTeleService()I
+Lcom/android/internal/telephony/cdma/SmsMessage;->isStatusReportMessage()Z
+Lcom/android/internal/telephony/cdma/SmsMessage;->mBearerData:Lcom/android/internal/telephony/cdma/sms/BearerData;
+Lcom/android/internal/telephony/cdma/SmsMessage;->mEnvelope:Lcom/android/internal/telephony/cdma/sms/SmsEnvelope;
+Lcom/android/internal/telephony/cdma/SmsMessage;->parseSms()V
+Lcom/android/internal/telephony/cdma/SmsMessage;->privateGetSubmitPdu(Ljava/lang/String;ZLcom/android/internal/telephony/cdma/sms/UserData;)Lcom/android/internal/telephony/cdma/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/CommandException$Error;->GENERIC_FAILURE:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException$Error;->PASSWORD_INCORRECT:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException$Error;->RADIO_NOT_AVAILABLE:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException$Error;->REQUEST_NOT_SUPPORTED:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException$Error;->SIM_PUK2:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException$Error;->SMS_FAIL_RETRY:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException;-><init>(Lcom/android/internal/telephony/CommandException$Error;)V
+Lcom/android/internal/telephony/CommandException;->fromRilErrno(I)Lcom/android/internal/telephony/CommandException;
+Lcom/android/internal/telephony/CommandException;->getCommandError()Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandException;->mError:Lcom/android/internal/telephony/CommandException$Error;
+Lcom/android/internal/telephony/CommandsInterface;->acceptCall(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->acknowledgeLastIncomingCdmaSms(ZILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->acknowledgeLastIncomingGsmSms(ZILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->changeBarringPassword(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->deleteSmsOnRuim(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->deleteSmsOnSim(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->dial(Ljava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->dial(Ljava/lang/String;ILcom/android/internal/telephony/UUSInfo;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->exitEmergencyCallbackMode(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getBasebandVersion(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getCdmaBroadcastConfig(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getCDMASubscription(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getDataCallList(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getIccCardStatus(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getIMEISV(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getIMSI(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getLastDataCallFailCause(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getLastPdpFailCause(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getNetworkSelectionMode(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getOperator(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getPDPContextList(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getPreferredNetworkType(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getSignalStrength(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getSmscAddress(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->getVoiceRegistrationState(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->handleCallSetupRequestFromSim(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->iccIO(IILjava/lang/String;IIILjava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->iccIOForApp(IILjava/lang/String;IIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->invokeOemRilRequestRaw([BLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->queryCallForwardStatus(IILjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->queryCallWaiting(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->queryFacilityLock(Ljava/lang/String;Ljava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->queryTTYMode(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForAvailable(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForCdmaOtaProvision(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForCellInfoList(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForIccRefresh(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForImsNetworkStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForNotAvailable(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForOffOrNotAvailable(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForOn(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForRadioStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->registerForRilConnected(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->reportSmsMemoryStatus(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->reportStkServiceIsRunning(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->requestIccSimAuthentication(ILjava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->requestShutdown(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->sendDtmf(CLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->sendEnvelope(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->sendTerminalResponse(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setCallForward(IIILjava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setCallWaiting(ZILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setCdmaBroadcastActivation(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setDataAllowed(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setEmergencyCallbackMode(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setFacilityLock(Ljava/lang/String;ZLjava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setNetworkSelectionModeAutomatic(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setNetworkSelectionModeManual(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnCallRing(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnCatCallSetUp(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnCatCcAlphaNotify(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnCatEvent(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnCatProactiveCmd(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnCatSessionEnd(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnIccRefresh(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnIccSmsFull(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnNewGsmBroadcastSms(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnNITZTime(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnSignalStrengthUpdate(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnSmsOnSim(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnSmsStatus(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setOnSuppServiceNotification(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/CommandsInterface;->setPhoneType(I)V
+Lcom/android/internal/telephony/CommandsInterface;->setPreferredNetworkType(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setRadioPower(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setSmscAddress(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setTTYMode(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->setUiccSubscription(IIIILandroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->supplyIccPin(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->switchWaitingOrHoldingAndActive(Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->unregisterForAvailable(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CommandsInterface;->unregisterForCdmaOtaProvision(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CommandsInterface;->unregisterForOffOrNotAvailable(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CommandsInterface;->unregisterForOn(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CommandsInterface;->unregisterForRilConnected(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CommandsInterface;->unregisterForVoiceRadioTechChanged(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/CommandsInterface;->writeSmsToRuim(ILjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/CommandsInterface;->writeSmsToSim(ILjava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/Connection$PostDialState;->CANCELLED:Lcom/android/internal/telephony/Connection$PostDialState;
+Lcom/android/internal/telephony/Connection$PostDialState;->COMPLETE:Lcom/android/internal/telephony/Connection$PostDialState;
+Lcom/android/internal/telephony/Connection$PostDialState;->NOT_STARTED:Lcom/android/internal/telephony/Connection$PostDialState;
+Lcom/android/internal/telephony/Connection$PostDialState;->STARTED:Lcom/android/internal/telephony/Connection$PostDialState;
+Lcom/android/internal/telephony/Connection$PostDialState;->WAIT:Lcom/android/internal/telephony/Connection$PostDialState;
+Lcom/android/internal/telephony/Connection$PostDialState;->WILD:Lcom/android/internal/telephony/Connection$PostDialState;
+Lcom/android/internal/telephony/Connection;-><init>(I)V
+Lcom/android/internal/telephony/Connection;->getAddress()Ljava/lang/String;
+Lcom/android/internal/telephony/Connection;->getCall()Lcom/android/internal/telephony/Call;
+Lcom/android/internal/telephony/Connection;->getConnectTime()J
+Lcom/android/internal/telephony/Connection;->getCreateTime()J
+Lcom/android/internal/telephony/Connection;->getDisconnectCause()I
+Lcom/android/internal/telephony/Connection;->getDisconnectTime()J
+Lcom/android/internal/telephony/Connection;->getDurationMillis()J
+Lcom/android/internal/telephony/Connection;->getState()Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/Connection;->getUserData()Ljava/lang/Object;
+Lcom/android/internal/telephony/Connection;->hangup()V
+Lcom/android/internal/telephony/Connection;->isAlive()Z
+Lcom/android/internal/telephony/Connection;->isIncoming()Z
+Lcom/android/internal/telephony/Connection;->LOG_TAG:Ljava/lang/String;
+Lcom/android/internal/telephony/Connection;->mAddress:Ljava/lang/String;
+Lcom/android/internal/telephony/Connection;->mCnapName:Ljava/lang/String;
+Lcom/android/internal/telephony/Connection;->mCnapNamePresentation:I
+Lcom/android/internal/telephony/Connection;->mDialString:Ljava/lang/String;
+Lcom/android/internal/telephony/Connection;->mDuration:J
+Lcom/android/internal/telephony/Connection;->mIsIncoming:Z
+Lcom/android/internal/telephony/Connection;->mNumberPresentation:I
+Lcom/android/internal/telephony/Connection;->setVideoState(I)V
+Lcom/android/internal/telephony/dataconnection/ApnContext;->getApnType()Ljava/lang/String;
+Lcom/android/internal/telephony/dataconnection/ApnContext;->getReason()Ljava/lang/String;
+Lcom/android/internal/telephony/dataconnection/ApnContext;->getState()Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/dataconnection/ApnContext;->isConnectable()Z
+Lcom/android/internal/telephony/dataconnection/ApnContext;->isDisconnected()Z
+Lcom/android/internal/telephony/dataconnection/ApnContext;->isEnabled()Z
+Lcom/android/internal/telephony/dataconnection/ApnContext;->isReady()Z
+Lcom/android/internal/telephony/dataconnection/ApnContext;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/ApnContext;->mApnType:Ljava/lang/String;
+Lcom/android/internal/telephony/dataconnection/ApnContext;->mRefCount:I
+Lcom/android/internal/telephony/dataconnection/ApnContext;->mRefCountLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/dataconnection/ApnContext;->setState(Lcom/android/internal/telephony/DctConstants$State;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;->mApnContext:Lcom/android/internal/telephony/dataconnection/ApnContext;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->clearSettings()V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->dumpToLog()V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->initConnection(Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;)Z
+Lcom/android/internal/telephony/dataconnection/DataConnection;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mActivatingState:Lcom/android/internal/telephony/dataconnection/DataConnection$DcActivatingState;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mActiveState:Lcom/android/internal/telephony/dataconnection/DataConnection$DcActiveState;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mApnContexts:Ljava/util/HashMap;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mConnectionParams:Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mDataRegState:I
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mDcFailCause:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mDct:Lcom/android/internal/telephony/dataconnection/DcTracker;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mDisconnectingErrorCreatingConnection:Lcom/android/internal/telephony/dataconnection/DataConnection$DcDisconnectionErrorCreatingConnection;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mDisconnectingState:Lcom/android/internal/telephony/dataconnection/DataConnection$DcDisconnectingState;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mDisconnectParams:Lcom/android/internal/telephony/dataconnection/DataConnection$DisconnectParams;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mId:I
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mInactiveState:Lcom/android/internal/telephony/dataconnection/DataConnection$DcInactiveState;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mLinkProperties:Landroid/net/LinkProperties;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mNetworkInfo:Landroid/net/NetworkInfo;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/dataconnection/DataConnection;->mRilRat:I
+Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllDisconnectCompleted(Lcom/android/internal/telephony/dataconnection/DcFailCause;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllOfConnected(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyAllOfDisconnectDcRetrying(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyConnectCompleted(Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;Lcom/android/internal/telephony/dataconnection/DcFailCause;Z)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->notifyDisconnectCompleted(Lcom/android/internal/telephony/dataconnection/DataConnection$DisconnectParams;Z)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->onConnect(Lcom/android/internal/telephony/dataconnection/DataConnection$ConnectionParams;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->tearDownData(Ljava/lang/Object;)V
+Lcom/android/internal/telephony/dataconnection/DataConnection;->updateTcpBufferSizes(I)V
+Lcom/android/internal/telephony/dataconnection/DcController;->lr(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcController;->mDcListActiveByCid:Ljava/util/HashMap;
+Lcom/android/internal/telephony/dataconnection/DcController;->mDct:Lcom/android/internal/telephony/dataconnection/DcTracker;
+Lcom/android/internal/telephony/dataconnection/DcController;->mDcTesterDeactivateAll:Lcom/android/internal/telephony/dataconnection/DcTesterDeactivateAll;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->ACTIVATION_REJECT_GGSN:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->ACTIVATION_REJECT_UNSPECIFIED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->APN_TYPE_CONFLICT:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->INSUFFICIENT_RESOURCES:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->MISSING_UNKNOWN_APN:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->NSAPI_IN_USE:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->ONLY_IPV4_ALLOWED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->ONLY_IPV6_ALLOWED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->ONLY_SINGLE_BEARER_ALLOWED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->OPERATOR_BARRED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->PROTOCOL_ERRORS:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->SERVICE_OPTION_NOT_SUBSCRIBED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->SERVICE_OPTION_NOT_SUPPORTED:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->SERVICE_OPTION_OUT_OF_ORDER:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->UNKNOWN_PDP_ADDRESS_TYPE:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcFailCause;->USER_AUTHENTICATION:Lcom/android/internal/telephony/dataconnection/DcFailCause;
+Lcom/android/internal/telephony/dataconnection/DcTracker$RecoveryAction;->isAggressiveRecovery(I)Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->cancelReconnectAlarm(Lcom/android/internal/telephony/dataconnection/ApnContext;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpAllConnections(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpAllConnections(ZLjava/lang/String;)Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->cleanUpConnection(ZLcom/android/internal/telephony/dataconnection/ApnContext;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->createAllApnList()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->getActiveApnTypes()[Ljava/lang/String;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->getOverallState()Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->getUiccRecords(I)Lcom/android/internal/telephony/uicc/IccRecords;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->isConnected()Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->isDisconnected()Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->isOnlySingleDcAllowed(I)Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mAllApnSettings:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mApnContexts:Ljava/util/concurrent/ConcurrentHashMap;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mAttached:Ljava/util/concurrent/atomic/AtomicBoolean;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mAutoAttachOnCreation:Ljava/util/concurrent/atomic/AtomicBoolean;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mDataConnectionTracker:Landroid/os/Handler;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mDisconnectPendingCount:I
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mIccRecords:Ljava/util/concurrent/atomic/AtomicReference;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mIsPsRestricted:Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mIsScreenOn:Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mNetStatPollEnabled:Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mNetStatPollPeriod:I
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mPrioritySortedApnContexts:Ljava/util/PriorityQueue;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mProvisioningSpinner:Landroid/app/ProgressDialog;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mResolver:Landroid/content/ContentResolver;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mState:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->mSubscriptionManager:Landroid/telephony/SubscriptionManager;
+Lcom/android/internal/telephony/dataconnection/DcTracker;->notifyDataConnection(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->notifyOffApnsOfAvailability(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onActionIntentDataStallAlarm(Landroid/content/Intent;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onActionIntentProvisioningApnAlarm(Landroid/content/Intent;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onCleanUpAllConnections(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onRecordsLoadedOrSubIdChanged()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onSetUserDataEnabled(Z)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onTrySetupData(Lcom/android/internal/telephony/dataconnection/ApnContext;)Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->onTrySetupData(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->registerForAllDataDisconnected(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->registerSettingsObserver()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->resetPollStats()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->restartDataStallAlarm()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->setInitialAttachApn()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->setInternalDataEnabled(ZLandroid/os/Message;)Z
+Lcom/android/internal/telephony/dataconnection/DcTracker;->setPreferredApn(I)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->setRadio(Z)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->setupDataOnConnectableApns(Ljava/lang/String;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->startDataStallAlarm(Z)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->startNetStatPoll()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->stopDataStallAlarm()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->stopNetStatPoll()V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->unregisterForAllDataDisconnected(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/dataconnection/DcTracker;->updateRecords()V
+Lcom/android/internal/telephony/DctConstants$Activity;->DATAIN:Lcom/android/internal/telephony/DctConstants$Activity;
+Lcom/android/internal/telephony/DctConstants$Activity;->DATAINANDOUT:Lcom/android/internal/telephony/DctConstants$Activity;
+Lcom/android/internal/telephony/DctConstants$Activity;->DATAOUT:Lcom/android/internal/telephony/DctConstants$Activity;
+Lcom/android/internal/telephony/DctConstants$Activity;->DORMANT:Lcom/android/internal/telephony/DctConstants$Activity;
+Lcom/android/internal/telephony/DctConstants$Activity;->values()[Lcom/android/internal/telephony/DctConstants$Activity;
+Lcom/android/internal/telephony/DctConstants$State;->CONNECTED:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->CONNECTING:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->DISCONNECTING:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->FAILED:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->IDLE:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->RETRYING:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->SCANNING:Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DctConstants$State;->values()[Lcom/android/internal/telephony/DctConstants$State;
+Lcom/android/internal/telephony/DefaultPhoneNotifier;->mRegistry:Lcom/android/internal/telephony/ITelephonyRegistry;
+Lcom/android/internal/telephony/DriverCall$State;->ACTIVE:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall$State;->ALERTING:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall$State;->DIALING:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall$State;->HOLDING:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall$State;->INCOMING:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall$State;->values()[Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall$State;->WAITING:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/DriverCall;-><init>()V
+Lcom/android/internal/telephony/DriverCall;->index:I
+Lcom/android/internal/telephony/DriverCall;->isMT:Z
+Lcom/android/internal/telephony/DriverCall;->isVoice:Z
+Lcom/android/internal/telephony/DriverCall;->name:Ljava/lang/String;
+Lcom/android/internal/telephony/DriverCall;->number:Ljava/lang/String;
+Lcom/android/internal/telephony/DriverCall;->numberPresentation:I
+Lcom/android/internal/telephony/DriverCall;->state:Lcom/android/internal/telephony/DriverCall$State;
+Lcom/android/internal/telephony/gsm/GsmCellBroadcastHandler$SmsCbConcatInfo;-><init>(Lcom/android/internal/telephony/gsm/SmsCbHeader;Landroid/telephony/SmsCbLocation;)V
+Lcom/android/internal/telephony/gsm/GsmCellBroadcastHandler$SmsCbConcatInfo;->matchesLocation(Ljava/lang/String;II)Z
+Lcom/android/internal/telephony/gsm/GsmCellBroadcastHandler;->mSmsCbPageMap:Ljava/util/HashMap;
+Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler;->acknowledgeLastIncomingSms(ZILandroid/os/Message;)V
+Lcom/android/internal/telephony/gsm/GsmMmiCode;-><init>(Lcom/android/internal/telephony/GsmCdmaPhone;Lcom/android/internal/telephony/uicc/UiccCardApplication;)V
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->getCLIRMode()I
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->getScString()Ljava/lang/CharSequence;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isActivate()Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isDeactivate()Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isErasure()Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isInterrogate()Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isRegister()Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isServiceCodeCallBarring(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isServiceCodeCallForwarding(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->isTemporaryModeCLIR()Z
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->makeEmptyNull(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mDialingNumber:Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mIccRecords:Lcom/android/internal/telephony/uicc/IccRecords;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mPhone:Lcom/android/internal/telephony/GsmCdmaPhone;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mSc:Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mSia:Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mSib:Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->mSic:Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->newFromDialString(Ljava/lang/String;Lcom/android/internal/telephony/GsmCdmaPhone;Lcom/android/internal/telephony/uicc/UiccCardApplication;)Lcom/android/internal/telephony/gsm/GsmMmiCode;
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->processCode()V
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->siToServiceClass(Ljava/lang/String;)I
+Lcom/android/internal/telephony/gsm/GsmMmiCode;->sPatternSuppService:Ljava/util/regex/Pattern;
+Lcom/android/internal/telephony/gsm/GsmSmsAddress;-><init>([BII)V
+Lcom/android/internal/telephony/gsm/GsmSmsAddress;->isCphsVoiceMessageClear()Z
+Lcom/android/internal/telephony/gsm/GsmSmsAddress;->isCphsVoiceMessageSet()Z
+Lcom/android/internal/telephony/gsm/GsmSMSDispatcher;->getFormat()Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/GsmSMSDispatcher;->mGsmInboundSmsHandler:Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler;
+Lcom/android/internal/telephony/gsm/GsmSMSDispatcher;->sendSms(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/gsm/SimTlv;-><init>([BII)V
+Lcom/android/internal/telephony/gsm/SimTlv;->getData()[B
+Lcom/android/internal/telephony/gsm/SimTlv;->getTag()I
+Lcom/android/internal/telephony/gsm/SimTlv;->isValidObject()Z
+Lcom/android/internal/telephony/gsm/SimTlv;->mHasValidTlvObject:Z
+Lcom/android/internal/telephony/gsm/SimTlv;->nextObject()Z
+Lcom/android/internal/telephony/gsm/SmsCbHeader;-><init>([B)V
+Lcom/android/internal/telephony/gsm/SmsCbHeader;->getGeographicalScope()I
+Lcom/android/internal/telephony/gsm/SmsCbHeader;->getNumberOfPages()I
+Lcom/android/internal/telephony/gsm/SmsCbHeader;->getPageIndex()I
+Lcom/android/internal/telephony/gsm/SmsCbHeader;->getSerialNumber()I
+Lcom/android/internal/telephony/gsm/SmsCbHeader;->getServiceCategory()I
+Lcom/android/internal/telephony/gsm/SmsCbHeader;->mMessageIdentifier:I
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;-><init>([B)V
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->getByte()I
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->getUserData()[B
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->getUserDataUCS2(I)Ljava/lang/String;
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->mCur:I
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->mPdu:[B
+Lcom/android/internal/telephony/gsm/SmsMessage$PduParser;->mUserDataSeptetPadding:I
+Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;-><init>()V
+Lcom/android/internal/telephony/gsm/SmsMessage;-><init>()V
+Lcom/android/internal/telephony/gsm/SmsMessage;->calculateLength(Ljava/lang/CharSequence;Z)Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;
+Lcom/android/internal/telephony/gsm/SmsMessage;->createFromEfRecord(I[B)Lcom/android/internal/telephony/gsm/SmsMessage;
+Lcom/android/internal/telephony/gsm/SmsMessage;->createFromPdu([B)Lcom/android/internal/telephony/gsm/SmsMessage;
+Lcom/android/internal/telephony/gsm/SmsMessage;->encodeUCS2(Ljava/lang/String;[B)[B
+Lcom/android/internal/telephony/gsm/SmsMessage;->getStatus()I
+Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZI)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z[B)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z[BIII)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPdu(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z[BIIII)Lcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;
+Lcom/android/internal/telephony/gsm/SmsMessage;->getSubmitPduHead(Ljava/lang/String;Ljava/lang/String;BZLcom/android/internal/telephony/gsm/SmsMessage$SubmitPdu;)Ljava/io/ByteArrayOutputStream;
+Lcom/android/internal/telephony/gsm/SmsMessage;->isMWIClearMessage()Z
+Lcom/android/internal/telephony/gsm/SmsMessage;->isMwiDontStore()Z
+Lcom/android/internal/telephony/gsm/SmsMessage;->isMWISetMessage()Z
+Lcom/android/internal/telephony/gsm/SmsMessage;->isStatusReportMessage()Z
+Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->loadEfFilesFromUsim()Ljava/util/ArrayList;
+Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->mPhoneBookRecords:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;->reset()V
 Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;-><init>()V
+Lcom/android/internal/telephony/GsmCdmaCall;->attachFake(Lcom/android/internal/telephony/Connection;Lcom/android/internal/telephony/Call$State;)V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->clearDisconnected()V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->dialThreeWay(Ljava/lang/String;)Lcom/android/internal/telephony/Connection;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->disableDataCallInEmergencyCall(Ljava/lang/String;)V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->fakeHoldForegroundBeforeDial()V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->getPhone()Lcom/android/internal/telephony/GsmCdmaPhone;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->handleEcmTimer(I)V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->isPhoneTypeGsm()Z
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->mBackgroundCall:Lcom/android/internal/telephony/GsmCdmaCall;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->mForegroundCall:Lcom/android/internal/telephony/GsmCdmaCall;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->mPendingMO:Lcom/android/internal/telephony/GsmCdmaConnection;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->mPhone:Lcom/android/internal/telephony/GsmCdmaPhone;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->mRingingCall:Lcom/android/internal/telephony/GsmCdmaCall;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->mState:Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->obtainCompleteMessage()Landroid/os/Message;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->obtainCompleteMessage(I)Landroid/os/Message;
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->setMute(Z)V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->switchWaitingOrHoldingAndActive()V
+Lcom/android/internal/telephony/GsmCdmaCallTracker;->updatePhoneState()V
+Lcom/android/internal/telephony/GsmCdmaConnection$MyHandler;-><init>(Lcom/android/internal/telephony/GsmCdmaConnection;Landroid/os/Looper;)V
+Lcom/android/internal/telephony/GsmCdmaConnection;->acquireWakeLock()V
+Lcom/android/internal/telephony/GsmCdmaConnection;->createWakeLock(Landroid/content/Context;)V
+Lcom/android/internal/telephony/GsmCdmaConnection;->disconnectCauseFromCode(I)I
+Lcom/android/internal/telephony/GsmCdmaConnection;->fetchDtmfToneDelay(Lcom/android/internal/telephony/GsmCdmaPhone;)V
+Lcom/android/internal/telephony/GsmCdmaConnection;->findNextPCharOrNonPOrNonWCharIndex(Ljava/lang/String;I)I
+Lcom/android/internal/telephony/GsmCdmaConnection;->findPOrWCharToAppend(Ljava/lang/String;II)C
+Lcom/android/internal/telephony/GsmCdmaConnection;->formatDialString(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/GsmCdmaConnection;->getState()Lcom/android/internal/telephony/Call$State;
+Lcom/android/internal/telephony/GsmCdmaConnection;->isPause(C)Z
+Lcom/android/internal/telephony/GsmCdmaConnection;->isPhoneTypeGsm()Z
+Lcom/android/internal/telephony/GsmCdmaConnection;->isWait(C)Z
+Lcom/android/internal/telephony/GsmCdmaConnection;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/GsmCdmaConnection;->maskDialString(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/GsmCdmaConnection;->mIndex:I
+Lcom/android/internal/telephony/GsmCdmaConnection;->mOwner:Lcom/android/internal/telephony/GsmCdmaCallTracker;
+Lcom/android/internal/telephony/GsmCdmaConnection;->onConnectedInOrOut()V
+Lcom/android/internal/telephony/GsmCdmaConnection;->updateParent(Lcom/android/internal/telephony/GsmCdmaCall;Lcom/android/internal/telephony/GsmCdmaCall;)V
+Lcom/android/internal/telephony/GsmCdmaPhone$Cfu;-><init>(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/GsmCdmaPhone;->exitEmergencyCallbackMode()V
+Lcom/android/internal/telephony/GsmCdmaPhone;->getCallTracker()Lcom/android/internal/telephony/CallTracker;
+Lcom/android/internal/telephony/GsmCdmaPhone;->getCdmaEriText()Ljava/lang/String;
+Lcom/android/internal/telephony/GsmCdmaPhone;->getEsn()Ljava/lang/String;
+Lcom/android/internal/telephony/GsmCdmaPhone;->getLine1Number()Ljava/lang/String;
+Lcom/android/internal/telephony/GsmCdmaPhone;->getPhoneType()I
+Lcom/android/internal/telephony/GsmCdmaPhone;->getServiceState()Landroid/telephony/ServiceState;
+Lcom/android/internal/telephony/GsmCdmaPhone;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/GsmCdmaPhone;->getSystemProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/GsmCdmaPhone;->handleInCallMmiCommands(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isCfEnable(I)Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isEriFileLoaded()Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isInCall()Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isManualSelProhibitedInGlobalMode()Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isPhoneTypeGsm()Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isValidCommandInterfaceCFAction(I)Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->isValidCommandInterfaceCFReason(I)Z
+Lcom/android/internal/telephony/GsmCdmaPhone;->logd(Ljava/lang/String;)V
+Lcom/android/internal/telephony/GsmCdmaPhone;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/GsmCdmaPhone;->mCT:Lcom/android/internal/telephony/GsmCdmaCallTracker;
+Lcom/android/internal/telephony/GsmCdmaPhone;->mEcmExitRespRegistrant:Landroid/os/Registrant;
+Lcom/android/internal/telephony/GsmCdmaPhone;->mEriManager:Lcom/android/internal/telephony/cdma/EriManager;
+Lcom/android/internal/telephony/GsmCdmaPhone;->mIccSmsInterfaceManager:Lcom/android/internal/telephony/IccSmsInterfaceManager;
+Lcom/android/internal/telephony/GsmCdmaPhone;->mIsimUiccRecords:Lcom/android/internal/telephony/uicc/IsimUiccRecords;
+Lcom/android/internal/telephony/GsmCdmaPhone;->mPendingMMIs:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/GsmCdmaPhone;->mSST:Lcom/android/internal/telephony/ServiceStateTracker;
+Lcom/android/internal/telephony/GsmCdmaPhone;->notifyPreciseCallStateChanged()V
+Lcom/android/internal/telephony/GsmCdmaPhone;->notifyServiceStateChanged(Landroid/telephony/ServiceState;)V
+Lcom/android/internal/telephony/GsmCdmaPhone;->setOnEcbModeExitResponse(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/GsmCdmaPhone;->syncClirSetting()V
 Lcom/android/internal/telephony/ICarrierConfigLoader;->getConfigForSubId(ILjava/lang/String;)Landroid/os/PersistableBundle;
+Lcom/android/internal/telephony/IccCard;->getState()Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCard;->registerForNetworkLocked(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/IccCard;->supplyNetworkDepersonalization(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/IccCard;->supplyPin(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/IccCard;->supplyPuk(Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/IccCardConstants$State;->ABSENT:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->CARD_IO_ERROR:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->NETWORK_LOCKED:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->NOT_READY:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->PERM_DISABLED:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->PIN_REQUIRED:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->PUK_REQUIRED:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->READY:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->UNKNOWN:Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccCardConstants$State;->values()[Lcom/android/internal/telephony/IccCardConstants$State;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->checkThread()V
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->DBG:Z
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->logd(Ljava/lang/String;)V
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mAdnCache:Lcom/android/internal/telephony/uicc/AdnRecordCache;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mBaseHandler:Landroid/os/Handler;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mCurrentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mIs3gCard:Z
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mRecords:Ljava/util/List;
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mRecordSize:[I
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mSuccess:Z
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->updateEfForIccType(I)I
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->waitForResult(Ljava/util/concurrent/atomic/AtomicBoolean;)V
+Lcom/android/internal/telephony/IccProvider;-><init>()V
+Lcom/android/internal/telephony/IccProvider;->ADDRESS_BOOK_COLUMN_NAMES:[Ljava/lang/String;
+Lcom/android/internal/telephony/IccProvider;->DBG:Z
+Lcom/android/internal/telephony/IccProvider;->loadRecord(Lcom/android/internal/telephony/uicc/AdnRecord;Landroid/database/MatrixCursor;I)V
+Lcom/android/internal/telephony/IccProvider;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->copyMessageToIccEf(Ljava/lang/String;I[B[B)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->disableCdmaBroadcastRange(II)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->disableGsmBroadcastRange(II)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->enableCdmaBroadcastRange(II)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->enableGsmBroadcastRange(II)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->enforceReceiveAndSend(Ljava/lang/String;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->filterDestAddress(Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->getAllMessagesFromIccEf(Ljava/lang/String;)Ljava/util/List;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->getImsSmsFormat()Ljava/lang/String;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->getPremiumSmsPermission(Ljava/lang/String;)I
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->injectSmsPdu([BLjava/lang/String;Landroid/app/PendingIntent;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->isImsSmsSupported()Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mAppOps:Landroid/app/AppOpsManager;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mCellBroadcastRangeManager:Lcom/android/internal/telephony/IccSmsInterfaceManager$CellBroadcastRangeManager;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mHandler:Landroid/os/Handler;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mSms:Ljava/util/List;
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->mSuccess:Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->sendData(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I[BLandroid/app/PendingIntent;Landroid/app/PendingIntent;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->sendStoredMultipartText(Ljava/lang/String;Landroid/net/Uri;Ljava/lang/String;Ljava/util/List;Ljava/util/List;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->sendStoredText(Ljava/lang/String;Landroid/net/Uri;Ljava/lang/String;Landroid/app/PendingIntent;Landroid/app/PendingIntent;)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->setCdmaBroadcastConfig([Lcom/android/internal/telephony/cdma/CdmaSmsBroadcastConfigInfo;)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->setCellBroadcastConfig([Lcom/android/internal/telephony/gsm/SmsBroadcastConfigInfo;)Z
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->setPremiumSmsPermission(Ljava/lang/String;I)V
+Lcom/android/internal/telephony/IccSmsInterfaceManager;->updateMessageOnIccEf(Ljava/lang/String;II[B)Z
+Lcom/android/internal/telephony/IIccPhoneBook$Stub$Proxy;->mRemote:Landroid/os/IBinder;
+Lcom/android/internal/telephony/IIccPhoneBook$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IIccPhoneBook;
+Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsInEf(I)Ljava/util/List;
+Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsInEfForSubscriber(II)Ljava/util/List;
+Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsSize(I)[I
+Lcom/android/internal/telephony/IIccPhoneBook;->getAdnRecordsSizeForSubscriber(II)[I
+Lcom/android/internal/telephony/IIccPhoneBook;->updateAdnRecordsInEfBySearch(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
 Lcom/android/internal/telephony/IMms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IMms;
+Lcom/android/internal/telephony/imsphone/ImsExternalCall;-><init>(Lcom/android/internal/telephony/Phone;Lcom/android/internal/telephony/imsphone/ImsExternalConnection;)V
+Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker$ExternalCallStateListener;-><init>(Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker;)V
+Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker$ExternalConnectionListener;-><init>(Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker;)V
+Lcom/android/internal/telephony/imsphone/ImsExternalConnection;->rebuildCapabilities()V
+Lcom/android/internal/telephony/imsphone/ImsExternalConnection;->setActive()V
+Lcom/android/internal/telephony/imsphone/ImsPhone$Cf;-><init>(Ljava/lang/String;ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getActionFromCFAction(I)I
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getBackgroundCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getCallForwardingOption(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getCallWaiting(Landroid/os/Message;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getConditionFromCFReason(I)I
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getForegroundCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getRingingCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getServiceState()Landroid/telephony/ServiceState;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->handleEnterEmergencyCallbackMode()V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->handleExitEmergencyCallbackMode()V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->handleInCallMmiCommands(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/imsphone/ImsPhone;->isCfEnable(I)Z
+Lcom/android/internal/telephony/imsphone/ImsPhone;->isUtEnabled()Z
+Lcom/android/internal/telephony/imsphone/ImsPhone;->isValidCommandInterfaceCFAction(I)Z
+Lcom/android/internal/telephony/imsphone/ImsPhone;->isValidCommandInterfaceCFReason(I)Z
+Lcom/android/internal/telephony/imsphone/ImsPhone;->isVolteEnabled()Z
+Lcom/android/internal/telephony/imsphone/ImsPhone;->mCT:Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->mPendingMMIs:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->mSS:Landroid/telephony/ServiceState;
+Lcom/android/internal/telephony/imsphone/ImsPhone;->notifyCallForwardingIndicator()V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->notifyPreciseCallStateChanged()V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->notifyUnknownConnection(Lcom/android/internal/telephony/Connection;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->onMMIDone(Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->sendErrorResponse(Landroid/os/Message;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->sendErrorResponse(Landroid/os/Message;Ljava/lang/Throwable;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->setCallForwardingOption(IILjava/lang/String;IILandroid/os/Message;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->setCallWaiting(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->setImsRegistered(Z)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->setOnEcbModeExitResponse(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/imsphone/ImsPhone;->setServiceState(I)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->attach(Lcom/android/internal/telephony/Connection;Lcom/android/internal/telephony/Call$State;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->attachFake(Lcom/android/internal/telephony/Connection;Lcom/android/internal/telephony/Call$State;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->getConnections()Ljava/util/List;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->getImsCall()Lcom/android/ims/ImsCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->hangup()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->merge(Lcom/android/internal/telephony/imsphone/ImsPhoneCall;Lcom/android/internal/telephony/Call$State;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCall;->onHangupLocal()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->addConnection(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->clearDisconnected()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->dial(Ljava/lang/String;ILandroid/os/Bundle;)Lcom/android/internal/telephony/Connection;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->dialPendingMO()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->findConnection(Lcom/android/ims/ImsCall;)Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->getEcbmInterface()Lcom/android/ims/ImsEcbm;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->getUtInterface()Lcom/android/ims/ImsUtInterface;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->handleEcmTimer(I)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mAllowEmergencyVideoCalls:Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mBackgroundCall:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mCallExpectedToResume:Lcom/android/ims/ImsCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mConnections:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mForegroundCall:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mHandoverCall:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mImsCallListener:Lcom/android/ims/ImsCall$Listener;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mImsManager:Lcom/android/ims/ImsManager;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mOnHoldToneId:I
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mOnHoldToneStarted:Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mPendingMO:Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mPendingUssd:Landroid/os/Message;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mPhone:Lcom/android/internal/telephony/imsphone/ImsPhone;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mRingingCall:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mSwitchingFgAndBgCalls:Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mSyncHold:Ljava/lang/Object;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->mUssdSession:Lcom/android/ims/ImsCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->processCallStateChange(Lcom/android/ims/ImsCall;Lcom/android/internal/telephony/Call$State;I)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->processCallStateChange(Lcom/android/ims/ImsCall;Lcom/android/internal/telephony/Call$State;IZ)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->removeConnection(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->setVideoCallProvider(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;Lcom/android/ims/ImsCall;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->switchAfterConferenceSuccess()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;->updatePhoneState()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection$MyHandler;-><init>(Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;Landroid/os/Looper;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->acquireWakeLock()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->createWakeLock(Landroid/content/Context;)V
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->getCall()Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->getOwner()Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->isMultiparty()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mDisconnected:Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mImsCall:Lcom/android/ims/ImsCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mOwner:Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker;
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->mParent:Lcom/android/internal/telephony/imsphone/ImsPhoneCall;
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->onDisconnect()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneConnection;->update(Lcom/android/ims/ImsCall;Lcom/android/internal/telephony/Call$State;)Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->getCLIRMode()I
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->getDialingNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->getErrorMessage(Landroid/os/AsyncResult;)Ljava/lang/CharSequence;
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->getScString()Ljava/lang/CharSequence;
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isActivate()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isDeactivate()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isEmptyOrNull(Ljava/lang/CharSequence;)Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isErasure()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isRegister()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isSupportedOverImsPhone()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->isTemporaryModeCLIR()Z
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->mPhone:Lcom/android/internal/telephony/imsphone/ImsPhone;
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->newFromDialString(Ljava/lang/String;Lcom/android/internal/telephony/imsphone/ImsPhone;)Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->processCode()V
+Lcom/android/internal/telephony/imsphone/ImsPhoneMmiCode;->serviceClassToCFString(I)Ljava/lang/CharSequence;
+Lcom/android/internal/telephony/InboundSmsHandler$SmsBroadcastReceiver;-><init>(Lcom/android/internal/telephony/InboundSmsHandler;Lcom/android/internal/telephony/InboundSmsTracker;)V
+Lcom/android/internal/telephony/InboundSmsHandler$SmsBroadcastReceiver;->mDeleteWhere:Ljava/lang/String;
+Lcom/android/internal/telephony/InboundSmsHandler$SmsBroadcastReceiver;->mDeleteWhereArgs:[Ljava/lang/String;
+Lcom/android/internal/telephony/InboundSmsHandler;->acknowledgeLastIncomingSms(ZILandroid/os/Message;)V
+Lcom/android/internal/telephony/InboundSmsHandler;->deleteFromRawTable(Ljava/lang/String;[Ljava/lang/String;I)V
+Lcom/android/internal/telephony/InboundSmsHandler;->dispatchIntent(Landroid/content/Intent;Ljava/lang/String;ILandroid/os/Bundle;Landroid/content/BroadcastReceiver;Landroid/os/UserHandle;)V
+Lcom/android/internal/telephony/InboundSmsHandler;->dispatchNormalMessage(Lcom/android/internal/telephony/SmsMessageBase;)I
+Lcom/android/internal/telephony/InboundSmsHandler;->getPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/InboundSmsHandler;->handleInjectSms(Landroid/os/AsyncResult;)V
+Lcom/android/internal/telephony/InboundSmsHandler;->handleNewSms(Landroid/os/AsyncResult;)V
+Lcom/android/internal/telephony/InboundSmsHandler;->handleSmsWhitelisting(Landroid/content/ComponentName;)Landroid/os/Bundle;
+Lcom/android/internal/telephony/InboundSmsHandler;->isSkipNotifyFlagSet(I)Z
+Lcom/android/internal/telephony/InboundSmsHandler;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/InboundSmsHandler;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/InboundSmsHandler;->mCellBroadcastHandler:Lcom/android/internal/telephony/CellBroadcastHandler;
+Lcom/android/internal/telephony/InboundSmsHandler;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/InboundSmsHandler;->mDeliveringState:Lcom/android/internal/telephony/InboundSmsHandler$DeliveringState;
+Lcom/android/internal/telephony/InboundSmsHandler;->mDeviceIdleController:Landroid/os/IDeviceIdleController;
+Lcom/android/internal/telephony/InboundSmsHandler;->mIdleState:Lcom/android/internal/telephony/InboundSmsHandler$IdleState;
+Lcom/android/internal/telephony/InboundSmsHandler;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/InboundSmsHandler;->mResolver:Landroid/content/ContentResolver;
+Lcom/android/internal/telephony/InboundSmsHandler;->mUserManager:Landroid/os/UserManager;
+Lcom/android/internal/telephony/InboundSmsHandler;->mWaitingState:Lcom/android/internal/telephony/InboundSmsHandler$WaitingState;
+Lcom/android/internal/telephony/InboundSmsHandler;->mWakeLock:Landroid/os/PowerManager$WakeLock;
+Lcom/android/internal/telephony/InboundSmsHandler;->mWapPush:Lcom/android/internal/telephony/WapPushOverSms;
+Lcom/android/internal/telephony/InboundSmsHandler;->processMessagePart(Lcom/android/internal/telephony/InboundSmsTracker;)Z
+Lcom/android/internal/telephony/InboundSmsHandler;->showNewMessageNotification()V
+Lcom/android/internal/telephony/InboundSmsHandler;->writeInboxMessage(Landroid/content/Intent;)Landroid/net/Uri;
+Lcom/android/internal/telephony/InboundSmsTracker;->getFormat()Ljava/lang/String;
+Lcom/android/internal/telephony/InboundSmsTracker;->getIndexOffset()I
+Lcom/android/internal/telephony/IntRangeManager;->mRanges:Ljava/util/ArrayList;
 Lcom/android/internal/telephony/IPhoneStateListener$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneStateListener;
 Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;->getDeviceId(Ljava/lang/String;)Ljava/lang/String;
@@ -2060,16 +3233,808 @@
 Lcom/android/internal/telephony/IWapPushManager;->addPackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZ)Z
 Lcom/android/internal/telephony/IWapPushManager;->deletePackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z
 Lcom/android/internal/telephony/IWapPushManager;->updatePackage(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZ)Z
+Lcom/android/internal/telephony/MccTable$MccEntry;->mIso:Ljava/lang/String;
+Lcom/android/internal/telephony/MccTable;->countryCodeForMcc(I)Ljava/lang/String;
+Lcom/android/internal/telephony/MccTable;->defaultLanguageForMcc(I)Ljava/lang/String;
+Lcom/android/internal/telephony/MccTable;->defaultTimeZoneForMcc(I)Ljava/lang/String;
+Lcom/android/internal/telephony/MccTable;->entryForMcc(I)Lcom/android/internal/telephony/MccTable$MccEntry;
+Lcom/android/internal/telephony/MccTable;->getLocaleForLanguageCountry(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)Ljava/util/Locale;
+Lcom/android/internal/telephony/MccTable;->smallestDigitsMccForMnc(I)I
+Lcom/android/internal/telephony/MmiCode$State;->CANCELLED:Lcom/android/internal/telephony/MmiCode$State;
+Lcom/android/internal/telephony/MmiCode$State;->COMPLETE:Lcom/android/internal/telephony/MmiCode$State;
+Lcom/android/internal/telephony/MmiCode$State;->FAILED:Lcom/android/internal/telephony/MmiCode$State;
+Lcom/android/internal/telephony/MmiCode$State;->PENDING:Lcom/android/internal/telephony/MmiCode$State;
+Lcom/android/internal/telephony/MmiCode;->getPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/Phone;->dispose()V
+Lcom/android/internal/telephony/Phone;->exitEmergencyCallbackMode()V
+Lcom/android/internal/telephony/Phone;->getActiveApnTypes()[Ljava/lang/String;
+Lcom/android/internal/telephony/Phone;->getCallTracker()Lcom/android/internal/telephony/CallTracker;
+Lcom/android/internal/telephony/Phone;->getCellLocation()Landroid/telephony/CellLocation;
+Lcom/android/internal/telephony/Phone;->getContext()Landroid/content/Context;
+Lcom/android/internal/telephony/Phone;->getDataConnectionState()Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/Phone;->getIccCard()Lcom/android/internal/telephony/IccCard;
+Lcom/android/internal/telephony/Phone;->getIccFileHandler()Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/Phone;->getIccSerialNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/Phone;->getIccSmsInterfaceManager()Lcom/android/internal/telephony/IccSmsInterfaceManager;
+Lcom/android/internal/telephony/Phone;->getImsPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/Phone;->getIsimRecords()Lcom/android/internal/telephony/uicc/IsimRecords;
+Lcom/android/internal/telephony/Phone;->getMsisdn()Ljava/lang/String;
+Lcom/android/internal/telephony/Phone;->getNai()Ljava/lang/String;
+Lcom/android/internal/telephony/Phone;->getPhoneId()I
+Lcom/android/internal/telephony/Phone;->getPhoneName()Ljava/lang/String;
+Lcom/android/internal/telephony/Phone;->getPhoneType()I
+Lcom/android/internal/telephony/Phone;->getServiceStateTracker()Lcom/android/internal/telephony/ServiceStateTracker;
+Lcom/android/internal/telephony/Phone;->getSmscAddress(Landroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->getState()Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/Phone;->getSubId()I
+Lcom/android/internal/telephony/Phone;->getSystemProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/Phone;->getUiccCard()Lcom/android/internal/telephony/uicc/UiccCard;
+Lcom/android/internal/telephony/Phone;->getVideoState(Lcom/android/internal/telephony/Call;)I
+Lcom/android/internal/telephony/Phone;->invokeOemRilRequestRaw([BLandroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->invokeOemRilRequestStrings([Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->isCspPlmnEnabled()Z
+Lcom/android/internal/telephony/Phone;->isUtEnabled()Z
+Lcom/android/internal/telephony/Phone;->isVideoEnabled()Z
+Lcom/android/internal/telephony/Phone;->isVolteEnabled()Z
+Lcom/android/internal/telephony/Phone;->isWifiCallingEnabled()Z
+Lcom/android/internal/telephony/Phone;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/Phone;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/Phone;->mDcTracker:Lcom/android/internal/telephony/dataconnection/DcTracker;
+Lcom/android/internal/telephony/Phone;->mIccRecords:Ljava/util/concurrent/atomic/AtomicReference;
+Lcom/android/internal/telephony/Phone;->mImsPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/Phone;->mMmiRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/Phone;->mNotifier:Lcom/android/internal/telephony/PhoneNotifier;
+Lcom/android/internal/telephony/Phone;->mPhoneId:I
+Lcom/android/internal/telephony/Phone;->mSmsStorageMonitor:Lcom/android/internal/telephony/SmsStorageMonitor;
+Lcom/android/internal/telephony/Phone;->mUiccApplication:Ljava/util/concurrent/atomic/AtomicReference;
+Lcom/android/internal/telephony/Phone;->mUiccController:Lcom/android/internal/telephony/uicc/UiccController;
+Lcom/android/internal/telephony/Phone;->needsOtaServiceProvisioning()Z
+Lcom/android/internal/telephony/Phone;->notifyOtaspChanged(I)V
+Lcom/android/internal/telephony/Phone;->registerForDisconnect(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForEcmTimerReset(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForIncomingRing(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForMmiComplete(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForMmiInitiate(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForNewRingingConnection(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForPreciseCallStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForRingbackTone(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForServiceStateChanged(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForSimRecordsLoaded(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->registerForUnknownConnection(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->selectNetworkManually(Lcom/android/internal/telephony/OperatorInfo;ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->setNetworkSelectionModeAutomatic(Landroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->setOnEcbModeExitResponse(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->setOnPostDialCharacter(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/Phone;->setPreferredNetworkType(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->setSmscAddress(Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/Phone;->unregisterForDisconnect(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForEcmTimerReset(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForIncomingRing(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForMmiComplete(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForMmiInitiate(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForNewRingingConnection(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForPreciseCallStateChanged(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForRingbackTone(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForServiceStateChanged(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForSimRecordsLoaded(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unregisterForUnknownConnection(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/Phone;->unsetOnEcbModeExitResponse(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/PhoneConstants$DataState;->CONNECTED:Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/PhoneConstants$DataState;->CONNECTING:Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/PhoneConstants$DataState;->DISCONNECTED:Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/PhoneConstants$DataState;->SUSPENDED:Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/PhoneConstants$DataState;->values()[Lcom/android/internal/telephony/PhoneConstants$DataState;
+Lcom/android/internal/telephony/PhoneConstants$State;->IDLE:Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/PhoneConstants$State;->OFFHOOK:Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/PhoneConstants$State;->RINGING:Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/PhoneConstants$State;->values()[Lcom/android/internal/telephony/PhoneConstants$State;
+Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_ALLOWED:I
+Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_PAYPHONE:I
+Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_RESTRICTED:I
+Lcom/android/internal/telephony/PhoneConstants;->PRESENTATION_UNKNOWN:I
+Lcom/android/internal/telephony/PhoneFactory;->calculatePreferredNetworkType(Landroid/content/Context;I)I
+Lcom/android/internal/telephony/PhoneFactory;->getDefaultPhone()Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/PhoneFactory;->getDefaultSubscription()I
+Lcom/android/internal/telephony/PhoneFactory;->getPhone(I)Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/PhoneFactory;->getPhones()[Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/PhoneFactory;->makeDefaultPhone(Landroid/content/Context;)V
+Lcom/android/internal/telephony/PhoneFactory;->sCommandsInterface:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/PhoneFactory;->sContext:Landroid/content/Context;
+Lcom/android/internal/telephony/PhoneFactory;->sMadeDefaults:Z
+Lcom/android/internal/telephony/PhoneFactory;->sPhoneNotifier:Lcom/android/internal/telephony/PhoneNotifier;
+Lcom/android/internal/telephony/PhoneInternalInterface$DataActivityState;->NONE:Lcom/android/internal/telephony/PhoneInternalInterface$DataActivityState;
+Lcom/android/internal/telephony/PhoneInternalInterface;->PREFERRED_NT_MODE:I
+Lcom/android/internal/telephony/PhoneNotifier;->notifyMessageWaitingChanged(Lcom/android/internal/telephony/Phone;)V
+Lcom/android/internal/telephony/PhoneNotifier;->notifySignalStrength(Lcom/android/internal/telephony/Phone;)V
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;-><init>(Landroid/content/Context;Landroid/os/Handler;)V
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->getSignalStrengthDbm()I
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->mSignalStrength:Landroid/telephony/SignalStrength;
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->mWants:I
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->notifyServiceState(I)V
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->notifySignalStrength(I)V
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->registerIntent()V
+Lcom/android/internal/telephony/PhoneStateIntentReceiver;->unregisterIntent()V
+Lcom/android/internal/telephony/PhoneSubInfoController;->getDefaultSubscription()I
+Lcom/android/internal/telephony/PhoneSubInfoController;->getPhone(I)Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/PhoneSubInfoController;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/PhoneSubInfoController;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/PhoneSubInfoController;->mPhone:[Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/PhoneSwitcher;->activate(I)V
+Lcom/android/internal/telephony/PhoneSwitcher;->deactivate(I)V
+Lcom/android/internal/telephony/PhoneSwitcher;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/PhoneSwitcher;->mMaxActivePhones:I
+Lcom/android/internal/telephony/PhoneSwitcher;->mNumPhones:I
+Lcom/android/internal/telephony/PhoneSwitcher;->mPhones:[Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/ProxyController;->completeRadioCapabilityTransaction()V
+Lcom/android/internal/telephony/ProxyController;->getInstance()Lcom/android/internal/telephony/ProxyController;
+Lcom/android/internal/telephony/ProxyController;->logd(Ljava/lang/String;)V
+Lcom/android/internal/telephony/ProxyController;->mOldRadioAccessFamily:[I
+Lcom/android/internal/telephony/ProxyController;->mRadioCapabilitySessionId:I
+Lcom/android/internal/telephony/ProxyController;->mSetRadioAccessFamilyStatus:[I
+Lcom/android/internal/telephony/ProxyController;->mUniqueIdGenerator:Ljava/util/concurrent/atomic/AtomicInteger;
+Lcom/android/internal/telephony/ProxyController;->registerForAllDataDisconnected(ILandroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/ProxyController;->sendRadioCapabilityRequest(IIIILjava/lang/String;II)V
+Lcom/android/internal/telephony/ProxyController;->sProxyController:Lcom/android/internal/telephony/ProxyController;
+Lcom/android/internal/telephony/RadioCapability;->getRadioAccessFamily()I
+Lcom/android/internal/telephony/RetryManager;->configure(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/RetryManager;->getRetryTimer()I
+Lcom/android/internal/telephony/RetryManager;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/RetryManager;->mApnType:Ljava/lang/String;
+Lcom/android/internal/telephony/RetryManager;->mFailFastInterApnDelay:J
+Lcom/android/internal/telephony/RetryManager;->mInterApnDelay:J
+Lcom/android/internal/telephony/RetryManager;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/RIL;-><init>(Landroid/content/Context;II)V
+Lcom/android/internal/telephony/RIL;-><init>(Landroid/content/Context;IILjava/lang/Integer;)V
+Lcom/android/internal/telephony/RIL;->acquireWakeLock(Lcom/android/internal/telephony/RILRequest;I)V
+Lcom/android/internal/telephony/RIL;->clearRequestList(IZ)V
+Lcom/android/internal/telephony/RIL;->clearWakeLock(I)Z
+Lcom/android/internal/telephony/RIL;->decrementWakeLock(Lcom/android/internal/telephony/RILRequest;)V
+Lcom/android/internal/telephony/RIL;->findAndRemoveRequestFromList(I)Lcom/android/internal/telephony/RILRequest;
+Lcom/android/internal/telephony/RIL;->getResponseForTimedOutRILRequest(Lcom/android/internal/telephony/RILRequest;)Ljava/lang/Object;
+Lcom/android/internal/telephony/RIL;->hangupForegroundResumeBackground(Landroid/os/Message;)V
+Lcom/android/internal/telephony/RIL;->hangupWaitingOrBackground(Landroid/os/Message;)V
+Lcom/android/internal/telephony/RIL;->invokeOemRilRequestRaw([BLandroid/os/Message;)V
+Lcom/android/internal/telephony/RIL;->makeStaticRadioCapability()Lcom/android/internal/telephony/RadioCapability;
+Lcom/android/internal/telephony/RIL;->mRequestList:Landroid/util/SparseArray;
+Lcom/android/internal/telephony/RIL;->mTestingEmergencyCall:Ljava/util/concurrent/atomic/AtomicBoolean;
+Lcom/android/internal/telephony/RIL;->mWakeLock:Landroid/os/PowerManager$WakeLock;
+Lcom/android/internal/telephony/RIL;->notifyRegistrantsCdmaInfoRec(Lcom/android/internal/telephony/cdma/CdmaInformationRecords;)V
+Lcom/android/internal/telephony/RIL;->notifyRegistrantsRilConnectionChanged(I)V
+Lcom/android/internal/telephony/RIL;->requestToString(I)Ljava/lang/String;
+Lcom/android/internal/telephony/RIL;->responseToString(I)Ljava/lang/String;
+Lcom/android/internal/telephony/RIL;->retToString(ILjava/lang/Object;)Ljava/lang/String;
+Lcom/android/internal/telephony/RIL;->riljLog(Ljava/lang/String;)V
+Lcom/android/internal/telephony/RIL;->setRadioPower(ZLandroid/os/Message;)V
+Lcom/android/internal/telephony/RIL;->unsljLog(I)V
+Lcom/android/internal/telephony/RIL;->unsljLogMore(ILjava/lang/String;)V
+Lcom/android/internal/telephony/RIL;->unsljLogRet(ILjava/lang/Object;)V
+Lcom/android/internal/telephony/RIL;->unsljLogvRet(ILjava/lang/Object;)V
+Lcom/android/internal/telephony/RILConstants;->PREFERRED_NETWORK_MODE:I
+Lcom/android/internal/telephony/RILRequest;->mRequest:I
+Lcom/android/internal/telephony/RILRequest;->mResult:Landroid/os/Message;
+Lcom/android/internal/telephony/RILRequest;->mSerial:I
+Lcom/android/internal/telephony/RILRequest;->obtain(ILandroid/os/Message;)Lcom/android/internal/telephony/RILRequest;
+Lcom/android/internal/telephony/RILRequest;->onError(ILjava/lang/Object;)V
+Lcom/android/internal/telephony/RILRequest;->release()V
+Lcom/android/internal/telephony/RILRequest;->serialString()Ljava/lang/String;
+Lcom/android/internal/telephony/ServiceStateTracker;->fixUnknownMcc(Ljava/lang/String;I)Ljava/lang/String;
+Lcom/android/internal/telephony/ServiceStateTracker;->getCurrentDataConnectionState()I
+Lcom/android/internal/telephony/ServiceStateTracker;->getDesiredPowerState()Z
+Lcom/android/internal/telephony/ServiceStateTracker;->getPhoneId()I
+Lcom/android/internal/telephony/ServiceStateTracker;->getSystemProperty(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/ServiceStateTracker;->isConcurrentVoiceAndDataAllowed()Z
+Lcom/android/internal/telephony/ServiceStateTracker;->isGprsConsistent(II)Z
+Lcom/android/internal/telephony/ServiceStateTracker;->isImsRegistered()Z
+Lcom/android/internal/telephony/ServiceStateTracker;->isInHomeSidNid(II)Z
+Lcom/android/internal/telephony/ServiceStateTracker;->isInvalidOperatorNumeric(Ljava/lang/String;)Z
+Lcom/android/internal/telephony/ServiceStateTracker;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/ServiceStateTracker;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/ServiceStateTracker;->mAttachedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/ServiceStateTracker;->mCr:Landroid/content/ContentResolver;
+Lcom/android/internal/telephony/ServiceStateTracker;->mCurDataSpn:Ljava/lang/String;
+Lcom/android/internal/telephony/ServiceStateTracker;->mCurPlmn:Ljava/lang/String;
+Lcom/android/internal/telephony/ServiceStateTracker;->mCurShowPlmn:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mCurShowSpn:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mCurSpn:Ljava/lang/String;
+Lcom/android/internal/telephony/ServiceStateTracker;->mDataRoamingOffRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->mDataRoamingOnRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->mDefaultRoamingIndicator:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mDesiredPowerState:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mDetachedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->mDeviceShuttingDown:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mEmergencyOnly:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mIccRecords:Lcom/android/internal/telephony/uicc/IccRecords;
+Lcom/android/internal/telephony/ServiceStateTracker;->mIntentReceiver:Landroid/content/BroadcastReceiver;
+Lcom/android/internal/telephony/ServiceStateTracker;->mIsSubscriptionFromRuim:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mMaxDataCalls:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mNetworkAttachedRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->mNewMaxDataCalls:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mNewReasonDataDenied:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mNewSS:Landroid/telephony/ServiceState;
+Lcom/android/internal/telephony/ServiceStateTracker;->mOnSubscriptionsChangedListener:Lcom/android/internal/telephony/ServiceStateTracker$SstSubscriptionsChangedListener;
+Lcom/android/internal/telephony/ServiceStateTracker;->mPhone:Lcom/android/internal/telephony/GsmCdmaPhone;
+Lcom/android/internal/telephony/ServiceStateTracker;->mPreferredNetworkType:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mReasonDataDenied:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mReportedGprsNoReg:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mRoamingIndicator:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mSignalStrength:Landroid/telephony/SignalStrength;
+Lcom/android/internal/telephony/ServiceStateTracker;->mSpnUpdatePending:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mSS:Landroid/telephony/ServiceState;
+Lcom/android/internal/telephony/ServiceStateTracker;->mStartedGprsRegCheck:Z
+Lcom/android/internal/telephony/ServiceStateTracker;->mSubId:I
+Lcom/android/internal/telephony/ServiceStateTracker;->mSubscriptionController:Lcom/android/internal/telephony/SubscriptionController;
+Lcom/android/internal/telephony/ServiceStateTracker;->mSubscriptionManager:Landroid/telephony/SubscriptionManager;
+Lcom/android/internal/telephony/ServiceStateTracker;->mUiccApplcation:Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/ServiceStateTracker;->mUiccController:Lcom/android/internal/telephony/uicc/UiccController;
+Lcom/android/internal/telephony/ServiceStateTracker;->mVoiceRoamingOffRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->mVoiceRoamingOnRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/ServiceStateTracker;->notifyDataRegStateRilRadioTechnologyChanged()V
+Lcom/android/internal/telephony/ServiceStateTracker;->notifySignalStrength()Z
+Lcom/android/internal/telephony/ServiceStateTracker;->pollState()V
+Lcom/android/internal/telephony/ServiceStateTracker;->powerOffRadioSafely(Lcom/android/internal/telephony/dataconnection/DcTracker;)V
+Lcom/android/internal/telephony/ServiceStateTracker;->reRegisterNetwork(Landroid/os/Message;)V
+Lcom/android/internal/telephony/ServiceStateTracker;->resetServiceStateInIwlanMode()V
+Lcom/android/internal/telephony/ServiceStateTracker;->setOperatorIdd(Ljava/lang/String;)V
+Lcom/android/internal/telephony/ServiceStateTracker;->setRoamingType(Landroid/telephony/ServiceState;)V
+Lcom/android/internal/telephony/ServiceStateTracker;->setSignalStrengthDefaultValues()V
+Lcom/android/internal/telephony/ServiceStateTracker;->updateOtaspState()V
+Lcom/android/internal/telephony/ServiceStateTracker;->updatePhoneObject()V
+Lcom/android/internal/telephony/ServiceStateTracker;->updateRoamingState()V
+Lcom/android/internal/telephony/ServiceStateTracker;->updateSpnDisplay()V
+Lcom/android/internal/telephony/ServiceStateTracker;->useDataRegStateForDataOnlyDevices()V
+Lcom/android/internal/telephony/sip/SipPhone$SipCall;->hold()V
+Lcom/android/internal/telephony/sip/SipPhone$SipCall;->switchWith(Lcom/android/internal/telephony/sip/SipPhone$SipCall;)V
+Lcom/android/internal/telephony/sip/SipPhone$SipCall;->unhold()V
+Lcom/android/internal/telephony/sip/SipPhone;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/sip/SipPhone;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/sip/SipPhone;->mBackgroundCall:Lcom/android/internal/telephony/sip/SipPhone$SipCall;
+Lcom/android/internal/telephony/sip/SipPhone;->mForegroundCall:Lcom/android/internal/telephony/sip/SipPhone$SipCall;
+Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->DBG:Z
+Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableCDMA:Landroid/util/SparseIntArray;
+Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableCommon:Landroid/util/SparseIntArray;
+Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableGSM:Landroid/util/SparseIntArray;
+Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->translate(Ljava/lang/CharSequence;)Ljava/lang/String;
+Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->useCdmaFormatForMoSms()Z
+Lcom/android/internal/telephony/SmsApplication$SmsApplicationData;->mApplicationName:Ljava/lang/String;
+Lcom/android/internal/telephony/SmsApplication;->configurePreferredActivity(Landroid/content/pm/PackageManager;Landroid/content/ComponentName;I)V
+Lcom/android/internal/telephony/SmsApplication;->getApplicationCollection(Landroid/content/Context;)Ljava/util/Collection;
+Lcom/android/internal/telephony/SmsApplication;->getDefaultMmsApplication(Landroid/content/Context;Z)Landroid/content/ComponentName;
+Lcom/android/internal/telephony/SmsApplication;->getDefaultRespondViaMessageApplication(Landroid/content/Context;Z)Landroid/content/ComponentName;
+Lcom/android/internal/telephony/SmsApplication;->getDefaultSmsApplication(Landroid/content/Context;Z)Landroid/content/ComponentName;
+Lcom/android/internal/telephony/SmsApplication;->getSmsApplicationData(Ljava/lang/String;Landroid/content/Context;)Lcom/android/internal/telephony/SmsApplication$SmsApplicationData;
+Lcom/android/internal/telephony/SmsApplication;->isDefaultSmsApplication(Landroid/content/Context;Ljava/lang/String;)Z
+Lcom/android/internal/telephony/SmsApplication;->setDefaultApplication(Ljava/lang/String;Landroid/content/Context;)V
+Lcom/android/internal/telephony/SmsApplication;->shouldWriteMessageForPackage(Ljava/lang/String;Landroid/content/Context;)Z
+Lcom/android/internal/telephony/SmsBroadcastUndelivered;-><init>(Landroid/content/Context;Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler;Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler;)V
+Lcom/android/internal/telephony/SMSDispatcher$ConfirmDialogListener;->mNegativeButton:Landroid/widget/Button;
+Lcom/android/internal/telephony/SMSDispatcher$ConfirmDialogListener;->mPositiveButton:Landroid/widget/Button;
+Lcom/android/internal/telephony/SMSDispatcher$ConfirmDialogListener;->mRememberUndoInstruction:Landroid/widget/TextView;
+Lcom/android/internal/telephony/SMSDispatcher$DataSmsSender;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSender;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Ljava/util/ArrayList;[Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSender;->sendSmsByCarrierApp(Ljava/lang/String;Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSenderCallback;)V
+Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSenderCallback;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$MultipartSmsSender;)V
+Lcom/android/internal/telephony/SMSDispatcher$SmsSenderCallback;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$SmsSender;)V
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->isMultipart()Z
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mAppInfo:Landroid/content/pm/PackageInfo;
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mData:Ljava/util/HashMap;
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mDeliveryIntent:Landroid/app/PendingIntent;
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mDestAddress:Ljava/lang/String;
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mMessageRef:I
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mMessageUri:Landroid/net/Uri;
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mPersistMessage:Z
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mSentIntent:Landroid/app/PendingIntent;
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->mTimestamp:J
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->onFailed(Landroid/content/Context;II)V
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->onSent(Landroid/content/Context;)V
+Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;->updateSentMessageStatus(Landroid/content/Context;I)V
+Lcom/android/internal/telephony/SMSDispatcher$TextSmsSender;-><init>(Lcom/android/internal/telephony/SMSDispatcher;Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/SMSDispatcher;->calculateLength(Ljava/lang/CharSequence;Z)Lcom/android/internal/telephony/GsmAlphabet$TextEncodingDetails;
+Lcom/android/internal/telephony/SMSDispatcher;->checkCallerIsPhoneOrCarrierApp()V
+Lcom/android/internal/telephony/SMSDispatcher;->deliveryPendingList:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/SMSDispatcher;->dispose()V
+Lcom/android/internal/telephony/SMSDispatcher;->getCarrierAppPackageName()Ljava/lang/String;
+Lcom/android/internal/telephony/SMSDispatcher;->getMultipartMessageText(Ljava/util/ArrayList;)Ljava/lang/String;
+Lcom/android/internal/telephony/SMSDispatcher;->getNextConcatenatedRef()I
+Lcom/android/internal/telephony/SMSDispatcher;->getSubId()I
+Lcom/android/internal/telephony/SMSDispatcher;->handleConfirmShortCode(ZLcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/SMSDispatcher;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/SMSDispatcher;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/SMSDispatcher;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/SMSDispatcher;->mResolver:Landroid/content/ContentResolver;
+Lcom/android/internal/telephony/SMSDispatcher;->mTelephonyManager:Landroid/telephony/TelephonyManager;
+Lcom/android/internal/telephony/SMSDispatcher;->processSendSmsResponse(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;II)V
+Lcom/android/internal/telephony/SMSDispatcher;->sendData(Ljava/lang/String;Ljava/lang/String;I[BLandroid/app/PendingIntent;Landroid/app/PendingIntent;)V
+Lcom/android/internal/telephony/SMSDispatcher;->sendMultipartSms(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/SMSDispatcher;->sendSms(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
+Lcom/android/internal/telephony/SMSDispatcher;->sendSubmitPdu(Lcom/android/internal/telephony/SMSDispatcher$SmsTracker;)V
 Lcom/android/internal/telephony/SmsHeader$ConcatRef;-><init>()V
 Lcom/android/internal/telephony/SmsHeader$PortAddrs;-><init>()V
 Lcom/android/internal/telephony/SmsMessageBase;-><init>()V
+Lcom/android/internal/telephony/SmsResponse;-><init>(ILjava/lang/String;I)V
+Lcom/android/internal/telephony/SmsResponse;->mAckPdu:Ljava/lang/String;
+Lcom/android/internal/telephony/SmsResponse;->mErrorCode:I
+Lcom/android/internal/telephony/SmsResponse;->mMessageRef:I
+Lcom/android/internal/telephony/SmsStorageMonitor;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/SmsUsageMonitor;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/telephony/SmsUsageMonitor;->check(Ljava/lang/String;I)Z
+Lcom/android/internal/telephony/SubscriptionController;->broadcastDefaultDataSubIdChanged(I)V
+Lcom/android/internal/telephony/SubscriptionController;->colorArr:[I
+Lcom/android/internal/telephony/SubscriptionController;->enforceModifyPhoneState(Ljava/lang/String;)V
+Lcom/android/internal/telephony/SubscriptionController;->getActiveSubInfoCount(Ljava/lang/String;)I
+Lcom/android/internal/telephony/SubscriptionController;->getActiveSubscriptionInfo(ILjava/lang/String;)Landroid/telephony/SubscriptionInfo;
+Lcom/android/internal/telephony/SubscriptionController;->getActiveSubscriptionInfoList(Ljava/lang/String;)Ljava/util/List;
+Lcom/android/internal/telephony/SubscriptionController;->getDefaultDataSubId()I
+Lcom/android/internal/telephony/SubscriptionController;->getDefaultSmsSubId()I
+Lcom/android/internal/telephony/SubscriptionController;->getDefaultSubId()I
+Lcom/android/internal/telephony/SubscriptionController;->getDefaultVoiceSubId()I
+Lcom/android/internal/telephony/SubscriptionController;->getDummySubIds(I)[I
+Lcom/android/internal/telephony/SubscriptionController;->getInstance()Lcom/android/internal/telephony/SubscriptionController;
+Lcom/android/internal/telephony/SubscriptionController;->getPhoneId(I)I
+Lcom/android/internal/telephony/SubscriptionController;->getSubId(I)[I
+Lcom/android/internal/telephony/SubscriptionController;->getSubIdUsingPhoneId(I)I
+Lcom/android/internal/telephony/SubscriptionController;->getSubInfo(Ljava/lang/String;Ljava/lang/Object;)Ljava/util/List;
+Lcom/android/internal/telephony/SubscriptionController;->getSubInfoRecord(Landroid/database/Cursor;)Landroid/telephony/SubscriptionInfo;
+Lcom/android/internal/telephony/SubscriptionController;->isActiveSubId(I)Z
+Lcom/android/internal/telephony/SubscriptionController;->isSubInfoReady()Z
+Lcom/android/internal/telephony/SubscriptionController;->logd(Ljava/lang/String;)V
+Lcom/android/internal/telephony/SubscriptionController;->logdl(Ljava/lang/String;)V
+Lcom/android/internal/telephony/SubscriptionController;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/SubscriptionController;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/SubscriptionController;->mDefaultPhoneId:I
+Lcom/android/internal/telephony/SubscriptionController;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/SubscriptionController;->notifySubscriptionInfoChanged()V
+Lcom/android/internal/telephony/SubscriptionController;->setDefaultDataSubId(I)V
+Lcom/android/internal/telephony/SubscriptionController;->setDefaultFallbackSubId(I)V
+Lcom/android/internal/telephony/SubscriptionController;->setDefaultSmsSubId(I)V
+Lcom/android/internal/telephony/SubscriptionController;->setDefaultVoiceSubId(I)V
+Lcom/android/internal/telephony/SubscriptionController;->setPlmnSpn(IZLjava/lang/String;ZLjava/lang/String;)Z
+Lcom/android/internal/telephony/SubscriptionController;->updateAllDataConnectionTrackers()V
+Lcom/android/internal/telephony/SubscriptionController;->validateSubId(I)V
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->broadcastSimStateChanged(ILjava/lang/String;Ljava/lang/String;)V
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->isAllIccIdQueryDone()Z
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->logd(Ljava/lang/String;)V
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mCurrentlyActiveUserId:I
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mIccId:[Ljava/lang/String;
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mInsertSimState:[I
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mPackageManager:Landroid/content/pm/IPackageManager;
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->mPhone:[Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->PROJECT_SIM_NUM:I
+Lcom/android/internal/telephony/SubscriptionInfoUpdater;->updateSubscriptionInfoByIccId()V
+Lcom/android/internal/telephony/TelephonyCapabilities;->supportsAdn(I)Z
+Lcom/android/internal/telephony/TelephonyProperties;->PROPERTY_ICC_OPERATOR_NUMERIC:Ljava/lang/String;
+Lcom/android/internal/telephony/test/InterpreterEx;-><init>(Ljava/lang/String;)V
+Lcom/android/internal/telephony/test/SimulatedCommands;->acceptCall(Landroid/os/Message;)V
+Lcom/android/internal/telephony/test/SimulatedCommands;->dial(Ljava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/test/SimulatedCommands;->dial(Ljava/lang/String;ILcom/android/internal/telephony/UUSInfo;Landroid/os/Message;)V
+Lcom/android/internal/telephony/test/SimulatedCommands;->mDcSuccess:Z
+Lcom/android/internal/telephony/test/SimulatedCommands;->resultFail(Landroid/os/Message;Ljava/lang/Object;Ljava/lang/Throwable;)V
+Lcom/android/internal/telephony/test/SimulatedCommands;->resultSuccess(Landroid/os/Message;Ljava/lang/Object;)V
+Lcom/android/internal/telephony/test/SimulatedCommands;->simulatedCallState:Lcom/android/internal/telephony/test/SimulatedGsmCallState;
+Lcom/android/internal/telephony/test/SimulatedCommands;->unimplemented(Landroid/os/Message;)V
+Lcom/android/internal/telephony/test/SimulatedCommandsVerifier;->getInstance()Lcom/android/internal/telephony/test/SimulatedCommandsVerifier;
+Lcom/android/internal/telephony/test/SimulatedCommandsVerifier;->setCallForward(IIILjava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/test/SimulatedGsmCallState;->conference()Z
+Lcom/android/internal/telephony/test/SimulatedGsmCallState;->onChld(CC)Z
+Lcom/android/internal/telephony/test/SimulatedGsmCallState;->releaseActiveAcceptHeldOrWaiting()Z
+Lcom/android/internal/telephony/test/SimulatedGsmCallState;->releaseHeldOrUDUB()Z
+Lcom/android/internal/telephony/test/SimulatedGsmCallState;->separateCall(I)Z
+Lcom/android/internal/telephony/test/SimulatedGsmCallState;->switchActiveAndHeldOrWaiting()Z
+Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(IILjava/lang/String;Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(II[B)V
+Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/AdnRecord;-><init>(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/AdnRecord;-><init>([B)V
+Lcom/android/internal/telephony/uicc/AdnRecord;->buildAdnString(I)[B
+Lcom/android/internal/telephony/uicc/AdnRecord;->CREATOR:Landroid/os/Parcelable$Creator;
+Lcom/android/internal/telephony/uicc/AdnRecord;->getEmails()[Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/AdnRecord;->getNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/AdnRecord;->isEmpty()Z
+Lcom/android/internal/telephony/uicc/AdnRecord;->mAlphaTag:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/AdnRecord;->mEfid:I
+Lcom/android/internal/telephony/uicc/AdnRecord;->mEmails:[Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/AdnRecord;->mExtRecord:I
+Lcom/android/internal/telephony/uicc/AdnRecord;->mNumber:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/AdnRecord;->mRecordNumber:I
+Lcom/android/internal/telephony/uicc/AdnRecord;->setEmails([Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->extensionEfForEf(I)I
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->getRecordsIfLoaded(I)Ljava/util/ArrayList;
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->mAdnLikeWaiters:Landroid/util/SparseArray;
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->mUserWriteResponse:Landroid/util/SparseArray;
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->mUsimPhoneBookManager:Lcom/android/internal/telephony/gsm/UsimPhoneBookManager;
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->reset()V
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->sendErrorResponse(Landroid/os/Message;Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/AdnRecordCache;->updateAdnByIndex(ILcom/android/internal/telephony/uicc/AdnRecord;ILjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/AdnRecordLoader;-><init>(Lcom/android/internal/telephony/uicc/IccFileHandler;)V
+Lcom/android/internal/telephony/uicc/AdnRecordLoader;->getEFPath(I)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/AdnRecordLoader;->loadFromEF(IIILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/AdnRecordLoader;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/uicc/AdnRecordLoader;->updateEF(Lcom/android/internal/telephony/uicc/AdnRecord;IIILjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_DETECTED:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_PIN:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_PUK:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_READY:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_SUBSCRIPTION_PERSO:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->APPSTATE_UNKNOWN:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;->values()[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_CSIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_ISIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_RUIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_SIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_UNKNOWN:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->APPTYPE_USIM:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;->values()[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_NETWORK:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_NETWORK_SUBSET:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_SERVICE_PROVIDER:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->PERSOSUBSTATE_UNKNOWN:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;->values()[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;-><init>()V
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;->AppTypeFromRILInt(I)Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;->app_type:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;->CARDSTATE_ABSENT:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
+Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;->CARDSTATE_ERROR:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
+Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;->CARDSTATE_PRESENT:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
+Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;->isCardPresent()Z
+Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;->PINSTATE_DISABLED:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
+Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;->PINSTATE_ENABLED_BLOCKED:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
+Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;->PINSTATE_ENABLED_PERM_BLOCKED:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
+Lcom/android/internal/telephony/uicc/IccCardStatus;->mApplications:[Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;
+Lcom/android/internal/telephony/uicc/IccCardStatus;->mCardState:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
+Lcom/android/internal/telephony/uicc/IccCardStatus;->mCdmaSubscriptionAppIndex:I
+Lcom/android/internal/telephony/uicc/IccCardStatus;->mGsmUmtsSubscriptionAppIndex:I
+Lcom/android/internal/telephony/uicc/IccCardStatus;->mImsSubscriptionAppIndex:I
+Lcom/android/internal/telephony/uicc/IccCardStatus;->mUniversalPinState:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
+Lcom/android/internal/telephony/uicc/IccFileHandler$LoadLinearFixedContext;-><init>(IILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler$LoadLinearFixedContext;->mRecordSize:I
+Lcom/android/internal/telephony/uicc/IccFileHandler$LoadLinearFixedContext;->results:Ljava/util/ArrayList;
+Lcom/android/internal/telephony/uicc/IccFileHandler;->getEFLinearRecordSize(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->getEFLinearRecordSize(ILjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->getEFPath(I)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixed(IILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixed(ILjava/lang/String;ILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixedAll(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFLinearFixedAll(ILjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->loadEFTransparent(ILandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->mAid:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccFileHandler;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/uicc/IccFileHandler;->mParentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/IccFileHandler;->updateEFLinearFixed(II[BLjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->updateEFLinearFixed(ILjava/lang/String;I[BLjava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccFileHandler;->updateEFTransparent(I[BLandroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccIoResult;-><init>(IILjava/lang/String;)V
+Lcom/android/internal/telephony/uicc/IccIoResult;-><init>(II[B)V
+Lcom/android/internal/telephony/uicc/IccIoResult;->payload:[B
+Lcom/android/internal/telephony/uicc/IccIoResult;->success()Z
+Lcom/android/internal/telephony/uicc/IccIoResult;->sw1:I
+Lcom/android/internal/telephony/uicc/IccIoResult;->sw2:I
+Lcom/android/internal/telephony/uicc/IccRecords;->auth_rsp:Lcom/android/internal/telephony/uicc/IccIoResult;
+Lcom/android/internal/telephony/uicc/IccRecords;->getGid1()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getIccId()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getIccSimChallengeResponse(ILjava/lang/String;)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getIMSI()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getMsisdnNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getOperatorNumeric()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getRecordsLoaded()Z
+Lcom/android/internal/telephony/uicc/IccRecords;->getServiceProviderName()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->getUsimServiceTable()Lcom/android/internal/telephony/uicc/UsimServiceTable;
+Lcom/android/internal/telephony/uicc/IccRecords;->handleRefresh(Lcom/android/internal/telephony/uicc/IccRefreshResponse;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->mAdnCache:Lcom/android/internal/telephony/uicc/AdnRecordCache;
+Lcom/android/internal/telephony/uicc/IccRecords;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/uicc/IccRecords;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/uicc/IccRecords;->mDestroyed:Ljava/util/concurrent/atomic/AtomicBoolean;
+Lcom/android/internal/telephony/uicc/IccRecords;->mFh:Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/uicc/IccRecords;->mGid1:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->mIccId:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->mImsi:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->mIsVoiceMailFixed:Z
+Lcom/android/internal/telephony/uicc/IccRecords;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/uicc/IccRecords;->mMncLength:I
+Lcom/android/internal/telephony/uicc/IccRecords;->mParentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/IccRecords;->mRecordsEventsRegistrants:Landroid/os/RegistrantList;
+Lcom/android/internal/telephony/uicc/IccRecords;->mRecordsToLoad:I
+Lcom/android/internal/telephony/uicc/IccRecords;->mSpn:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->mTelephonyManager:Landroid/telephony/TelephonyManager;
+Lcom/android/internal/telephony/uicc/IccRecords;->mVoiceMailNum:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRecords;->registerForNetworkSelectionModeAutomatic(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->registerForNewSms(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->registerForRecordsEvents(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->registerForRecordsLoaded(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->setMsisdnNumber(Ljava/lang/String;Ljava/lang/String;Landroid/os/Message;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->setVoiceCallForwardingFlag(IZLjava/lang/String;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->unregisterForNetworkSelectionModeAutomatic(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->unregisterForNewSms(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->unregisterForRecordsEvents(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/uicc/IccRecords;->unregisterForRecordsLoaded(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/uicc/IccRefreshResponse;-><init>()V
+Lcom/android/internal/telephony/uicc/IccRefreshResponse;->aid:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccRefreshResponse;->efId:I
+Lcom/android/internal/telephony/uicc/IccRefreshResponse;->refreshResult:I
+Lcom/android/internal/telephony/uicc/IccServiceTable;->getTag()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccServiceTable;->mServiceTable:[B
+Lcom/android/internal/telephony/uicc/IccUtils;->adnStringFieldToString([BII)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccUtils;->bcdToString([BII)Ljava/lang/String;
 Lcom/android/internal/telephony/uicc/IccUtils;->bytesToHexString([B)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccUtils;->cdmaBcdByteToInt(B)I
+Lcom/android/internal/telephony/uicc/IccUtils;->cdmaBcdToString([BII)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccUtils;->gsmBcdByteToInt(B)I
+Lcom/android/internal/telephony/uicc/IccUtils;->hexCharToInt(C)I
+Lcom/android/internal/telephony/uicc/IccUtils;->hexStringToBytes(Ljava/lang/String;)[B
+Lcom/android/internal/telephony/uicc/IccUtils;->networkNameToString([BII)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IccUtils;->parseToBnW([BI)Landroid/graphics/Bitmap;
+Lcom/android/internal/telephony/uicc/IccUtils;->parseToRGB([BIZ)Landroid/graphics/Bitmap;
+Lcom/android/internal/telephony/uicc/IsimRecords;->getIsimDomain()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimRecords;->getIsimImpi()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimRecords;->getIsimImpu()[Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->auth_rsp:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->fetchIsimRecords()V
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->isimTlvToString([B)Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimDomain:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpi:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimImpu:[Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimIst:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mIsimPcscf:[Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/IsimUiccRecords;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/uicc/RuimRecords;->adjstMinDigits(I)I
+Lcom/android/internal/telephony/uicc/RuimRecords;->fetchRuimRecords()V
+Lcom/android/internal/telephony/uicc/RuimRecords;->getAssetLanguages(Landroid/content/Context;)[Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/RuimRecords;->getCsimSpnDisplayCondition()Z
+Lcom/android/internal/telephony/uicc/RuimRecords;->getMdn()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/RuimRecords;->getMdnNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/RuimRecords;->getRUIMOperatorNumeric()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/RuimRecords;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/RuimRecords;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/RuimRecords;->mEFli:[B
+Lcom/android/internal/telephony/uicc/RuimRecords;->mEFpl:[B
+Lcom/android/internal/telephony/uicc/RuimRecords;->mMin:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/RuimRecords;->mNai:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/RuimRecords;->onGetCSimEprlDone(Landroid/os/AsyncResult;)V
+Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->INIT:Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
+Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->READ_SPN_3GPP:Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
+Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->READ_SPN_CPHS:Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
+Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->READ_SPN_SHORT_CPHS:Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
+Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;->values()[Lcom/android/internal/telephony/uicc/SIMRecords$GetSpnFsmState;
+Lcom/android/internal/telephony/uicc/SIMRecords;->fetchSimRecords()V
+Lcom/android/internal/telephony/uicc/SIMRecords;->getExtFromEf(I)I
+Lcom/android/internal/telephony/uicc/SIMRecords;->getMsisdnNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/SIMRecords;->getOperatorNumeric()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/SIMRecords;->getSpnFsm(ZLandroid/os/AsyncResult;)V
+Lcom/android/internal/telephony/uicc/SIMRecords;->getVoiceMailNumber()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/SIMRecords;->isCphsMailboxEnabled()Z
+Lcom/android/internal/telephony/uicc/SIMRecords;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/SIMRecords;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/SIMRecords;->logv(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/SIMRecords;->mEfCff:[B
+Lcom/android/internal/telephony/uicc/SIMRecords;->mEfCfis:[B
+Lcom/android/internal/telephony/uicc/SIMRecords;->mEfCPHS_MWI:[B
+Lcom/android/internal/telephony/uicc/SIMRecords;->mEfLi:[B
+Lcom/android/internal/telephony/uicc/SIMRecords;->mEfMWIS:[B
+Lcom/android/internal/telephony/uicc/SIMRecords;->mEfPl:[B
+Lcom/android/internal/telephony/uicc/SIMRecords;->mSpnDisplayCondition:I
+Lcom/android/internal/telephony/uicc/SIMRecords;->mUsimServiceTable:Lcom/android/internal/telephony/uicc/UsimServiceTable;
+Lcom/android/internal/telephony/uicc/SIMRecords;->mVmConfig:Lcom/android/internal/telephony/uicc/VoiceMailConstants;
+Lcom/android/internal/telephony/uicc/SIMRecords;->setVoiceCallForwardingFlag(IZLjava/lang/String;)V
+Lcom/android/internal/telephony/uicc/UiccCard;->getApplication(I)Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/UiccCard;->getApplicationByType(I)Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/UiccCard;->getApplicationIndex(I)Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/UiccCard;->getCardState()Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
+Lcom/android/internal/telephony/uicc/UiccCard;->getCarrierPackageNamesForIntent(Landroid/content/pm/PackageManager;Landroid/content/Intent;)Ljava/util/List;
+Lcom/android/internal/telephony/uicc/UiccCard;->getIccId()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/UiccCard;->getNumApplications()I
+Lcom/android/internal/telephony/uicc/UiccCard;->getOperatorBrandOverride()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/UiccCard;->isApplicationOnIcc(Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;)Z
+Lcom/android/internal/telephony/uicc/UiccCard;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/UiccCard;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/UiccCard;->mCardState:Lcom/android/internal/telephony/uicc/IccCardStatus$CardState;
+Lcom/android/internal/telephony/uicc/UiccCard;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/uicc/UiccCard;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/uicc/UiccCard;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/uicc/UiccCard;->mPhoneId:I
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->dispose()V
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getAid()Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getAuthContext()I
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getIccFileHandler()Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getIccRecords()Lcom/android/internal/telephony/uicc/IccRecords;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getPersoSubState()Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getPhoneId()I
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getPin1State()Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getState()Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->getType()Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->loge(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mAid:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mAppState:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppState;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mAppType:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$AppType;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mCi:Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mDestroyed:Z
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mPersoSubState:Lcom/android/internal/telephony/uicc/IccCardApplicationStatus$PersoSubState;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->mPin1State:Lcom/android/internal/telephony/uicc/IccCardStatus$PinState;
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->registerForReady(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->unregisterForReady(Landroid/os/Handler;)V
+Lcom/android/internal/telephony/uicc/UiccCardApplication;->update(Lcom/android/internal/telephony/uicc/IccCardApplicationStatus;Landroid/content/Context;Lcom/android/internal/telephony/CommandsInterface;)V
+Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules$TLV;->length:Ljava/lang/Integer;
+Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules$TLV;->value:Ljava/lang/String;
+Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules;->mLoadedCallback:Landroid/os/Message;
+Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules;->mState:Ljava/util/concurrent/atomic/AtomicInteger;
+Lcom/android/internal/telephony/uicc/UiccController;->getIccFileHandler(II)Lcom/android/internal/telephony/uicc/IccFileHandler;
+Lcom/android/internal/telephony/uicc/UiccController;->getIccRecords(II)Lcom/android/internal/telephony/uicc/IccRecords;
+Lcom/android/internal/telephony/uicc/UiccController;->getInstance()Lcom/android/internal/telephony/uicc/UiccController;
+Lcom/android/internal/telephony/uicc/UiccController;->getUiccCard(I)Lcom/android/internal/telephony/uicc/UiccCard;
+Lcom/android/internal/telephony/uicc/UiccController;->getUiccCardApplication(II)Lcom/android/internal/telephony/uicc/UiccCardApplication;
+Lcom/android/internal/telephony/uicc/UiccController;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/uicc/UiccController;->mCis:[Lcom/android/internal/telephony/CommandsInterface;
+Lcom/android/internal/telephony/uicc/UiccController;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/uicc/UiccController;->mInstance:Lcom/android/internal/telephony/uicc/UiccController;
+Lcom/android/internal/telephony/uicc/UiccController;->mLock:Ljava/lang/Object;
+Lcom/android/internal/telephony/uicc/UiccController;->registerForIccChanged(Landroid/os/Handler;ILjava/lang/Object;)V
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->ALLOWED_CSG_LISTS_AND_INDICATIONS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->CFI_STATUS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->CSG_DISPLAY_CONTROL:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->FDN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->MBDN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->MSISDN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->MWI_STATUS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->OPERATOR_CSG_LISTS_AND_INDICATIONS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->OPERATOR_PLMN_LIST:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->PLMN_NETWORK_NAME:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SDN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SM_OVER_IP:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SM_SERVICE_PARAMS:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SM_STORAGE:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;->SPN:Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;
+Lcom/android/internal/telephony/uicc/UsimServiceTable;->isAvailable(Lcom/android/internal/telephony/uicc/UsimServiceTable$UsimService;)Z
+Lcom/android/internal/telephony/uicc/VoiceMailConstants;-><init>()V
+Lcom/android/internal/telephony/UiccPhoneBookController;-><init>([Lcom/android/internal/telephony/Phone;)V
+Lcom/android/internal/telephony/UiccPhoneBookController;->getDefaultSubscription()I
+Lcom/android/internal/telephony/UiccPhoneBookController;->getIccPhoneBookInterfaceManager(I)Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;
+Lcom/android/internal/telephony/UiccPhoneBookController;->mPhone:[Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/UiccSmsController;->copyMessageToIccEfForSubscriber(ILjava/lang/String;I[B[B)Z
+Lcom/android/internal/telephony/UiccSmsController;->disableCellBroadcastForSubscriber(III)Z
+Lcom/android/internal/telephony/UiccSmsController;->disableCellBroadcastRangeForSubscriber(IIII)Z
+Lcom/android/internal/telephony/UiccSmsController;->enableCellBroadcastForSubscriber(III)Z
+Lcom/android/internal/telephony/UiccSmsController;->enableCellBroadcastRangeForSubscriber(IIII)Z
+Lcom/android/internal/telephony/UiccSmsController;->getAllMessagesFromIccEfForSubscriber(ILjava/lang/String;)Ljava/util/List;
+Lcom/android/internal/telephony/UiccSmsController;->getIccSmsInterfaceManager(I)Lcom/android/internal/telephony/IccSmsInterfaceManager;
+Lcom/android/internal/telephony/UiccSmsController;->getImsSmsFormatForSubscriber(I)Ljava/lang/String;
+Lcom/android/internal/telephony/UiccSmsController;->getPreferredSmsSubscription()I
+Lcom/android/internal/telephony/UiccSmsController;->isImsSmsSupportedForSubscriber(I)Z
+Lcom/android/internal/telephony/UiccSmsController;->sendDataForSubscriber(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;I[BLandroid/app/PendingIntent;Landroid/app/PendingIntent;)V
+Lcom/android/internal/telephony/UiccSmsController;->sendErrorInPendingIntent(Landroid/app/PendingIntent;I)V
+Lcom/android/internal/telephony/UiccSmsController;->sendErrorInPendingIntents(Ljava/util/List;I)V
+Lcom/android/internal/telephony/UiccSmsController;->updateMessageOnIccEfForSubscriber(ILjava/lang/String;II[B)Z
+Lcom/android/internal/telephony/UUSInfo;->getDcs()I
+Lcom/android/internal/telephony/UUSInfo;->getType()I
+Lcom/android/internal/telephony/UUSInfo;->getUserData()[B
+Lcom/android/internal/telephony/WakeLockStateMachine;->log(Ljava/lang/String;)V
+Lcom/android/internal/telephony/WakeLockStateMachine;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/WakeLockStateMachine;->mIdleState:Lcom/android/internal/telephony/WakeLockStateMachine$IdleState;
+Lcom/android/internal/telephony/WakeLockStateMachine;->mPhone:Lcom/android/internal/telephony/Phone;
+Lcom/android/internal/telephony/WapPushOverSms;->dispatchWapPdu([BLandroid/content/BroadcastReceiver;Lcom/android/internal/telephony/InboundSmsHandler;)I
+Lcom/android/internal/telephony/WapPushOverSms;->getDeliveryOrReadReportThreadId(Landroid/content/Context;Lcom/google/android/mms/pdu/GenericPdu;)J
+Lcom/android/internal/telephony/WapPushOverSms;->isDuplicateNotification(Landroid/content/Context;Lcom/google/android/mms/pdu/NotificationInd;)Z
+Lcom/android/internal/telephony/WapPushOverSms;->isWapPushForMms([BLcom/android/internal/telephony/InboundSmsHandler;)Z
+Lcom/android/internal/telephony/WapPushOverSms;->mContext:Landroid/content/Context;
+Lcom/android/internal/telephony/WapPushOverSms;->mDeviceIdleController:Landroid/os/IDeviceIdleController;
+Lcom/android/internal/telephony/WapPushOverSms;->mWapPushManager:Lcom/android/internal/telephony/IWapPushManager;
+Lcom/android/internal/telephony/WspTypeDecoder;-><init>([B)V
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeContentType(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeIntegerValue(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeShortInteger(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeTextString(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeUintvarInteger(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeValueLength(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->decodeXWapApplicationId(I)Z
+Lcom/android/internal/telephony/WspTypeDecoder;->getContentParameters()Ljava/util/HashMap;
+Lcom/android/internal/telephony/WspTypeDecoder;->getDecodedDataLength()I
+Lcom/android/internal/telephony/WspTypeDecoder;->getValue32()J
+Lcom/android/internal/telephony/WspTypeDecoder;->getValueString()Ljava/lang/String;
+Lcom/android/internal/telephony/WspTypeDecoder;->mWspData:[B
+Lcom/android/internal/telephony/WspTypeDecoder;->seekXWapApplicationId(II)Z
 Lcom/android/internal/textservice/ITextServicesManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
+Lcom/android/internal/util/ArrayUtils;->appendElement(Ljava/lang/Class;[Ljava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object;
+Lcom/android/internal/util/ArrayUtils;->appendInt([II)[I
+Lcom/android/internal/util/ArrayUtils;->contains([II)Z
+Lcom/android/internal/util/ArrayUtils;->contains([Ljava/lang/Object;Ljava/lang/Object;)Z
+Lcom/android/internal/util/ArrayUtils;->emptyArray(Ljava/lang/Class;)[Ljava/lang/Object;
+Lcom/android/internal/util/ArrayUtils;->indexOf([Ljava/lang/Object;Ljava/lang/Object;)I
+Lcom/android/internal/util/ArrayUtils;->isEmpty([Ljava/lang/Object;)Z
+Lcom/android/internal/util/ArrayUtils;->newUnpaddedArray(Ljava/lang/Class;I)[Ljava/lang/Object;
+Lcom/android/internal/util/ArrayUtils;->newUnpaddedIntArray(I)[I
+Lcom/android/internal/util/ArrayUtils;->removeElement(Ljava/lang/Class;[Ljava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object;
+Lcom/android/internal/util/BitwiseInputStream;-><init>([B)V
+Lcom/android/internal/util/BitwiseInputStream;->available()I
+Lcom/android/internal/util/BitwiseInputStream;->read(I)I
+Lcom/android/internal/util/BitwiseInputStream;->readByteArray(I)[B
+Lcom/android/internal/util/BitwiseInputStream;->skip(I)V
+Lcom/android/internal/util/BitwiseOutputStream;-><init>(I)V
+Lcom/android/internal/util/BitwiseOutputStream;->toByteArray()[B
+Lcom/android/internal/util/BitwiseOutputStream;->write(II)V
+Lcom/android/internal/util/BitwiseOutputStream;->writeByteArray(I[B)V
+Lcom/android/internal/util/CharSequences;->compareToIgnoreCase(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)I
+Lcom/android/internal/util/CharSequences;->equals(Ljava/lang/CharSequence;Ljava/lang/CharSequence;)Z
+Lcom/android/internal/util/FastMath;->round(F)I
+Lcom/android/internal/util/FastXmlSerializer;-><init>()V
+Lcom/android/internal/util/GrowingArrayUtils;->append([III)[I
+Lcom/android/internal/util/GrowingArrayUtils;->append([Ljava/lang/Object;ILjava/lang/Object;)[Ljava/lang/Object;
+Lcom/android/internal/util/HexDump;->hexStringToByteArray(Ljava/lang/String;)[B
+Lcom/android/internal/util/HexDump;->toHexString(I)Ljava/lang/String;
+Lcom/android/internal/util/HexDump;->toHexString([B)Ljava/lang/String;
+Lcom/android/internal/util/HexDump;->toHexString([BII)Ljava/lang/String;
 Lcom/android/internal/util/HexDump;->toHexString([BZ)Ljava/lang/String;
+Lcom/android/internal/util/IState;->getName()Ljava/lang/String;
+Lcom/android/internal/util/MemInfoReader;-><init>()V
+Lcom/android/internal/util/MemInfoReader;->getCachedSize()J
+Lcom/android/internal/util/MemInfoReader;->getFreeSize()J
+Lcom/android/internal/util/MemInfoReader;->getRawInfo()[J
+Lcom/android/internal/util/MemInfoReader;->getTotalSize()J
+Lcom/android/internal/util/MemInfoReader;->readMemInfo()V
+Lcom/android/internal/util/Preconditions;->checkArgument(Z)V
+Lcom/android/internal/util/Preconditions;->checkArgument(ZLjava/lang/Object;)V
+Lcom/android/internal/util/Preconditions;->checkArgumentInRange(IIILjava/lang/String;)I
+Lcom/android/internal/util/Preconditions;->checkNotNull(Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/android/internal/util/Preconditions;->checkNotNull(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/android/internal/util/Preconditions;->checkState(Z)V
+Lcom/android/internal/util/Preconditions;->checkState(ZLjava/lang/String;)V
+Lcom/android/internal/util/State;-><init>()V
+Lcom/android/internal/util/State;->enter()V
+Lcom/android/internal/util/State;->exit()V
+Lcom/android/internal/util/State;->getName()Ljava/lang/String;
+Lcom/android/internal/util/State;->processMessage(Landroid/os/Message;)Z
+Lcom/android/internal/util/StateMachine;-><init>(Ljava/lang/String;)V
+Lcom/android/internal/util/StateMachine;-><init>(Ljava/lang/String;Landroid/os/Handler;)V
+Lcom/android/internal/util/StateMachine;-><init>(Ljava/lang/String;Landroid/os/Looper;)V
+Lcom/android/internal/util/StateMachine;->dump(Ljava/io/FileDescriptor;Ljava/io/PrintWriter;[Ljava/lang/String;)V
+Lcom/android/internal/util/StateMachine;->obtainMessage(III)Landroid/os/Message;
+Lcom/android/internal/util/StateMachine;->obtainMessage(IIILjava/lang/Object;)Landroid/os/Message;
+Lcom/android/internal/util/StateMachine;->sendMessage(I)V
+Lcom/android/internal/util/StateMachine;->sendMessage(II)V
+Lcom/android/internal/util/StateMachine;->sendMessage(IIILjava/lang/Object;)V
+Lcom/android/internal/util/StateMachine;->sendMessage(ILjava/lang/Object;)V
+Lcom/android/internal/util/StateMachine;->sendMessage(Landroid/os/Message;)V
+Lcom/android/internal/view/ActionBarPolicy;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/view/ActionBarPolicy;->get(Landroid/content/Context;)Lcom/android/internal/view/ActionBarPolicy;
+Lcom/android/internal/view/ActionBarPolicy;->getEmbeddedMenuWidthLimit()I
+Lcom/android/internal/view/ActionBarPolicy;->getMaxActionButtons()I
+Lcom/android/internal/view/ActionBarPolicy;->getStackedTabMaxWidth()I
+Lcom/android/internal/view/ActionBarPolicy;->getTabContainerHeight()I
+Lcom/android/internal/view/ActionBarPolicy;->hasEmbeddedTabs()Z
+Lcom/android/internal/view/ActionBarPolicy;->mContext:Landroid/content/Context;
+Lcom/android/internal/view/ActionBarPolicy;->showsOverflowMenuButton()Z
 Lcom/android/internal/view/BaseIWindow;-><init>()V
 Lcom/android/internal/view/IInputMethodManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/view/IInputMethodManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodManager;
 Lcom/android/internal/view/IInputMethodSession$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/view/IInputMethodSession;
+Lcom/android/internal/view/InputConnectionWrapper$InputContextCallback;->dispose()V
+Lcom/android/internal/view/InputConnectionWrapper$InputContextCallback;->getInstance()Lcom/android/internal/view/InputConnectionWrapper$InputContextCallback;
+Lcom/android/internal/view/menu/ActionMenu;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/view/menu/ActionMenuItem;-><init>(Landroid/content/Context;IIIILjava/lang/CharSequence;)V
+Lcom/android/internal/view/menu/ContextMenuBuilder;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/view/menu/IconMenuItemView;->getTextAppropriateLayoutParams()Lcom/android/internal/view/menu/IconMenuView$LayoutParams;
+Lcom/android/internal/view/menu/IconMenuItemView;->setIconMenuView(Lcom/android/internal/view/menu/IconMenuView;)V
+Lcom/android/internal/view/menu/IconMenuItemView;->setItemInvoker(Lcom/android/internal/view/menu/MenuBuilder$ItemInvoker;)V
+Lcom/android/internal/view/menu/IconMenuView$SavedState;-><init>(Landroid/os/Parcel;)V
+Lcom/android/internal/view/menu/IconMenuView;->createMoreItemView()Lcom/android/internal/view/menu/IconMenuItemView;
+Lcom/android/internal/view/menu/IconMenuView;->getNumActualItemsShown()I
+Lcom/android/internal/view/menu/IconMenuView;->mItemBackground:Landroid/graphics/drawable/Drawable;
+Lcom/android/internal/view/menu/IconMenuView;->mMaxItems:I
+Lcom/android/internal/view/menu/IconMenuView;->mMenu:Lcom/android/internal/view/menu/MenuBuilder;
+Lcom/android/internal/view/menu/MenuDialogHelper;-><init>(Lcom/android/internal/view/menu/MenuBuilder;)V
+Lcom/android/internal/view/menu/MenuDialogHelper;->dismiss()V
+Lcom/android/internal/view/menu/MenuDialogHelper;->show(Landroid/os/IBinder;)V
+Lcom/android/internal/view/WindowManagerPolicyThread;->getLooper()Landroid/os/Looper;
+Lcom/android/internal/widget/AbsActionBarView;->dismissPopupMenus()V
+Lcom/android/internal/widget/ActionBarContextView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+Lcom/android/internal/widget/ActionBarOverlayLayout;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+Lcom/android/internal/widget/ActionBarOverlayLayout;->setWindowCallback(Landroid/view/Window$Callback;)V
+Lcom/android/internal/widget/EditableInputConnection;-><init>(Landroid/widget/TextView;)V
 Lcom/android/internal/widget/ILockSettings$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/widget/ILockSettings;
 Lcom/android/internal/widget/ILockSettings;->getBoolean(Ljava/lang/String;ZI)Z
 Lcom/android/internal/widget/ILockSettings;->getLong(Ljava/lang/String;JI)J
@@ -2088,17 +4053,109 @@
 Lcom/android/internal/widget/IRemoteViewsFactory;->hasStableIds()Z
 Lcom/android/internal/widget/IRemoteViewsFactory;->isCreated()Z
 Lcom/android/internal/widget/IRemoteViewsFactory;->onDataSetChanged()V
+Lcom/android/internal/widget/LinearLayoutWithDefaultTouchRecepient;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/widget/LinearLayoutWithDefaultTouchRecepient;->setDefaultTouchRecepient(Landroid/view/View;)V
+Lcom/android/internal/widget/LockPatternChecker;->checkPassword(Lcom/android/internal/widget/LockPatternUtils;Ljava/lang/String;ILcom/android/internal/widget/LockPatternChecker$OnCheckCallback;)Landroid/os/AsyncTask;
+Lcom/android/internal/widget/LockPatternUtils$RequestThrottledException;-><init>(I)V
+Lcom/android/internal/widget/LockPatternUtils$RequestThrottledException;->getTimeoutMs()I
+Lcom/android/internal/widget/LockPatternUtils;-><init>(Landroid/content/Context;)V
+Lcom/android/internal/widget/LockPatternUtils;->checkPassword(Ljava/lang/String;I)Z
+Lcom/android/internal/widget/LockPatternUtils;->getActivePasswordQuality(I)I
+Lcom/android/internal/widget/LockPatternUtils;->getDevicePolicyManager()Landroid/app/admin/DevicePolicyManager;
+Lcom/android/internal/widget/LockPatternUtils;->getKeyguardStoredPasswordQuality(I)I
+Lcom/android/internal/widget/LockPatternUtils;->getLockSettings()Lcom/android/internal/widget/ILockSettings;
+Lcom/android/internal/widget/LockPatternUtils;->getOwnerInfo(I)Ljava/lang/String;
+Lcom/android/internal/widget/LockPatternUtils;->getPowerButtonInstantlyLocks(I)Z
+Lcom/android/internal/widget/LockPatternUtils;->getString(Ljava/lang/String;I)Ljava/lang/String;
+Lcom/android/internal/widget/LockPatternUtils;->isDeviceEncryptionEnabled()Z
+Lcom/android/internal/widget/LockPatternUtils;->isLockPasswordEnabled(I)Z
+Lcom/android/internal/widget/LockPatternUtils;->isLockPatternEnabled(I)Z
+Lcom/android/internal/widget/LockPatternUtils;->isLockScreenDisabled(I)Z
+Lcom/android/internal/widget/LockPatternUtils;->isSecure(I)Z
+Lcom/android/internal/widget/LockPatternUtils;->isTactileFeedbackEnabled()Z
+Lcom/android/internal/widget/LockPatternUtils;->isVisiblePatternEnabled(I)Z
+Lcom/android/internal/widget/LockPatternUtils;->mContentResolver:Landroid/content/ContentResolver;
+Lcom/android/internal/widget/LockPatternUtils;->mContext:Landroid/content/Context;
+Lcom/android/internal/widget/LockPatternUtils;->patternToHash(Ljava/util/List;)[B
+Lcom/android/internal/widget/LockPatternUtils;->patternToString(Ljava/util/List;)Ljava/lang/String;
+Lcom/android/internal/widget/LockPatternUtils;->reportFailedPasswordAttempt(I)V
+Lcom/android/internal/widget/LockPatternUtils;->reportSuccessfulPasswordAttempt(I)V
+Lcom/android/internal/widget/LockPatternUtils;->saveLockPassword(Ljava/lang/String;Ljava/lang/String;II)V
+Lcom/android/internal/widget/LockPatternUtils;->setLockoutAttemptDeadline(II)J
+Lcom/android/internal/widget/LockPatternUtils;->setLong(Ljava/lang/String;JI)V
+Lcom/android/internal/widget/LockPatternUtils;->setOwnerInfo(Ljava/lang/String;I)V
+Lcom/android/internal/widget/LockPatternUtils;->setOwnerInfoEnabled(ZI)V
+Lcom/android/internal/widget/LockPatternUtils;->setString(Ljava/lang/String;Ljava/lang/String;I)V
+Lcom/android/internal/widget/LockPatternView$Cell;->column:I
+Lcom/android/internal/widget/LockPatternView$Cell;->row:I
+Lcom/android/internal/widget/LockPatternView$DisplayMode;->Animate:Lcom/android/internal/widget/LockPatternView$DisplayMode;
+Lcom/android/internal/widget/LockPatternView$DisplayMode;->Correct:Lcom/android/internal/widget/LockPatternView$DisplayMode;
+Lcom/android/internal/widget/LockPatternView$DisplayMode;->Wrong:Lcom/android/internal/widget/LockPatternView$DisplayMode;
+Lcom/android/internal/widget/LockPatternView$SavedState;-><init>(Landroid/os/Parcel;)V
+Lcom/android/internal/widget/LockPatternView$SavedState;-><init>(Landroid/os/Parcelable;Ljava/lang/String;IZZZ)V
+Lcom/android/internal/widget/LockPatternView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+Lcom/android/internal/widget/LockPatternView;->clearPattern()V
+Lcom/android/internal/widget/LockPatternView;->disableInput()V
+Lcom/android/internal/widget/LockPatternView;->enableInput()V
+Lcom/android/internal/widget/LockPatternView;->getCellStates()[[Lcom/android/internal/widget/LockPatternView$CellState;
+Lcom/android/internal/widget/LockPatternView;->mInStealthMode:Z
+Lcom/android/internal/widget/LockPatternView;->mPaint:Landroid/graphics/Paint;
+Lcom/android/internal/widget/LockPatternView;->mPathPaint:Landroid/graphics/Paint;
+Lcom/android/internal/widget/LockPatternView;->mPattern:Ljava/util/ArrayList;
+Lcom/android/internal/widget/LockPatternView;->mPatternDisplayMode:Lcom/android/internal/widget/LockPatternView$DisplayMode;
+Lcom/android/internal/widget/LockPatternView;->mPatternInProgress:Z
+Lcom/android/internal/widget/LockPatternView;->mSquareHeight:F
+Lcom/android/internal/widget/LockPatternView;->mSquareWidth:F
+Lcom/android/internal/widget/LockPatternView;->notifyPatternDetected()V
+Lcom/android/internal/widget/LockPatternView;->setDisplayMode(Lcom/android/internal/widget/LockPatternView$DisplayMode;)V
+Lcom/android/internal/widget/LockPatternView;->setInStealthMode(Z)V
+Lcom/android/internal/widget/LockPatternView;->setOnPatternListener(Lcom/android/internal/widget/LockPatternView$OnPatternListener;)V
+Lcom/android/internal/widget/LockPatternView;->setTactileFeedbackEnabled(Z)V
+Lcom/android/internal/widget/PointerLocationView$PointerState;-><init>()V
+Lcom/android/internal/widget/PointerLocationView$PointerState;->mCurDown:Z
+Lcom/android/internal/widget/PointerLocationView;->mCurDown:Z
+Lcom/android/internal/widget/PointerLocationView;->mCurNumPointers:I
+Lcom/android/internal/widget/PointerLocationView;->mMaxNumPointers:I
+Lcom/android/internal/widget/PointerLocationView;->mPointers:Ljava/util/ArrayList;
+Lcom/android/internal/widget/PointerLocationView;->mPrintCoords:Z
+Lcom/android/internal/widget/PreferenceImageView;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+Lcom/android/internal/widget/RecyclerView$RecycledViewPool$ScrapData;->mScrapHeap:Ljava/util/ArrayList;
 Lcom/android/internal/widget/ScrollBarUtils;->getThumbLength(IIII)I
+Lcom/android/internal/widget/SlidingTab$Slider;->tab:Landroid/widget/ImageView;
+Lcom/android/internal/widget/SlidingTab$Slider;->text:Landroid/widget/TextView;
+Lcom/android/internal/widget/SlidingTab;->mAnimationDoneListener:Landroid/view/animation/Animation$AnimationListener;
+Lcom/android/internal/widget/SlidingTab;->mLeftSlider:Lcom/android/internal/widget/SlidingTab$Slider;
+Lcom/android/internal/widget/SlidingTab;->mRightSlider:Lcom/android/internal/widget/SlidingTab$Slider;
+Lcom/android/internal/widget/SlidingTab;->onAnimationDone()V
+Lcom/android/internal/widget/SlidingTab;->resetView()V
+Lcom/android/internal/widget/SlidingTab;->setHoldAfterTrigger(ZZ)V
+Lcom/android/internal/widget/SlidingTab;->setLeftHintText(I)V
+Lcom/android/internal/widget/SlidingTab;->setLeftTabResources(IIII)V
+Lcom/android/internal/widget/SlidingTab;->setOnTriggerListener(Lcom/android/internal/widget/SlidingTab$OnTriggerListener;)V
+Lcom/android/internal/widget/SlidingTab;->setRightHintText(I)V
+Lcom/android/internal/widget/SlidingTab;->setRightTabResources(IIII)V
+Lcom/android/internal/widget/TextViewInputDisabler;-><init>(Landroid/widget/TextView;)V
+Lcom/android/internal/widget/TextViewInputDisabler;->setInputEnabled(Z)V
+Lcom/android/internal/widget/ViewPager$OnPageChangeListener;->onPageScrolled(IFI)V
+Lcom/android/internal/widget/ViewPager$OnPageChangeListener;->onPageScrollStateChanged(I)V
+Lcom/android/internal/widget/ViewPager$OnPageChangeListener;->onPageSelected(I)V
+Lcom/android/internal/widget/ViewPager;->getCurrentItem()I
 Lcom/android/okhttp/Connection;->getSocket()Ljava/net/Socket;
 Lcom/android/okhttp/ConnectionPool;->connections:Ljava/util/Deque;
 Lcom/android/okhttp/ConnectionPool;->keepAliveDurationNs:J
 Lcom/android/okhttp/ConnectionPool;->maxIdleConnections:I
 Lcom/android/okhttp/ConnectionPool;->systemDefault:Lcom/android/okhttp/ConnectionPool;
+Lcom/android/okhttp/HttpHandler;-><init>()V
+Lcom/android/okhttp/HttpsHandler;-><init>()V
 Lcom/android/okhttp/HttpUrl$Builder;->build()Lcom/android/okhttp/HttpUrl;
 Lcom/android/okhttp/HttpUrl;->encodedPath()Ljava/lang/String;
 Lcom/android/okhttp/HttpUrl;->newBuilder()Lcom/android/okhttp/HttpUrl$Builder;
 Lcom/android/okhttp/HttpUrl;->parse(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl;
 Lcom/android/okhttp/HttpUrl;->query()Ljava/lang/String;
+Lcom/android/okhttp/internal/http/HeaderParser;->skipUntil(Ljava/lang/String;ILjava/lang/String;)I
+Lcom/android/okhttp/internal/http/HeaderParser;->skipWhitespace(Ljava/lang/String;I)I
+Lcom/android/okhttp/internal/http/HttpDate;->format(Ljava/util/Date;)Ljava/lang/String;
+Lcom/android/okhttp/internal/http/HttpDate;->parse(Ljava/lang/String;)Ljava/util/Date;
 Lcom/android/okhttp/internal/http/HttpEngine;->getConnection()Lcom/android/okhttp/Connection;
 Lcom/android/okhttp/internal/http/HttpEngine;->hasResponse()Z
 Lcom/android/okhttp/internal/http/HttpEngine;->httpStream:Lcom/android/okhttp/internal/http/HttpStream;
@@ -2111,6 +4168,29 @@
 Lcom/android/okhttp/internal/http/HttpEngine;->userResponse:Lcom/android/okhttp/Response;
 Lcom/android/okhttp/internal/http/HttpEngine;->writingRequestHeaders()V
 Lcom/android/okhttp/internal/http/RouteSelector;->hasNext()Z
+Lcom/android/okhttp/internal/huc/HttpsURLConnectionImpl;->delegate:Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;
+Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->client:Lcom/android/okhttp/OkHttpClient;
+Lcom/android/okhttp/internal/huc/HttpURLConnectionImpl;->httpEngine:Lcom/android/okhttp/internal/http/HttpEngine;
+Lcom/android/okhttp/internal/Internal;-><init>()V
+Lcom/android/okhttp/internal/Internal;->addLenient(Lcom/android/okhttp/Headers$Builder;Ljava/lang/String;)V
+Lcom/android/okhttp/internal/Internal;->addLenient(Lcom/android/okhttp/Headers$Builder;Ljava/lang/String;Ljava/lang/String;)V
+Lcom/android/okhttp/internal/Internal;->apply(Lcom/android/okhttp/ConnectionSpec;Ljavax/net/ssl/SSLSocket;Z)V
+Lcom/android/okhttp/internal/Internal;->callEngineGetStreamAllocation(Lcom/android/okhttp/Call;)Lcom/android/okhttp/internal/http/StreamAllocation;
+Lcom/android/okhttp/internal/Internal;->callEnqueue(Lcom/android/okhttp/Call;Lcom/android/okhttp/Callback;Z)V
+Lcom/android/okhttp/internal/Internal;->connectionBecameIdle(Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/internal/io/RealConnection;)Z
+Lcom/android/okhttp/internal/Internal;->get(Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/Address;Lcom/android/okhttp/internal/http/StreamAllocation;)Lcom/android/okhttp/internal/io/RealConnection;
+Lcom/android/okhttp/internal/Internal;->getHttpUrlChecked(Ljava/lang/String;)Lcom/android/okhttp/HttpUrl;
+Lcom/android/okhttp/internal/Internal;->instance:Lcom/android/okhttp/internal/Internal;
+Lcom/android/okhttp/internal/Internal;->internalCache(Lcom/android/okhttp/OkHttpClient;)Lcom/android/okhttp/internal/InternalCache;
+Lcom/android/okhttp/internal/Internal;->put(Lcom/android/okhttp/ConnectionPool;Lcom/android/okhttp/internal/io/RealConnection;)V
+Lcom/android/okhttp/internal/Internal;->routeDatabase(Lcom/android/okhttp/ConnectionPool;)Lcom/android/okhttp/internal/RouteDatabase;
+Lcom/android/okhttp/internal/Internal;->setCache(Lcom/android/okhttp/OkHttpClient;Lcom/android/okhttp/internal/InternalCache;)V
+Lcom/android/okhttp/internal/Platform;->get()Lcom/android/okhttp/internal/Platform;
+Lcom/android/okhttp/internal/Platform;->logW(Ljava/lang/String;)V
+Lcom/android/okhttp/internal/Util;->closeAll(Ljava/io/Closeable;Ljava/io/Closeable;)V
+Lcom/android/okhttp/internal/Util;->closeQuietly(Ljava/io/Closeable;)V
+Lcom/android/okhttp/internal/Util;->EMPTY_BYTE_ARRAY:[B
+Lcom/android/okhttp/internal/Util;->UTF_8:Ljava/nio/charset/Charset;
 Lcom/android/okhttp/OkHttpClient;-><init>()V
 Lcom/android/okhttp/OkHttpClient;->connectionPool:Lcom/android/okhttp/ConnectionPool;
 Lcom/android/okhttp/OkHttpClient;->DEFAULT_PROTOCOLS:Ljava/util/List;
@@ -2131,76 +4211,73 @@
 Lcom/android/okhttp/Response;->message:Ljava/lang/String;
 Lcom/android/okhttp/Response;->networkResponse:Lcom/android/okhttp/Response;
 Lcom/android/okhttp/Response;->protocol:Lcom/android/okhttp/Protocol;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getAlpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocol()Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getApplicationProtocols()[Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getChannelId()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHandshakeApplicationProtocol()Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHostname()Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getHostnameOrIP()Ljava/lang/String;
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getNpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->getSoWriteTimeout()I
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setAlpnProtocols([B)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setAlpnProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setApplicationProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setChannelIdEnabled(Z)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setHandshakeTimeout(I)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setHostname(Ljava/lang/String;)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setNpnProtocols([B)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setSoWriteTimeout(I)V
-Lcom/android/org/conscrypt/AbstractConscryptSocket;->setUseSessionTickets(Z)V
-Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setHostname(Ljava/lang/String;)V
-Lcom/android/org/conscrypt/ConscryptFileDescriptorSocket;->setUseSessionTickets(Z)V
-Lcom/android/org/conscrypt/OpenSSLKey;-><init>(J)V
-Lcom/android/org/conscrypt/OpenSSLKey;->fromPrivateKey(Ljava/security/PrivateKey;)Lcom/android/org/conscrypt/OpenSSLKey;
-Lcom/android/org/conscrypt/OpenSSLKey;->getNativeRef()Lcom/android/org/conscrypt/NativeRef$EVP_PKEY;
-Lcom/android/org/conscrypt/OpenSSLKey;->getPublicKey()Ljava/security/PublicKey;
-Lcom/android/org/conscrypt/OpenSSLProvider;-><init>()V
-Lcom/android/org/conscrypt/OpenSSLRandom;-><init>()V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getAlpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getChannelId()[B
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostname()Ljava/lang/String;
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getHostnameOrIP()Ljava/lang/String;
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getNpnSelectedProtocol()[B
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->getSoWriteTimeout()I
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([B)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setAlpnProtocols([Ljava/lang/String;)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setChannelIdEnabled(Z)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setChannelIdPrivateKey(Ljava/security/PrivateKey;)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setHandshakeTimeout(I)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setHostname(Ljava/lang/String;)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setNpnProtocols([B)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setSoWriteTimeout(I)V
-Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setUseSessionTickets(Z)V
-Lcom/android/org/conscrypt/OpenSSLX509Certificate;->fromX509PemInputStream(Ljava/io/InputStream;)Lcom/android/org/conscrypt/OpenSSLX509Certificate;
-Lcom/android/org/conscrypt/OpenSSLX509Certificate;->mContext:J
-Lcom/android/org/conscrypt/TrustedCertificateStore;-><init>()V
-Lcom/android/org/conscrypt/TrustedCertificateStore;->getCertificateChain(Ljava/security/cert/X509Certificate;)Ljava/util/List;
-Lcom/android/org/conscrypt/TrustManagerImpl;-><init>(Ljava/security/KeyStore;)V
-Lcom/android/org/conscrypt/TrustManagerImpl;->checkServerTrusted([Ljava/security/cert/X509Certificate;Ljava/lang/String;Ljava/lang/String;)Ljava/util/List;
+Lcom/android/server/net/BaseNetworkObserver;-><init>()V
+Lcom/android/server/net/NetlinkTracker;-><init>(Ljava/lang/String;Lcom/android/server/net/NetlinkTracker$Callback;)V
+Lcom/android/server/net/NetlinkTracker;->clearLinkProperties()V
+Lcom/android/server/net/NetlinkTracker;->getLinkProperties()Landroid/net/LinkProperties;
+Lcom/android/server/ResettableTimeout$T;-><init>(Lcom/android/server/ResettableTimeout;)V
+Lcom/android/server/ResettableTimeout;->mLock:Landroid/os/ConditionVariable;
+Lcom/android/server/ResettableTimeout;->mOffAt:J
+Lcom/google/android/collect/Lists;->newArrayList([Ljava/lang/Object;)Ljava/util/ArrayList;
+Lcom/google/android/collect/Sets;->newArraySet()Landroid/util/ArraySet;
+Lcom/google/android/collect/Sets;->newArraySet([Ljava/lang/Object;)Landroid/util/ArraySet;
+Lcom/google/android/collect/Sets;->newHashSet()Ljava/util/HashSet;
+Lcom/google/android/collect/Sets;->newHashSet([Ljava/lang/Object;)Ljava/util/HashSet;
+Lcom/google/android/collect/Sets;->newSortedSet()Ljava/util/SortedSet;
+Lcom/google/android/gles_jni/EGLImpl;-><init>()V
+Lcom/google/android/gles_jni/GLImpl;-><init>()V
 Lcom/google/android/mms/ContentType;->getAudioTypes()Ljava/util/ArrayList;
 Lcom/google/android/mms/ContentType;->getImageTypes()Ljava/util/ArrayList;
 Lcom/google/android/mms/ContentType;->getVideoTypes()Ljava/util/ArrayList;
 Lcom/google/android/mms/ContentType;->isAudioType(Ljava/lang/String;)Z
 Lcom/google/android/mms/ContentType;->isDrmType(Ljava/lang/String;)Z
 Lcom/google/android/mms/ContentType;->isImageType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isSupportedAudioType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isSupportedImageType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isSupportedType(Ljava/lang/String;)Z
+Lcom/google/android/mms/ContentType;->isSupportedVideoType(Ljava/lang/String;)Z
 Lcom/google/android/mms/ContentType;->isTextType(Ljava/lang/String;)Z
 Lcom/google/android/mms/ContentType;->isVideoType(Ljava/lang/String;)Z
+Lcom/google/android/mms/InvalidHeaderValueException;-><init>(Ljava/lang/String;)V
 Lcom/google/android/mms/MmsException;-><init>()V
 Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/String;)V
+Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;)V
 Lcom/google/android/mms/MmsException;-><init>(Ljava/lang/Throwable;)V
 Lcom/google/android/mms/pdu/AcknowledgeInd;-><init>(I[B)V
+Lcom/google/android/mms/pdu/AcknowledgeInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
+Lcom/google/android/mms/pdu/AcknowledgeInd;->setReportAllowed(I)V
+Lcom/google/android/mms/pdu/AcknowledgeInd;->setTransactionId([B)V
+Lcom/google/android/mms/pdu/Base64;->decodeBase64([B)[B
+Lcom/google/android/mms/pdu/CharacterSets;->getMibEnumValue(Ljava/lang/String;)I
 Lcom/google/android/mms/pdu/CharacterSets;->getMimeName(I)Ljava/lang/String;
+Lcom/google/android/mms/pdu/DeliveryInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
+Lcom/google/android/mms/pdu/DeliveryInd;->getDate()J
 Lcom/google/android/mms/pdu/DeliveryInd;->getMessageId()[B
+Lcom/google/android/mms/pdu/DeliveryInd;->getStatus()I
+Lcom/google/android/mms/pdu/DeliveryInd;->getTo()[Lcom/google/android/mms/pdu/EncodedStringValue;
 Lcom/google/android/mms/pdu/EncodedStringValue;-><init>(I[B)V
 Lcom/google/android/mms/pdu/EncodedStringValue;-><init>(Ljava/lang/String;)V
 Lcom/google/android/mms/pdu/EncodedStringValue;-><init>([B)V
+Lcom/google/android/mms/pdu/EncodedStringValue;->appendTextString([B)V
 Lcom/google/android/mms/pdu/EncodedStringValue;->concat([Lcom/google/android/mms/pdu/EncodedStringValue;)Ljava/lang/String;
+Lcom/google/android/mms/pdu/EncodedStringValue;->copy(Lcom/google/android/mms/pdu/EncodedStringValue;)Lcom/google/android/mms/pdu/EncodedStringValue;
 Lcom/google/android/mms/pdu/EncodedStringValue;->encodeStrings([Ljava/lang/String;)[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/EncodedStringValue;->extract(Ljava/lang/String;)[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/EncodedStringValue;->getCharacterSet()I
 Lcom/google/android/mms/pdu/EncodedStringValue;->getString()Ljava/lang/String;
+Lcom/google/android/mms/pdu/EncodedStringValue;->getTextString()[B
+Lcom/google/android/mms/pdu/EncodedStringValue;->setCharacterSet(I)V
+Lcom/google/android/mms/pdu/EncodedStringValue;->setTextString([B)V
+Lcom/google/android/mms/pdu/GenericPdu;-><init>()V
+Lcom/google/android/mms/pdu/GenericPdu;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue;
 Lcom/google/android/mms/pdu/GenericPdu;->getMessageType()I
+Lcom/google/android/mms/pdu/GenericPdu;->getPduHeaders()Lcom/google/android/mms/pdu/PduHeaders;
+Lcom/google/android/mms/pdu/GenericPdu;->mPduHeaders:Lcom/google/android/mms/pdu/PduHeaders;
 Lcom/google/android/mms/pdu/GenericPdu;->setFrom(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/GenericPdu;->setMessageType(I)V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;-><init>()V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;-><init>(Lcom/google/android/mms/pdu/PduHeaders;Lcom/google/android/mms/pdu/PduBody;)V
+Lcom/google/android/mms/pdu/MultimediaMessagePdu;->addTo(Lcom/google/android/mms/pdu/EncodedStringValue;)V
 Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getBody()Lcom/google/android/mms/pdu/PduBody;
 Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getDate()J
 Lcom/google/android/mms/pdu/MultimediaMessagePdu;->getPriority()I
@@ -2210,15 +4287,31 @@
 Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setDate(J)V
 Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setPriority(I)V
 Lcom/google/android/mms/pdu/MultimediaMessagePdu;->setSubject(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/NotificationInd;-><init>()V
+Lcom/google/android/mms/pdu/NotificationInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
+Lcom/google/android/mms/pdu/NotificationInd;->getContentClass()I
 Lcom/google/android/mms/pdu/NotificationInd;->getContentLocation()[B
+Lcom/google/android/mms/pdu/NotificationInd;->getDeliveryReport()I
 Lcom/google/android/mms/pdu/NotificationInd;->getExpiry()J
 Lcom/google/android/mms/pdu/NotificationInd;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue;
 Lcom/google/android/mms/pdu/NotificationInd;->getMessageClass()[B
 Lcom/google/android/mms/pdu/NotificationInd;->getMessageSize()J
 Lcom/google/android/mms/pdu/NotificationInd;->getSubject()Lcom/google/android/mms/pdu/EncodedStringValue;
 Lcom/google/android/mms/pdu/NotificationInd;->getTransactionId()[B
+Lcom/google/android/mms/pdu/NotificationInd;->setContentClass(I)V
 Lcom/google/android/mms/pdu/NotificationInd;->setContentLocation([B)V
+Lcom/google/android/mms/pdu/NotificationInd;->setDeliveryReport(I)V
+Lcom/google/android/mms/pdu/NotificationInd;->setExpiry(J)V
+Lcom/google/android/mms/pdu/NotificationInd;->setFrom(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/NotificationInd;->setMessageClass([B)V
+Lcom/google/android/mms/pdu/NotificationInd;->setMessageSize(J)V
+Lcom/google/android/mms/pdu/NotificationInd;->setSubject(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/NotificationInd;->setTransactionId([B)V
 Lcom/google/android/mms/pdu/NotifyRespInd;-><init>(I[BI)V
+Lcom/google/android/mms/pdu/NotifyRespInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
+Lcom/google/android/mms/pdu/NotifyRespInd;->setReportAllowed(I)V
+Lcom/google/android/mms/pdu/NotifyRespInd;->setStatus(I)V
+Lcom/google/android/mms/pdu/NotifyRespInd;->setTransactionId([B)V
 Lcom/google/android/mms/pdu/PduBody;-><init>()V
 Lcom/google/android/mms/pdu/PduBody;->addPart(ILcom/google/android/mms/pdu/PduPart;)V
 Lcom/google/android/mms/pdu/PduBody;->addPart(Lcom/google/android/mms/pdu/PduPart;)Z
@@ -2227,62 +4320,1114 @@
 Lcom/google/android/mms/pdu/PduBody;->getPartByContentLocation(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
 Lcom/google/android/mms/pdu/PduBody;->getPartByFileName(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
 Lcom/google/android/mms/pdu/PduBody;->getPartByName(Ljava/lang/String;)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduBody;->getPartIndex(Lcom/google/android/mms/pdu/PduPart;)I
 Lcom/google/android/mms/pdu/PduBody;->getPartsNum()I
+Lcom/google/android/mms/pdu/PduBody;->removePart(I)Lcom/google/android/mms/pdu/PduPart;
+Lcom/google/android/mms/pdu/PduComposer$BufferStack;->copy()V
+Lcom/google/android/mms/pdu/PduComposer$BufferStack;->mark()Lcom/google/android/mms/pdu/PduComposer$PositionMarker;
+Lcom/google/android/mms/pdu/PduComposer$BufferStack;->newbuf()V
+Lcom/google/android/mms/pdu/PduComposer$BufferStack;->pop()V
+Lcom/google/android/mms/pdu/PduComposer$PositionMarker;->getLength()I
 Lcom/google/android/mms/pdu/PduComposer;-><init>(Landroid/content/Context;Lcom/google/android/mms/pdu/GenericPdu;)V
+Lcom/google/android/mms/pdu/PduComposer;->appendEncodedString(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/PduComposer;->appendHeader(I)I
+Lcom/google/android/mms/pdu/PduComposer;->appendLongInteger(J)V
+Lcom/google/android/mms/pdu/PduComposer;->appendOctet(I)V
+Lcom/google/android/mms/pdu/PduComposer;->appendQuotedString(Ljava/lang/String;)V
+Lcom/google/android/mms/pdu/PduComposer;->appendQuotedString([B)V
+Lcom/google/android/mms/pdu/PduComposer;->appendShortInteger(I)V
+Lcom/google/android/mms/pdu/PduComposer;->appendTextString(Ljava/lang/String;)V
+Lcom/google/android/mms/pdu/PduComposer;->appendTextString([B)V
+Lcom/google/android/mms/pdu/PduComposer;->appendUintvarInteger(J)V
+Lcom/google/android/mms/pdu/PduComposer;->appendValueLength(J)V
+Lcom/google/android/mms/pdu/PduComposer;->arraycopy([BII)V
 Lcom/google/android/mms/pdu/PduComposer;->make()[B
+Lcom/google/android/mms/pdu/PduComposer;->mContentTypeMap:Ljava/util/HashMap;
+Lcom/google/android/mms/pdu/PduComposer;->mMessage:Ljava/io/ByteArrayOutputStream;
+Lcom/google/android/mms/pdu/PduComposer;->mPdu:Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/pdu/PduComposer;->mPduHeader:Lcom/google/android/mms/pdu/PduHeaders;
+Lcom/google/android/mms/pdu/PduComposer;->mPosition:I
+Lcom/google/android/mms/pdu/PduComposer;->mResolver:Landroid/content/ContentResolver;
+Lcom/google/android/mms/pdu/PduComposer;->mStack:Lcom/google/android/mms/pdu/PduComposer$BufferStack;
+Lcom/google/android/mms/pdu/PduContentTypes;->contentTypes:[Ljava/lang/String;
+Lcom/google/android/mms/pdu/PduHeaders;-><init>()V
+Lcom/google/android/mms/pdu/PduHeaders;->appendEncodedStringValue(Lcom/google/android/mms/pdu/EncodedStringValue;I)V
+Lcom/google/android/mms/pdu/PduHeaders;->getEncodedStringValue(I)Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/PduHeaders;->getEncodedStringValues(I)[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/PduHeaders;->getLongInteger(I)J
+Lcom/google/android/mms/pdu/PduHeaders;->getOctet(I)I
+Lcom/google/android/mms/pdu/PduHeaders;->getTextString(I)[B
+Lcom/google/android/mms/pdu/PduHeaders;->setEncodedStringValue(Lcom/google/android/mms/pdu/EncodedStringValue;I)V
+Lcom/google/android/mms/pdu/PduHeaders;->setLongInteger(JI)V
+Lcom/google/android/mms/pdu/PduHeaders;->setOctet(II)V
+Lcom/google/android/mms/pdu/PduParser;->$assertionsDisabled:Z
+Lcom/google/android/mms/pdu/PduParser;-><init>([BZ)V
+Lcom/google/android/mms/pdu/PduParser;->checkPartPosition(Lcom/google/android/mms/pdu/PduPart;)I
+Lcom/google/android/mms/pdu/PduParser;->log(Ljava/lang/String;)V
 Lcom/google/android/mms/pdu/PduParser;->parse()Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/pdu/PduParser;->parseContentType(Ljava/io/ByteArrayInputStream;Ljava/util/HashMap;)[B
+Lcom/google/android/mms/pdu/PduParser;->parsePartHeaders(Ljava/io/ByteArrayInputStream;Lcom/google/android/mms/pdu/PduPart;I)Z
+Lcom/google/android/mms/pdu/PduParser;->parseShortInteger(Ljava/io/ByteArrayInputStream;)I
+Lcom/google/android/mms/pdu/PduParser;->parseUnsignedInt(Ljava/io/ByteArrayInputStream;)I
+Lcom/google/android/mms/pdu/PduParser;->parseValueLength(Ljava/io/ByteArrayInputStream;)I
+Lcom/google/android/mms/pdu/PduParser;->parseWapString(Ljava/io/ByteArrayInputStream;I)[B
 Lcom/google/android/mms/pdu/PduPart;-><init>()V
 Lcom/google/android/mms/pdu/PduPart;->generateLocation()Ljava/lang/String;
 Lcom/google/android/mms/pdu/PduPart;->getCharset()I
+Lcom/google/android/mms/pdu/PduPart;->getContentDisposition()[B
+Lcom/google/android/mms/pdu/PduPart;->getContentId()[B
 Lcom/google/android/mms/pdu/PduPart;->getContentLocation()[B
+Lcom/google/android/mms/pdu/PduPart;->getContentTransferEncoding()[B
 Lcom/google/android/mms/pdu/PduPart;->getContentType()[B
 Lcom/google/android/mms/pdu/PduPart;->getData()[B
+Lcom/google/android/mms/pdu/PduPart;->getDataLength()I
 Lcom/google/android/mms/pdu/PduPart;->getDataUri()Landroid/net/Uri;
 Lcom/google/android/mms/pdu/PduPart;->getFilename()[B
 Lcom/google/android/mms/pdu/PduPart;->getName()[B
 Lcom/google/android/mms/pdu/PduPart;->setCharset(I)V
+Lcom/google/android/mms/pdu/PduPart;->setContentDisposition([B)V
 Lcom/google/android/mms/pdu/PduPart;->setContentId([B)V
 Lcom/google/android/mms/pdu/PduPart;->setContentLocation([B)V
+Lcom/google/android/mms/pdu/PduPart;->setContentTransferEncoding([B)V
 Lcom/google/android/mms/pdu/PduPart;->setContentType([B)V
 Lcom/google/android/mms/pdu/PduPart;->setData([B)V
 Lcom/google/android/mms/pdu/PduPart;->setDataUri(Landroid/net/Uri;)V
+Lcom/google/android/mms/pdu/PduPart;->setFilename([B)V
+Lcom/google/android/mms/pdu/PduPart;->setName([B)V
+Lcom/google/android/mms/pdu/PduPersister;->ADDRESS_FIELDS:[I
+Lcom/google/android/mms/pdu/PduPersister;->CHARSET_COLUMN_NAME_MAP:Ljava/util/HashMap;
+Lcom/google/android/mms/pdu/PduPersister;->ENCODED_STRING_COLUMN_NAME_MAP:Ljava/util/HashMap;
+Lcom/google/android/mms/pdu/PduPersister;->getByteArrayFromPartColumn(Landroid/database/Cursor;I)[B
 Lcom/google/android/mms/pdu/PduPersister;->getBytes(Ljava/lang/String;)[B
+Lcom/google/android/mms/pdu/PduPersister;->getIntegerFromPartColumn(Landroid/database/Cursor;I)Ljava/lang/Integer;
+Lcom/google/android/mms/pdu/PduPersister;->getPartContentType(Lcom/google/android/mms/pdu/PduPart;)Ljava/lang/String;
 Lcom/google/android/mms/pdu/PduPersister;->getPduPersister(Landroid/content/Context;)Lcom/google/android/mms/pdu/PduPersister;
 Lcom/google/android/mms/pdu/PduPersister;->getPendingMessages(J)Landroid/database/Cursor;
 Lcom/google/android/mms/pdu/PduPersister;->load(Landroid/net/Uri;)Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/pdu/PduPersister;->loadRecipients(ILjava/util/HashSet;Ljava/util/HashMap;Z)V
+Lcom/google/android/mms/pdu/PduPersister;->LONG_COLUMN_NAME_MAP:Ljava/util/HashMap;
+Lcom/google/android/mms/pdu/PduPersister;->mContentResolver:Landroid/content/ContentResolver;
+Lcom/google/android/mms/pdu/PduPersister;->mContext:Landroid/content/Context;
+Lcom/google/android/mms/pdu/PduPersister;->MESSAGE_BOX_MAP:Ljava/util/HashMap;
 Lcom/google/android/mms/pdu/PduPersister;->move(Landroid/net/Uri;Landroid/net/Uri;)Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPersister;->mTelephonyManager:Landroid/telephony/TelephonyManager;
+Lcom/google/android/mms/pdu/PduPersister;->OCTET_COLUMN_NAME_MAP:Ljava/util/HashMap;
+Lcom/google/android/mms/pdu/PduPersister;->PART_PROJECTION:[Ljava/lang/String;
+Lcom/google/android/mms/pdu/PduPersister;->PDU_CACHE_INSTANCE:Lcom/google/android/mms/util/PduCache;
 Lcom/google/android/mms/pdu/PduPersister;->persist(Lcom/google/android/mms/pdu/GenericPdu;Landroid/net/Uri;ZZLjava/util/HashMap;)Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPersister;->persistAddress(JI[Lcom/google/android/mms/pdu/EncodedStringValue;)V
 Lcom/google/android/mms/pdu/PduPersister;->persistPart(Lcom/google/android/mms/pdu/PduPart;JLjava/util/HashMap;)Landroid/net/Uri;
+Lcom/google/android/mms/pdu/PduPersister;->TEXT_STRING_COLUMN_NAME_MAP:Ljava/util/HashMap;
 Lcom/google/android/mms/pdu/PduPersister;->toIsoString([B)Ljava/lang/String;
+Lcom/google/android/mms/pdu/PduPersister;->updateAddress(JI[Lcom/google/android/mms/pdu/EncodedStringValue;)V
 Lcom/google/android/mms/pdu/PduPersister;->updateHeaders(Landroid/net/Uri;Lcom/google/android/mms/pdu/SendReq;)V
 Lcom/google/android/mms/pdu/PduPersister;->updateParts(Landroid/net/Uri;Lcom/google/android/mms/pdu/PduBody;Ljava/util/HashMap;)V
+Lcom/google/android/mms/pdu/QuotedPrintable;->decodeQuotedPrintable([B)[B
+Lcom/google/android/mms/pdu/ReadOrigInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
 Lcom/google/android/mms/pdu/ReadOrigInd;->getMessageId()[B
+Lcom/google/android/mms/pdu/ReadOrigInd;->getReadStatus()I
 Lcom/google/android/mms/pdu/ReadRecInd;-><init>(Lcom/google/android/mms/pdu/EncodedStringValue;[BII[Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/ReadRecInd;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
+Lcom/google/android/mms/pdu/ReadRecInd;->getMessageId()[B
 Lcom/google/android/mms/pdu/ReadRecInd;->setDate(J)V
+Lcom/google/android/mms/pdu/RetrieveConf;-><init>()V
+Lcom/google/android/mms/pdu/RetrieveConf;-><init>(Lcom/google/android/mms/pdu/PduHeaders;Lcom/google/android/mms/pdu/PduBody;)V
+Lcom/google/android/mms/pdu/RetrieveConf;->addCc(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/RetrieveConf;->getCc()[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/RetrieveConf;->getContentType()[B
+Lcom/google/android/mms/pdu/RetrieveConf;->getDeliveryReport()I
 Lcom/google/android/mms/pdu/RetrieveConf;->getFrom()Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/RetrieveConf;->getMessageClass()[B
 Lcom/google/android/mms/pdu/RetrieveConf;->getMessageId()[B
+Lcom/google/android/mms/pdu/RetrieveConf;->getReadReport()I
+Lcom/google/android/mms/pdu/RetrieveConf;->getRetrieveStatus()I
+Lcom/google/android/mms/pdu/RetrieveConf;->getRetrieveText()Lcom/google/android/mms/pdu/EncodedStringValue;
 Lcom/google/android/mms/pdu/RetrieveConf;->getTransactionId()[B
+Lcom/google/android/mms/pdu/RetrieveConf;->setContentType([B)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setDeliveryReport(I)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setFrom(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setMessageClass([B)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setMessageId([B)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setReadReport(I)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setRetrieveStatus(I)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setRetrieveText(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/RetrieveConf;->setTransactionId([B)V
+Lcom/google/android/mms/pdu/SendConf;-><init>()V
+Lcom/google/android/mms/pdu/SendConf;-><init>(Lcom/google/android/mms/pdu/PduHeaders;)V
 Lcom/google/android/mms/pdu/SendConf;->getMessageId()[B
 Lcom/google/android/mms/pdu/SendConf;->getResponseStatus()I
 Lcom/google/android/mms/pdu/SendConf;->getTransactionId()[B
 Lcom/google/android/mms/pdu/SendReq;-><init>()V
+Lcom/google/android/mms/pdu/SendReq;-><init>(Lcom/google/android/mms/pdu/PduHeaders;Lcom/google/android/mms/pdu/PduBody;)V
+Lcom/google/android/mms/pdu/SendReq;->addBcc(Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/SendReq;->addCc(Lcom/google/android/mms/pdu/EncodedStringValue;)V
 Lcom/google/android/mms/pdu/SendReq;->getBcc()[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/SendReq;->getCc()[Lcom/google/android/mms/pdu/EncodedStringValue;
+Lcom/google/android/mms/pdu/SendReq;->getContentType()[B
+Lcom/google/android/mms/pdu/SendReq;->getDeliveryReport()I
+Lcom/google/android/mms/pdu/SendReq;->getExpiry()J
+Lcom/google/android/mms/pdu/SendReq;->getMessageClass()[B
+Lcom/google/android/mms/pdu/SendReq;->getMessageSize()J
+Lcom/google/android/mms/pdu/SendReq;->getReadReport()I
 Lcom/google/android/mms/pdu/SendReq;->getTransactionId()[B
+Lcom/google/android/mms/pdu/SendReq;->setBcc([Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/SendReq;->setCc([Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/SendReq;->setContentType([B)V
 Lcom/google/android/mms/pdu/SendReq;->setDeliveryReport(I)V
 Lcom/google/android/mms/pdu/SendReq;->setExpiry(J)V
 Lcom/google/android/mms/pdu/SendReq;->setMessageClass([B)V
 Lcom/google/android/mms/pdu/SendReq;->setMessageSize(J)V
 Lcom/google/android/mms/pdu/SendReq;->setReadReport(I)V
 Lcom/google/android/mms/pdu/SendReq;->setTo([Lcom/google/android/mms/pdu/EncodedStringValue;)V
+Lcom/google/android/mms/pdu/SendReq;->setTransactionId([B)V
+Lcom/google/android/mms/util/AbstractCache;-><init>()V
 Lcom/google/android/mms/util/AbstractCache;->get(Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/google/android/mms/util/AbstractCache;->purge(Ljava/lang/Object;)Ljava/lang/Object;
+Lcom/google/android/mms/util/AbstractCache;->purgeAll()V
+Lcom/google/android/mms/util/AbstractCache;->put(Ljava/lang/Object;Ljava/lang/Object;)Z
+Lcom/google/android/mms/util/DownloadDrmHelper;->isDrmConvertNeeded(Ljava/lang/String;)Z
+Lcom/google/android/mms/util/DownloadDrmHelper;->modifyDrmFwLockFileExtension(Ljava/lang/String;)Ljava/lang/String;
+Lcom/google/android/mms/util/DrmConvertSession;->close(Ljava/lang/String;)I
+Lcom/google/android/mms/util/DrmConvertSession;->convert([BI)[B
+Lcom/google/android/mms/util/DrmConvertSession;->open(Landroid/content/Context;Ljava/lang/String;)Lcom/google/android/mms/util/DrmConvertSession;
+Lcom/google/android/mms/util/PduCache;-><init>()V
 Lcom/google/android/mms/util/PduCache;->getInstance()Lcom/google/android/mms/util/PduCache;
 Lcom/google/android/mms/util/PduCache;->isUpdating(Landroid/net/Uri;)Z
 Lcom/google/android/mms/util/PduCache;->purge(Landroid/net/Uri;)Lcom/google/android/mms/util/PduCacheEntry;
 Lcom/google/android/mms/util/PduCache;->purgeAll()V
+Lcom/google/android/mms/util/PduCacheEntry;-><init>(Lcom/google/android/mms/pdu/GenericPdu;IJ)V
+Lcom/google/android/mms/util/PduCacheEntry;->getMessageBox()I
 Lcom/google/android/mms/util/PduCacheEntry;->getPdu()Lcom/google/android/mms/pdu/GenericPdu;
+Lcom/google/android/mms/util/PduCacheEntry;->getThreadId()J
+Lcom/google/android/mms/util/SqliteWrapper;->checkSQLiteException(Landroid/content/Context;Landroid/database/sqlite/SQLiteException;)V
+Lcom/google/android/mms/util/SqliteWrapper;->delete(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Ljava/lang/String;[Ljava/lang/String;)I
 Lcom/google/android/mms/util/SqliteWrapper;->insert(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri;
+Lcom/google/android/mms/util/SqliteWrapper;->query(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;
+Lcom/google/android/mms/util/SqliteWrapper;->requery(Landroid/content/Context;Landroid/database/Cursor;)Z
+Lcom/google/android/mms/util/SqliteWrapper;->update(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;)I
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->ACRONYM:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->FLICKR:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->FORMAT:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->GOOGLE_VIDEO:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->HTML:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->LINK:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->MUSIC:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->PHOTO:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->SMILEY:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->values()[Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/google/android/util/AbstractMessageParser$Token$Type;->YOUTUBE_VIDEO:Lcom/google/android/util/AbstractMessageParser$Token$Type;
+Lcom/sun/nio/file/ExtendedWatchEventModifier;->FILE_TREE:Lcom/sun/nio/file/ExtendedWatchEventModifier;
+Lgov/nist/core/Debug;->printStackTrace(Ljava/lang/Exception;)V
+Lgov/nist/core/GenericObject;-><init>()V
+Lgov/nist/core/GenericObject;->dbgPrint()V
+Lgov/nist/core/GenericObject;->debugDump(I)Ljava/lang/String;
+Lgov/nist/core/GenericObject;->encode()Ljava/lang/String;
+Lgov/nist/core/GenericObject;->getMatcher()Lgov/nist/core/Match;
+Lgov/nist/core/GenericObject;->indentation:I
+Lgov/nist/core/GenericObject;->isMySubclass(Ljava/lang/Class;)Z
+Lgov/nist/core/GenericObject;->match(Ljava/lang/Object;)Z
+Lgov/nist/core/GenericObject;->matchExpression:Lgov/nist/core/Match;
+Lgov/nist/core/GenericObject;->merge(Ljava/lang/Object;)V
+Lgov/nist/core/GenericObject;->sprint(Ljava/lang/String;)V
+Lgov/nist/core/GenericObject;->stringRepresentation:Ljava/lang/String;
+Lgov/nist/core/GenericObjectList;-><init>()V
+Lgov/nist/core/GenericObjectList;-><init>(Ljava/lang/String;)V
+Lgov/nist/core/GenericObjectList;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
+Lgov/nist/core/GenericObjectList;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lgov/nist/core/GenericObjectList;->concatenate(Lgov/nist/core/GenericObjectList;)V
+Lgov/nist/core/GenericObjectList;->concatenate(Lgov/nist/core/GenericObjectList;Z)V
+Lgov/nist/core/GenericObjectList;->debugDump(I)Ljava/lang/String;
+Lgov/nist/core/GenericObjectList;->first()Lgov/nist/core/GenericObject;
+Lgov/nist/core/GenericObjectList;->getIndentation()Ljava/lang/String;
+Lgov/nist/core/GenericObjectList;->indentation:I
+Lgov/nist/core/GenericObjectList;->isMySubclass(Ljava/lang/Class;)Z
+Lgov/nist/core/GenericObjectList;->match(Ljava/lang/Object;)Z
+Lgov/nist/core/GenericObjectList;->myClass:Ljava/lang/Class;
+Lgov/nist/core/GenericObjectList;->next()Lgov/nist/core/GenericObject;
+Lgov/nist/core/GenericObjectList;->next(Ljava/util/ListIterator;)Lgov/nist/core/GenericObject;
+Lgov/nist/core/GenericObjectList;->setMyClass(Ljava/lang/Class;)V
+Lgov/nist/core/GenericObjectList;->stringRep:Ljava/lang/String;
+Lgov/nist/core/Host;-><init>()V
+Lgov/nist/core/Host;-><init>(Ljava/lang/String;)V
+Lgov/nist/core/Host;->encode()Ljava/lang/String;
+Lgov/nist/core/Host;->getAddress()Ljava/lang/String;
+Lgov/nist/core/Host;->getHostname()Ljava/lang/String;
+Lgov/nist/core/Host;->isIPv6Reference(Ljava/lang/String;)Z
+Lgov/nist/core/Host;->setAddress(Ljava/lang/String;)V
+Lgov/nist/core/Host;->setHostname(Ljava/lang/String;)V
+Lgov/nist/core/HostNameParser;-><init>(Lgov/nist/core/LexerCore;)V
+Lgov/nist/core/HostNameParser;-><init>(Ljava/lang/String;)V
+Lgov/nist/core/HostNameParser;->host()Lgov/nist/core/Host;
+Lgov/nist/core/HostNameParser;->hostPort(Z)Lgov/nist/core/HostPort;
+Lgov/nist/core/HostPort;-><init>()V
+Lgov/nist/core/HostPort;->encode()Ljava/lang/String;
+Lgov/nist/core/HostPort;->encode(Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer;
+Lgov/nist/core/HostPort;->getHost()Lgov/nist/core/Host;
+Lgov/nist/core/HostPort;->getInetAddress()Ljava/net/InetAddress;
+Lgov/nist/core/HostPort;->getPort()I
+Lgov/nist/core/HostPort;->hasPort()Z
+Lgov/nist/core/HostPort;->removePort()V
+Lgov/nist/core/HostPort;->setHost(Lgov/nist/core/Host;)V
+Lgov/nist/core/HostPort;->setPort(I)V
+Lgov/nist/core/InternalErrorHandler;->handleException(Ljava/lang/Exception;)V
+Lgov/nist/core/InternalErrorHandler;->handleException(Ljava/lang/String;)V
+Lgov/nist/core/LexerCore;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lgov/nist/core/LexerCore;->byteStringNoSemicolon()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->byteStringNoSlash()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->charAsString(I)Ljava/lang/String;
+Lgov/nist/core/LexerCore;->comment()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->createParseException()Ljava/text/ParseException;
+Lgov/nist/core/LexerCore;->currentLexer:Ljava/util/Hashtable;
+Lgov/nist/core/LexerCore;->getBuffer()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->getNextId()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->getNextToken()Lgov/nist/core/Token;
+Lgov/nist/core/LexerCore;->getPtr()I
+Lgov/nist/core/LexerCore;->getRest()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->getString(C)Ljava/lang/String;
+Lgov/nist/core/LexerCore;->isTokenChar(C)Z
+Lgov/nist/core/LexerCore;->lexerTables:Ljava/util/Hashtable;
+Lgov/nist/core/LexerCore;->markInputPosition()I
+Lgov/nist/core/LexerCore;->match(I)Lgov/nist/core/Token;
+Lgov/nist/core/LexerCore;->number()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->peekNextToken()Lgov/nist/core/Token;
+Lgov/nist/core/LexerCore;->peekNextToken(I)[Lgov/nist/core/Token;
+Lgov/nist/core/LexerCore;->quotedString()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->rewindInputPosition(I)V
+Lgov/nist/core/LexerCore;->selectLexer(Ljava/lang/String;)V
+Lgov/nist/core/LexerCore;->SPorHT()V
+Lgov/nist/core/LexerCore;->startsId()Z
+Lgov/nist/core/LexerCore;->ttoken()Ljava/lang/String;
+Lgov/nist/core/LexerCore;->ttokenSafe()Ljava/lang/String;
+Lgov/nist/core/Match;->match(Ljava/lang/String;)Z
+Lgov/nist/core/NameValue;-><init>()V
+Lgov/nist/core/NameValue;-><init>(Ljava/lang/String;Ljava/lang/Object;)V
+Lgov/nist/core/NameValue;-><init>(Ljava/lang/String;Ljava/lang/Object;Z)V
+Lgov/nist/core/NameValue;->encode()Ljava/lang/String;
+Lgov/nist/core/NameValue;->encode(Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer;
+Lgov/nist/core/NameValue;->getName()Ljava/lang/String;
+Lgov/nist/core/NameValue;->getValueAsObject()Ljava/lang/Object;
+Lgov/nist/core/NameValue;->setName(Ljava/lang/String;)V
+Lgov/nist/core/NameValue;->setQuotedValue()V
+Lgov/nist/core/NameValue;->setSeparator(Ljava/lang/String;)V
+Lgov/nist/core/NameValue;->setValueAsObject(Ljava/lang/Object;)V
+Lgov/nist/core/NameValueList;-><init>()V
+Lgov/nist/core/NameValueList;-><init>(Z)V
+Lgov/nist/core/NameValueList;->delete(Ljava/lang/String;)Z
+Lgov/nist/core/NameValueList;->encode()Ljava/lang/String;
+Lgov/nist/core/NameValueList;->encode(Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer;
+Lgov/nist/core/NameValueList;->getNames()Ljava/util/Iterator;
+Lgov/nist/core/NameValueList;->getNameValue(Ljava/lang/String;)Lgov/nist/core/NameValue;
+Lgov/nist/core/NameValueList;->getParameter(Ljava/lang/String;)Ljava/lang/String;
+Lgov/nist/core/NameValueList;->getValue(Ljava/lang/String;)Ljava/lang/Object;
+Lgov/nist/core/NameValueList;->hasNameValue(Ljava/lang/String;)Z
+Lgov/nist/core/NameValueList;->iterator()Ljava/util/Iterator;
+Lgov/nist/core/NameValueList;->set(Lgov/nist/core/NameValue;)V
+Lgov/nist/core/NameValueList;->set(Ljava/lang/String;Ljava/lang/Object;)V
+Lgov/nist/core/NameValueList;->setSeparator(Ljava/lang/String;)V
+Lgov/nist/core/net/DefaultNetworkLayer;->SINGLETON:Lgov/nist/core/net/DefaultNetworkLayer;
+Lgov/nist/core/net/NetworkLayer;->createDatagramSocket()Ljava/net/DatagramSocket;
+Lgov/nist/core/net/NetworkLayer;->createDatagramSocket(ILjava/net/InetAddress;)Ljava/net/DatagramSocket;
+Lgov/nist/core/net/NetworkLayer;->createServerSocket(IILjava/net/InetAddress;)Ljava/net/ServerSocket;
+Lgov/nist/core/net/NetworkLayer;->createSocket(Ljava/net/InetAddress;I)Ljava/net/Socket;
+Lgov/nist/core/net/NetworkLayer;->createSSLServerSocket(IILjava/net/InetAddress;)Ljavax/net/ssl/SSLServerSocket;
+Lgov/nist/core/net/NetworkLayer;->createSSLSocket(Ljava/net/InetAddress;I)Ljavax/net/ssl/SSLSocket;
+Lgov/nist/core/ParserCore;-><init>()V
+Lgov/nist/core/ParserCore;->lexer:Lgov/nist/core/LexerCore;
+Lgov/nist/core/StringTokenizer;->ptr:I
+Lgov/nist/core/ThreadAuditor$ThreadHandle;->getPingIntervalInMillisecs()J
+Lgov/nist/core/ThreadAuditor$ThreadHandle;->ping()V
+Lgov/nist/core/ThreadAuditor;-><init>()V
+Lgov/nist/core/ThreadAuditor;->addCurrentThread()Lgov/nist/core/ThreadAuditor$ThreadHandle;
+Lgov/nist/core/ThreadAuditor;->getPingIntervalInMillisecs()J
+Lgov/nist/core/ThreadAuditor;->isEnabled()Z
+Lgov/nist/core/ThreadAuditor;->setPingIntervalInMillisecs(J)V
+Lgov/nist/core/Token;-><init>()V
+Lgov/nist/core/Token;->getTokenType()I
+Lgov/nist/core/Token;->getTokenValue()Ljava/lang/String;
+Lgov/nist/javax/sip/address/GenericURI;-><init>()V
+Lgov/nist/javax/sip/address/GenericURI;->encode()Ljava/lang/String;
+Lgov/nist/javax/sip/address/GenericURI;->getScheme()Ljava/lang/String;
+Lgov/nist/javax/sip/address/SipUri;->getHost()Ljava/lang/String;
+Lgov/nist/javax/sip/address/SipUri;->getParameter(Ljava/lang/String;)Ljava/lang/String;
+Lgov/nist/javax/sip/address/SipUri;->getPort()I
+Lgov/nist/javax/sip/address/SipUri;->getUser()Ljava/lang/String;
+Lgov/nist/javax/sip/address/SipUri;->removeParameter(Ljava/lang/String;)V
+Lgov/nist/javax/sip/address/SipUri;->setParameter(Ljava/lang/String;Ljava/lang/String;)V
+Lgov/nist/javax/sip/address/SipUri;->setUserParam(Ljava/lang/String;)V
+Lgov/nist/javax/sip/parser/URLParser;-><init>(Ljava/lang/String;)V
+Lgov/nist/javax/sip/parser/URLParser;->sipURL(Z)Lgov/nist/javax/sip/address/SipUri;
+Ljava/lang/DexCache;->dexFile:J
+Ljava/lang/invoke/SerializedLambda;-><init>(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
+Ljava/lang/invoke/SerializedLambda;->getCapturedArg(I)Ljava/lang/Object;
+Ljava/lang/invoke/SerializedLambda;->getCapturedArgCount()I
+Ljava/lang/invoke/SerializedLambda;->getCapturingClass()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getFunctionalInterfaceClass()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getFunctionalInterfaceMethodName()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getFunctionalInterfaceMethodSignature()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getImplClass()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getImplMethodKind()I
+Ljava/lang/invoke/SerializedLambda;->getImplMethodName()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getImplMethodSignature()Ljava/lang/String;
+Ljava/lang/invoke/SerializedLambda;->getInstantiatedMethodType()Ljava/lang/String;
+Ljava/lang/UNIXProcess;->pid:I
+Ljava/net/AddressCache$AddressCacheEntry;-><init>(Ljava/lang/Object;)V
+Ljava/net/AddressCache$AddressCacheEntry;->expiryNanos:J
+Ljava/net/AddressCache$AddressCacheEntry;->value:Ljava/lang/Object;
+Ljava/net/AddressCache$AddressCacheKey;->mHostname:Ljava/lang/String;
+Ljava/net/AddressCache;->cache:Llibcore/util/BasicLruCache;
+Ljava/net/Inet6AddressImpl;->addressCache:Ljava/net/AddressCache;
+Ljava/net/PlainSocketImpl;-><init>()V
+Ljava/nio/DirectByteBuffer;->cleaner()Lsun/misc/Cleaner;
+Ljava/nio/file/FileTreeWalker;->followLinks:Z
+Ljava/nio/file/FileTreeWalker;->linkOptions:[Ljava/nio/file/LinkOption;
+Ljava/nio/file/FileTreeWalker;->maxDepth:I
+Ljava/util/zip/ZipFile$ZipEntryIterator;->nextElement()Ljava/util/zip/ZipEntry;
+Ljunit/framework/TestCase;->fName:Ljava/lang/String;
+Ljunit/framework/TestSuite;->isPublicTestMethod(Ljava/lang/reflect/Method;)Z
+Ljunit/framework/TestSuite;->isTestMethod(Ljava/lang/reflect/Method;)Z
+Llibcore/icu/DateIntervalFormat;->formatDateRange(JJILjava/lang/String;)Ljava/lang/String;
+Llibcore/icu/ICU;->CACHED_PATTERNS:Llibcore/util/BasicLruCache;
+Llibcore/icu/ICU;->getBestDateTimePattern(Ljava/lang/String;Ljava/util/Locale;)Ljava/lang/String;
+Llibcore/icu/ICU;->getBestDateTimePatternNative(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Llibcore/icu/ICU;->getDateFormatOrder(Ljava/lang/String;)[C
+Llibcore/icu/LocaleData;->firstDayOfWeek:Ljava/lang/Integer;
+Llibcore/icu/LocaleData;->get(Ljava/util/Locale;)Llibcore/icu/LocaleData;
+Llibcore/icu/LocaleData;->longStandAloneWeekdayNames:[Ljava/lang/String;
+Llibcore/icu/LocaleData;->mapInvalidAndNullLocales(Ljava/util/Locale;)Ljava/util/Locale;
+Llibcore/icu/LocaleData;->minimalDaysInFirstWeek:Ljava/lang/Integer;
+Llibcore/icu/LocaleData;->shortMonthNames:[Ljava/lang/String;
+Llibcore/icu/LocaleData;->shortStandAloneMonthNames:[Ljava/lang/String;
+Llibcore/icu/LocaleData;->shortStandAloneWeekdayNames:[Ljava/lang/String;
+Llibcore/icu/LocaleData;->timeFormat_Hm:Ljava/lang/String;
+Llibcore/icu/LocaleData;->timeFormat_hm:Ljava/lang/String;
+Llibcore/icu/LocaleData;->today:Ljava/lang/String;
+Llibcore/icu/LocaleData;->tomorrow:Ljava/lang/String;
+Llibcore/icu/LocaleData;->zeroDigit:C
+Llibcore/icu/TimeZoneNames;->forLocale(Ljava/util/Locale;)[Ljava/lang/String;
+Llibcore/io/AsynchronousCloseMonitor;->signalBlockedThreads(Ljava/io/FileDescriptor;)V
+Llibcore/io/BlockGuardOs;-><init>(Llibcore/io/Os;)V
+Llibcore/io/BlockGuardOs;->chmod(Ljava/lang/String;I)V
+Llibcore/io/BlockGuardOs;->chown(Ljava/lang/String;II)V
+Llibcore/io/BlockGuardOs;->close(Ljava/io/FileDescriptor;)V
+Llibcore/io/BlockGuardOs;->fchmod(Ljava/io/FileDescriptor;I)V
+Llibcore/io/BlockGuardOs;->fchown(Ljava/io/FileDescriptor;II)V
+Llibcore/io/BlockGuardOs;->fdatasync(Ljava/io/FileDescriptor;)V
+Llibcore/io/BlockGuardOs;->fstat(Ljava/io/FileDescriptor;)Landroid/system/StructStat;
+Llibcore/io/BlockGuardOs;->fstatvfs(Ljava/io/FileDescriptor;)Landroid/system/StructStatVfs;
+Llibcore/io/BlockGuardOs;->lchown(Ljava/lang/String;II)V
+Llibcore/io/BlockGuardOs;->link(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/BlockGuardOs;->lseek(Ljava/io/FileDescriptor;JI)J
+Llibcore/io/BlockGuardOs;->lstat(Ljava/lang/String;)Landroid/system/StructStat;
+Llibcore/io/BlockGuardOs;->mkdir(Ljava/lang/String;I)V
+Llibcore/io/BlockGuardOs;->mkfifo(Ljava/lang/String;I)V
+Llibcore/io/BlockGuardOs;->open(Ljava/lang/String;II)Ljava/io/FileDescriptor;
+Llibcore/io/BlockGuardOs;->posix_fallocate(Ljava/io/FileDescriptor;JJ)V
+Llibcore/io/BlockGuardOs;->pread(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;J)I
+Llibcore/io/BlockGuardOs;->pread(Ljava/io/FileDescriptor;[BIIJ)I
+Llibcore/io/BlockGuardOs;->pwrite(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;J)I
+Llibcore/io/BlockGuardOs;->pwrite(Ljava/io/FileDescriptor;[BIIJ)I
+Llibcore/io/BlockGuardOs;->read(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;)I
+Llibcore/io/BlockGuardOs;->read(Ljava/io/FileDescriptor;[BII)I
+Llibcore/io/BlockGuardOs;->readlink(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/io/BlockGuardOs;->readv(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I
+Llibcore/io/BlockGuardOs;->realpath(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/io/BlockGuardOs;->remove(Ljava/lang/String;)V
+Llibcore/io/BlockGuardOs;->rename(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/BlockGuardOs;->stat(Ljava/lang/String;)Landroid/system/StructStat;
+Llibcore/io/BlockGuardOs;->statvfs(Ljava/lang/String;)Landroid/system/StructStatVfs;
+Llibcore/io/BlockGuardOs;->symlink(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/BlockGuardOs;->write(Ljava/io/FileDescriptor;Ljava/nio/ByteBuffer;)I
+Llibcore/io/BlockGuardOs;->write(Ljava/io/FileDescriptor;[BII)I
+Llibcore/io/BlockGuardOs;->writev(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I
+Llibcore/io/BufferIterator;->readByte()B
+Llibcore/io/BufferIterator;->readByteArray([BII)V
+Llibcore/io/BufferIterator;->readInt()I
+Llibcore/io/BufferIterator;->readIntArray([III)V
+Llibcore/io/BufferIterator;->seek(I)V
+Llibcore/io/BufferIterator;->skip(I)V
+Llibcore/io/DropBox;->addText(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/ForwardingOs;-><init>(Llibcore/io/Os;)V
+Llibcore/io/ForwardingOs;->access(Ljava/lang/String;I)Z
+Llibcore/io/ForwardingOs;->chmod(Ljava/lang/String;I)V
+Llibcore/io/ForwardingOs;->chown(Ljava/lang/String;II)V
+Llibcore/io/ForwardingOs;->getenv(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/io/ForwardingOs;->lchown(Ljava/lang/String;II)V
+Llibcore/io/ForwardingOs;->link(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/ForwardingOs;->lstat(Ljava/lang/String;)Landroid/system/StructStat;
+Llibcore/io/ForwardingOs;->mkdir(Ljava/lang/String;I)V
+Llibcore/io/ForwardingOs;->mkfifo(Ljava/lang/String;I)V
+Llibcore/io/ForwardingOs;->open(Ljava/lang/String;II)Ljava/io/FileDescriptor;
+Llibcore/io/ForwardingOs;->os:Llibcore/io/Os;
+Llibcore/io/ForwardingOs;->readlink(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/io/ForwardingOs;->remove(Ljava/lang/String;)V
+Llibcore/io/ForwardingOs;->removexattr(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/ForwardingOs;->rename(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/ForwardingOs;->setenv(Ljava/lang/String;Ljava/lang/String;Z)V
+Llibcore/io/ForwardingOs;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V
+Llibcore/io/ForwardingOs;->setxattr(Ljava/lang/String;Ljava/lang/String;[BI)V
+Llibcore/io/ForwardingOs;->stat(Ljava/lang/String;)Landroid/system/StructStat;
+Llibcore/io/ForwardingOs;->statvfs(Ljava/lang/String;)Landroid/system/StructStatVfs;
+Llibcore/io/ForwardingOs;->symlink(Ljava/lang/String;Ljava/lang/String;)V
+Llibcore/io/ForwardingOs;->sysconf(I)J
+Llibcore/io/ForwardingOs;->unlink(Ljava/lang/String;)V
+Llibcore/io/IoBridge;->isConnected(Ljava/io/FileDescriptor;Ljava/net/InetAddress;III)Z
+Llibcore/io/IoUtils;->closeQuietly(Ljava/io/FileDescriptor;)V
+Llibcore/io/IoUtils;->closeQuietly(Ljava/lang/AutoCloseable;)V
+Llibcore/io/IoUtils;->closeQuietly(Ljava/net/Socket;)V
+Llibcore/io/IoUtils;->readFileAsByteArray(Ljava/lang/String;)[B
+Llibcore/io/IoUtils;->readFileAsString(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/io/IoUtils;->setBlocking(Ljava/io/FileDescriptor;Z)V
+Llibcore/io/MemoryMappedFile;->bigEndianIterator()Llibcore/io/BufferIterator;
+Llibcore/io/MemoryMappedFile;->mmapRO(Ljava/lang/String;)Llibcore/io/MemoryMappedFile;
+Llibcore/io/Os;->chmod(Ljava/lang/String;I)V
+Llibcore/io/Os;->close(Ljava/io/FileDescriptor;)V
+Llibcore/io/Os;->connect(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V
+Llibcore/io/Os;->gai_strerror(I)Ljava/lang/String;
+Llibcore/io/Os;->remove(Ljava/lang/String;)V
+Llibcore/io/Os;->setenv(Ljava/lang/String;Ljava/lang/String;Z)V
+Llibcore/io/Os;->setsockoptTimeval(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V
+Llibcore/io/Os;->stat(Ljava/lang/String;)Landroid/system/StructStat;
+Llibcore/io/Os;->strerror(I)Ljava/lang/String;
+Llibcore/io/Os;->sysconf(I)J
+Llibcore/io/Streams;->readAsciiLine(Ljava/io/InputStream;)Ljava/lang/String;
+Llibcore/io/Streams;->readFully(Ljava/io/InputStream;)[B
+Llibcore/io/Streams;->readFully(Ljava/io/InputStream;[B)V
+Llibcore/io/Streams;->readSingleByte(Ljava/io/InputStream;)I
+Llibcore/io/Streams;->skipAll(Ljava/io/InputStream;)V
+Llibcore/io/Streams;->writeSingleByte(Ljava/io/OutputStream;I)V
+Llibcore/net/event/NetworkEventDispatcher;->addListener(Llibcore/net/event/NetworkEventListener;)V
+Llibcore/net/event/NetworkEventDispatcher;->getInstance()Llibcore/net/event/NetworkEventDispatcher;
+Llibcore/net/event/NetworkEventListener;-><init>()V
+Llibcore/net/http/HttpDate;->format(Ljava/util/Date;)Ljava/lang/String;
+Llibcore/net/http/HttpDate;->parse(Ljava/lang/String;)Ljava/util/Date;
+Llibcore/net/MimeUtils;->guessExtensionFromMimeType(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/net/MimeUtils;->guessMimeTypeFromExtension(Ljava/lang/String;)Ljava/lang/String;
+Llibcore/net/NetworkSecurityPolicy;->isCleartextTrafficPermitted()Z
+Llibcore/util/BasicLruCache;-><init>(I)V
+Llibcore/util/BasicLruCache;->evictAll()V
+Llibcore/util/BasicLruCache;->get(Ljava/lang/Object;)Ljava/lang/Object;
+Llibcore/util/BasicLruCache;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+Llibcore/util/EmptyArray;->BYTE:[B
+Llibcore/util/EmptyArray;->INT:[I
+Llibcore/util/EmptyArray;->OBJECT:[Ljava/lang/Object;
+Llibcore/util/ZoneInfoDB$TzData;-><init>()V
+Lorg/apache/harmony/dalvik/ddmc/Chunk;-><init>(ILjava/nio/ByteBuffer;)V
+Lorg/apache/harmony/dalvik/ddmc/ChunkHandler;->CHUNK_ORDER:Ljava/nio/ByteOrder;
+Lorg/apache/harmony/dalvik/ddmc/DdmServer;->broadcast(I)V
+Lorg/apache/harmony/dalvik/ddmc/DdmServer;->sendChunk(Lorg/apache/harmony/dalvik/ddmc/Chunk;)V
+Lorg/apache/harmony/dalvik/ddmc/DdmVmInternal;->getThreadStats()[B
+Lorg/apache/harmony/xml/dom/ElementImpl;->localName:Ljava/lang/String;
+Lorg/apache/harmony/xml/ExpatAttributes;-><init>()V
+Lorg/apache/harmony/xml/ExpatParser$EntityParser;->depth:I
+Lorg/apache/harmony/xml/ExpatParser;-><init>(Ljava/lang/String;Lorg/apache/harmony/xml/ExpatReader;ZLjava/lang/String;Ljava/lang/String;)V
+Lorg/apache/harmony/xml/ExpatParser;->append([BII)V
+Lorg/apache/harmony/xml/ExpatParser;->append([CII)V
+Lorg/apache/harmony/xml/ExpatParser;->attributes:Lorg/apache/harmony/xml/ExpatAttributes;
+Lorg/apache/harmony/xml/ExpatParser;->cloneAttributes()Lorg/xml/sax/Attributes;
+Lorg/apache/harmony/xml/ExpatParser;->finish()V
+Lorg/apache/harmony/xml/ExpatParser;->xmlReader:Lorg/apache/harmony/xml/ExpatReader;
+Lorg/apache/harmony/xml/ExpatReader;-><init>()V
+Lorg/apache/harmony/xml/ExpatReader;->contentHandler:Lorg/xml/sax/ContentHandler;
+Lorg/apache/xalan/extensions/ExpressionContext;->getContextNode()Lorg/w3c/dom/Node;
+Lorg/apache/xalan/extensions/ExpressionContext;->getErrorListener()Ljavax/xml/transform/ErrorListener;
+Lorg/apache/xalan/extensions/ExpressionContext;->getVariableOrParam(Lorg/apache/xml/utils/QName;)Lorg/apache/xpath/objects/XObject;
+Lorg/apache/xalan/extensions/ExpressionContext;->getXPathContext()Lorg/apache/xpath/XPathContext;
+Lorg/apache/xalan/extensions/ExtensionHandler;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lorg/apache/xalan/extensions/ExtensionHandler;->callFunction(Ljava/lang/String;Ljava/util/Vector;Ljava/lang/Object;Lorg/apache/xalan/extensions/ExpressionContext;)Ljava/lang/Object;
+Lorg/apache/xalan/extensions/ExtensionHandler;->getClassForName(Ljava/lang/String;)Ljava/lang/Class;
+Lorg/apache/xalan/extensions/ObjectFactory$ConfigurationError;-><init>(Ljava/lang/String;Ljava/lang/Exception;)V
+Lorg/apache/xalan/extensions/ObjectFactory;->findClassLoader()Ljava/lang/ClassLoader;
+Lorg/apache/xalan/extensions/ObjectFactory;->findProviderClass(Ljava/lang/String;Ljava/lang/ClassLoader;Z)Ljava/lang/Class;
+Lorg/apache/xalan/processor/TransformerFactoryImpl;-><init>()V
+Lorg/apache/xalan/res/XSLMessages;->createMessage(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
+Lorg/apache/xalan/res/XSLTErrorResources;-><init>()V
+Lorg/apache/xalan/serialize/SerializerUtils;->outputResultTreeFragment(Lorg/apache/xml/serializer/SerializationHandler;Lorg/apache/xpath/objects/XObject;Lorg/apache/xpath/XPathContext;)V
+Lorg/apache/xalan/templates/AVT;->evaluate(Lorg/apache/xpath/XPathContext;ILorg/apache/xml/utils/PrefixResolver;)Ljava/lang/String;
+Lorg/apache/xalan/templates/ElemElement;->execute(Lorg/apache/xalan/transformer/TransformerImpl;)V
+Lorg/apache/xalan/templates/ElemExsltFunction;->execute(Lorg/apache/xalan/transformer/TransformerImpl;[Lorg/apache/xpath/objects/XObject;)V
+Lorg/apache/xalan/templates/ElemExtensionCall;->getAttribute(Ljava/lang/String;Lorg/w3c/dom/Node;Lorg/apache/xalan/transformer/TransformerImpl;)Ljava/lang/String;
+Lorg/apache/xalan/templates/ElemLiteralResult;->getLiteralResultAttribute(Ljava/lang/String;)Lorg/apache/xalan/templates/AVT;
+Lorg/apache/xalan/templates/ElemTemplate;->getMatch()Lorg/apache/xpath/XPath;
+Lorg/apache/xalan/templates/ElemTemplate;->getName()Lorg/apache/xml/utils/QName;
+Lorg/apache/xalan/templates/ElemTemplateElement;->getFirstChildElem()Lorg/apache/xalan/templates/ElemTemplateElement;
+Lorg/apache/xalan/templates/ElemTemplateElement;->getNextSiblingElem()Lorg/apache/xalan/templates/ElemTemplateElement;
+Lorg/apache/xalan/templates/ElemTemplateElement;->getParentElem()Lorg/apache/xalan/templates/ElemTemplateElement;
+Lorg/apache/xalan/templates/ElemTemplateElement;->getStylesheetRoot()Lorg/apache/xalan/templates/StylesheetRoot;
+Lorg/apache/xalan/templates/ElemTemplateElement;->getXSLToken()I
+Lorg/apache/xalan/templates/ElemTextLiteral;->getChars()[C
+Lorg/apache/xalan/templates/KeyDeclaration;->getName()Lorg/apache/xml/utils/QName;
+Lorg/apache/xalan/templates/KeyDeclaration;->getUse()Lorg/apache/xpath/XPath;
+Lorg/apache/xalan/templates/StylesheetRoot;->getDefaultRootRule()Lorg/apache/xalan/templates/ElemTemplate;
+Lorg/apache/xalan/templates/StylesheetRoot;->getDefaultRule()Lorg/apache/xalan/templates/ElemTemplate;
+Lorg/apache/xalan/templates/StylesheetRoot;->getDefaultTextRule()Lorg/apache/xalan/templates/ElemTemplate;
+Lorg/apache/xalan/templates/StylesheetRoot;->getTemplateComposed(Lorg/apache/xml/utils/QName;)Lorg/apache/xalan/templates/ElemTemplate;
+Lorg/apache/xalan/transformer/ClonerToResultTree;->cloneToResultTree(IILorg/apache/xml/dtm/DTM;Lorg/apache/xml/serializer/SerializationHandler;Z)V
+Lorg/apache/xalan/transformer/DecimalToRoman;-><init>(JLjava/lang/String;JLjava/lang/String;)V
+Lorg/apache/xalan/transformer/DecimalToRoman;->m_postLetter:Ljava/lang/String;
+Lorg/apache/xalan/transformer/DecimalToRoman;->m_postValue:J
+Lorg/apache/xalan/transformer/DecimalToRoman;->m_preLetter:Ljava/lang/String;
+Lorg/apache/xalan/transformer/DecimalToRoman;->m_preValue:J
+Lorg/apache/xalan/transformer/MsgMgr;->error(Ljavax/xml/transform/SourceLocator;Lorg/w3c/dom/Node;Lorg/w3c/dom/Node;Ljava/lang/String;)V
+Lorg/apache/xalan/transformer/TransformerImpl;->createSerializationHandler(Ljavax/xml/transform/Result;Lorg/apache/xalan/templates/OutputProperties;)Lorg/apache/xml/serializer/SerializationHandler;
+Lorg/apache/xalan/transformer/TransformerImpl;->executeChildTemplates(Lorg/apache/xalan/templates/ElemTemplateElement;Lorg/w3c/dom/Node;Lorg/apache/xml/utils/QName;Lorg/xml/sax/ContentHandler;)V
+Lorg/apache/xalan/transformer/TransformerImpl;->executeChildTemplates(Lorg/apache/xalan/templates/ElemTemplateElement;Z)V
+Lorg/apache/xalan/transformer/TransformerImpl;->getCountersTable()Lorg/apache/xalan/transformer/CountersTable;
+Lorg/apache/xalan/transformer/TransformerImpl;->getCurrentTemplateElements()Lorg/apache/xml/utils/ObjectStack;
+Lorg/apache/xalan/transformer/TransformerImpl;->getCurrentTemplateElementsCount()I
+Lorg/apache/xalan/transformer/TransformerImpl;->getMatchedNode()I
+Lorg/apache/xalan/transformer/TransformerImpl;->getMatchedTemplate()Lorg/apache/xalan/templates/ElemTemplate;
+Lorg/apache/xalan/transformer/TransformerImpl;->getMode()Lorg/apache/xml/utils/QName;
+Lorg/apache/xalan/transformer/TransformerImpl;->getMsgMgr()Lorg/apache/xalan/transformer/MsgMgr;
+Lorg/apache/xalan/transformer/TransformerImpl;->getOutputFormat()Lorg/apache/xalan/templates/OutputProperties;
+Lorg/apache/xalan/transformer/TransformerImpl;->getResultTreeHandler()Lorg/apache/xml/serializer/SerializationHandler;
+Lorg/apache/xalan/transformer/TransformerImpl;->getSerializationHandler()Lorg/apache/xml/serializer/SerializationHandler;
+Lorg/apache/xalan/transformer/TransformerImpl;->getXPathContext()Lorg/apache/xpath/XPathContext;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_attrSetStack:Ljava/util/Stack;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_currentMatchedNodes:Lorg/apache/xml/utils/NodeVector;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_currentMatchTemplates:Ljava/util/Stack;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_currentTemplateElements:Lorg/apache/xml/utils/ObjectStack;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_currentTemplateRuleIsNull:Lorg/apache/xml/utils/BoolStack;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_inputContentHandler:Lorg/xml/sax/ContentHandler;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_outputTarget:Ljavax/xml/transform/Result;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_stringWriterObjectPool:Lorg/apache/xml/utils/ObjectPool;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_urlOfSource:Ljava/lang/String;
+Lorg/apache/xalan/transformer/TransformerImpl;->m_xcontext:Lorg/apache/xpath/XPathContext;
+Lorg/apache/xalan/transformer/TransformerImpl;->popCurrentFuncResult()Ljava/lang/Object;
+Lorg/apache/xalan/transformer/TransformerImpl;->pushCurrentFuncResult(Ljava/lang/Object;)V
+Lorg/apache/xalan/transformer/TransformerImpl;->pushElemTemplateElement(Lorg/apache/xalan/templates/ElemTemplateElement;)V
+Lorg/apache/xalan/Version;->getVersion()Ljava/lang/String;
+Lorg/apache/xalan/xslt/EnvironmentCheck;-><init>()V
+Lorg/apache/xalan/xslt/EnvironmentCheck;->appendEnvironmentReport(Lorg/w3c/dom/Node;Lorg/w3c/dom/Document;Ljava/util/Hashtable;)V
+Lorg/apache/xalan/xslt/EnvironmentCheck;->getEnvironmentHash()Ljava/util/Hashtable;
+Lorg/apache/xalan/xslt/ObjectFactory;->findClassLoader()Ljava/lang/ClassLoader;
+Lorg/apache/xalan/xslt/ObjectFactory;->newInstance(Ljava/lang/String;Ljava/lang/ClassLoader;Z)Ljava/lang/Object;
+Lorg/apache/xml/dtm/Axis;->getNames(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/Axis;->isReverse(I)Z
+Lorg/apache/xml/dtm/DTM;->getDocument()I
+Lorg/apache/xml/dtm/DTM;->getDocumentRoot(I)I
+Lorg/apache/xml/dtm/DTM;->getFirstChild(I)I
+Lorg/apache/xml/dtm/DTM;->getNextSibling(I)I
+Lorg/apache/xml/dtm/DTM;->getNode(I)Lorg/w3c/dom/Node;
+Lorg/apache/xml/dtm/DTM;->getNodeName(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/DTM;->getNodeType(I)S
+Lorg/apache/xml/dtm/DTM;->getParent(I)I
+Lorg/apache/xml/dtm/DTM;->getSourceLocatorFor(I)Ljavax/xml/transform/SourceLocator;
+Lorg/apache/xml/dtm/DTM;->getStringValue(I)Lorg/apache/xml/utils/XMLString;
+Lorg/apache/xml/dtm/DTM;->migrateTo(Lorg/apache/xml/dtm/DTMManager;)V
+Lorg/apache/xml/dtm/DTMAxisIterator;->cloneIterator()Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/DTMAxisIterator;->getLast()I
+Lorg/apache/xml/dtm/DTMAxisIterator;->getNodeByPosition(I)I
+Lorg/apache/xml/dtm/DTMAxisIterator;->getPosition()I
+Lorg/apache/xml/dtm/DTMAxisIterator;->gotoMark()V
+Lorg/apache/xml/dtm/DTMAxisIterator;->isReverse()Z
+Lorg/apache/xml/dtm/DTMAxisIterator;->next()I
+Lorg/apache/xml/dtm/DTMAxisIterator;->reset()Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/DTMAxisIterator;->setMark()V
+Lorg/apache/xml/dtm/DTMAxisIterator;->setRestartable(Z)V
+Lorg/apache/xml/dtm/DTMAxisIterator;->setStartNode(I)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/DTMException;-><init>(Ljava/lang/String;)V
+Lorg/apache/xml/dtm/DTMFilter;->acceptNode(II)S
+Lorg/apache/xml/dtm/DTMIterator;->cloneWithReset()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xml/dtm/DTMIterator;->getCurrentPos()I
+Lorg/apache/xml/dtm/DTMIterator;->getDTM(I)Lorg/apache/xml/dtm/DTM;
+Lorg/apache/xml/dtm/DTMIterator;->nextNode()I
+Lorg/apache/xml/dtm/DTMIterator;->runTo(I)V
+Lorg/apache/xml/dtm/DTMIterator;->setCurrentPos(I)V
+Lorg/apache/xml/dtm/DTMIterator;->setRoot(ILjava/lang/Object;)V
+Lorg/apache/xml/dtm/DTMIterator;->setShouldCacheNodes(Z)V
+Lorg/apache/xml/dtm/DTMManager;->getDTM(Ljavax/xml/transform/Source;ZLorg/apache/xml/dtm/DTMWSFilter;ZZ)Lorg/apache/xml/dtm/DTM;
+Lorg/apache/xml/dtm/DTMManager;->getXMLStringFactory()Lorg/apache/xml/utils/XMLStringFactory;
+Lorg/apache/xml/dtm/DTMManager;->release(Lorg/apache/xml/dtm/DTM;Z)Z
+Lorg/apache/xml/dtm/ref/CoroutineManager;-><init>()V
+Lorg/apache/xml/dtm/ref/CoroutineManager;->co_joinCoroutineSet(I)I
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;-><init>()V
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->includeSelf()Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->reset()Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->resetPosition()Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->returnNode(I)I
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->setRestartable(Z)V
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_includeSelf:Z
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_isRestartable:Z
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_last:I
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_markedNode:I
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_position:I
+Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_startNode:I
+Lorg/apache/xml/dtm/ref/DTMAxisIterNodeList;-><init>(Lorg/apache/xml/dtm/DTM;Lorg/apache/xml/dtm/DTMAxisIterator;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->appendChild(IZZ)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->appendTextChild(Ljava/lang/String;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->declareNamespaceInContext(II)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->documentRegistration()V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->documentRelease()V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->ensureSizeOfIndex(II)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->error(Ljava/lang/String;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->findGTE([IIII)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->findInSortedSuballocatedIntVector(Lorg/apache/xml/utils/SuballocatedIntVector;I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->findNamespaceContext(I)Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocument()I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentAllDeclarationsProcessed()Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentBaseURI()Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentEncoding(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentRoot(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentStandalone(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentSystemIdentifier(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentVersion(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDTMIDs()Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getExpandedTypeID(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getExpandedTypeID(Ljava/lang/String;Ljava/lang/String;I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getFirstChild(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getFirstNamespaceNode(IZ)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getLastChild(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getLevel(I)S
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getLocalNameFromExpandedNameID(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getManager()Lorg/apache/xml/dtm/DTMManager;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNamespaceFromExpandedNameID(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNamespaceType(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNextAttribute(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNextNamespaceNode(IIZ)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNextSibling(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNode(I)Lorg/w3c/dom/Node;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNodeHandle(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNodeIdent(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNodeType(I)S
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getOwnerDocument(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getParent(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getPreviousSibling(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getShouldStripWhitespace()Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getStringValueChunk(II[I)[C
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getStringValueChunkCount(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->hasChildNodes(I)Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->indexNode(II)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->isCharacterElementContentWhitespace(I)Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->isDocumentAllDeclarationsProcessed(I)Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->isNodeAfter(II)Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->isSupported(Ljava/lang/String;Ljava/lang/String;)Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->makeNodeHandle(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->makeNodeIdentity(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_expandedNameTable:Lorg/apache/xml/dtm/ref/ExpandedNameTable;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_exptype:Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_firstch:Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_nextsib:Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_parent:Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_prevsib:Lorg/apache/xml/utils/SuballocatedIntVector;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_size:I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_wsfilter:Lorg/apache/xml/dtm/DTMWSFilter;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_xstrf:Lorg/apache/xml/utils/XMLStringFactory;
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->popShouldStripWhitespace()V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->pushShouldStripWhitespace(Z)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->setDocumentBaseURI(Ljava/lang/String;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->setFeature(Ljava/lang/String;Z)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->setShouldStripWhitespace(Z)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->supportsPreStripping()Z
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_exptype(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_firstch(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_level(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_nextsib(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_parent(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_prevsib(I)I
+Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_type(I)S
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$InternalAxisIteratorBase;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$InternalAxisIteratorBase;->_currentNode:I
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$NamespaceIterator;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$NamespaceIterator;->next()I
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$NamespaceIterator;->setStartNode(I)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$NthDescendantIterator;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;I)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$SingletonIterator;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$SingletonIterator;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;I)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;-><init>(Lorg/apache/xml/dtm/DTMManager;Ljavax/xml/transform/Source;ILorg/apache/xml/dtm/DTMWSFilter;Lorg/apache/xml/utils/XMLStringFactory;Z)V
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;->getAxisIterator(I)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;->getTypedAxisIterator(II)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/DTMDefaultBaseTraversers;->getAxisTraverser(I)Lorg/apache/xml/dtm/DTMAxisTraverser;
+Lorg/apache/xml/dtm/ref/DTMManagerDefault;-><init>()V
+Lorg/apache/xml/dtm/ref/DTMManagerDefault;->addDTM(Lorg/apache/xml/dtm/DTM;I)V
+Lorg/apache/xml/dtm/ref/DTMManagerDefault;->addDTM(Lorg/apache/xml/dtm/DTM;II)V
+Lorg/apache/xml/dtm/ref/DTMManagerDefault;->getFirstFreeDTMID()I
+Lorg/apache/xml/dtm/ref/DTMManagerDefault;->getXMLReader(Ljavax/xml/transform/Source;)Lorg/xml/sax/XMLReader;
+Lorg/apache/xml/dtm/ref/DTMManagerDefault;->releaseXMLReader(Lorg/xml/sax/XMLReader;)V
+Lorg/apache/xml/dtm/ref/DTMNodeIterator;-><init>(Lorg/apache/xml/dtm/DTMIterator;)V
+Lorg/apache/xml/dtm/ref/DTMNodeIterator;->getDTMIterator()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xml/dtm/ref/DTMNodeIterator;->getRoot()Lorg/w3c/dom/Node;
+Lorg/apache/xml/dtm/ref/DTMNodeList;-><init>(Lorg/apache/xml/dtm/DTMIterator;)V
+Lorg/apache/xml/dtm/ref/DTMNodeProxy;-><init>(Lorg/apache/xml/dtm/DTM;I)V
+Lorg/apache/xml/dtm/ref/DTMNodeProxy;->getDTM()Lorg/apache/xml/dtm/DTM;
+Lorg/apache/xml/dtm/ref/DTMNodeProxy;->getDTMNodeNumber()I
+Lorg/apache/xml/dtm/ref/DTMNodeProxy;->getStringValue()Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMStringPool;-><init>()V
+Lorg/apache/xml/dtm/ref/DTMStringPool;->indexToString(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/DTMStringPool;->m_intToString:Ljava/util/Vector;
+Lorg/apache/xml/dtm/ref/DTMStringPool;->removeAllElements()V
+Lorg/apache/xml/dtm/ref/DTMStringPool;->stringToIndex(Ljava/lang/String;)I
+Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getExpandedTypeID(Ljava/lang/String;Ljava/lang/String;I)I
+Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getExpandedTypeID(Ljava/lang/String;Ljava/lang/String;IZ)I
+Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getLocalName(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getSize()I
+Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getType(I)S
+Lorg/apache/xml/dtm/ref/IncrementalSAXSource;->deliverMoreNodes(Z)Ljava/lang/Object;
+Lorg/apache/xml/dtm/ref/IncrementalSAXSource;->setContentHandler(Lorg/xml/sax/ContentHandler;)V
+Lorg/apache/xml/dtm/ref/IncrementalSAXSource;->setLexicalHandler(Lorg/xml/sax/ext/LexicalHandler;)V
+Lorg/apache/xml/dtm/ref/IncrementalSAXSource;->startParse(Lorg/xml/sax/InputSource;)V
+Lorg/apache/xml/dtm/ref/IncrementalSAXSource_Filter;-><init>()V
+Lorg/apache/xml/dtm/ref/IncrementalSAXSource_Filter;->setXMLReader(Lorg/xml/sax/XMLReader;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$AncestorIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$AncestorIterator;->next()I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$AncestorIterator;->setStartNode(I)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$AttributeIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$ChildrenIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$ChildrenIterator;->setStartNode(I)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$DescendantIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$FollowingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$FollowingSiblingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$ParentIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$ParentIterator;->setNodeType(I)Lorg/apache/xml/dtm/DTMAxisIterator;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$PrecedingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$PrecedingSiblingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedAncestorIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedAttributeIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedChildrenIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedDescendantIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedFollowingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedFollowingSiblingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedPrecedingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedPrecedingSiblingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedSingletonIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;-><init>(Lorg/apache/xml/dtm/DTMManager;Ljavax/xml/transform/Source;ILorg/apache/xml/dtm/DTMWSFilter;Lorg/apache/xml/utils/XMLStringFactory;ZIZZZ)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyAttribute(IILorg/apache/xml/serializer/SerializationHandler;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyAttributes(ILorg/apache/xml/serializer/SerializationHandler;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyElement(IILorg/apache/xml/serializer/SerializationHandler;)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyNS(ILorg/apache/xml/serializer/SerializationHandler;Z)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyTextNode(ILorg/apache/xml/serializer/SerializationHandler;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->dispatchCharactersEvents(ILorg/xml/sax/ContentHandler;Z)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getFirstAttribute(I)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getIdForNamespace(Ljava/lang/String;)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getLocalName(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getNodeName(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getNodeNameX(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getNodeValue(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getStringValue()Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getStringValue(I)Lorg/apache/xml/utils/XMLString;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getStringValueX(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->m_buildIdIndex:Z
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->_exptype2(I)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->_exptype2Type(I)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->_firstch2(I)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->_nextsib2(I)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->dispatchToEvents(ILorg/xml/sax/ContentHandler;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getAttributeNode(ILjava/lang/String;Ljava/lang/String;)I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getContentHandler()Lorg/xml/sax/ContentHandler;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getDeclHandler()Lorg/xml/sax/ext/DeclHandler;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getDocumentTypeDeclarationPublicIdentifier()Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getDocumentTypeDeclarationSystemIdentifier()Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getDTDHandler()Lorg/xml/sax/DTDHandler;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getEntityResolver()Lorg/xml/sax/EntityResolver;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getErrorHandler()Lorg/xml/sax/ErrorHandler;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getLexicalHandler()Lorg/xml/sax/ext/LexicalHandler;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getNamespaceURI(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getNumberOfNodes()I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getPrefix(I)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getSourceLocatorFor(I)Ljavax/xml/transform/SourceLocator;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getUnparsedEntityURI(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->isAttributeSpecified(I)Z
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->migrateTo(Lorg/apache/xml/dtm/DTMManager;)V
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->m_idAttributes:Ljava/util/Hashtable;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->m_parents:Lorg/apache/xml/utils/IntStack;
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->m_previous:I
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->needsTwoThreads()Z
+Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->setProperty(Ljava/lang/String;Ljava/lang/Object;)V
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getContextClassLoader()Ljava/lang/ClassLoader;
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getFileExists(Ljava/io/File;)Z
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getFileInputStream(Ljava/io/File;)Ljava/io/FileInputStream;
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getInstance()Lorg/apache/xml/dtm/ref/SecuritySupport;
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getLastModified(Ljava/io/File;)J
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getParentClassLoader(Ljava/lang/ClassLoader;)Ljava/lang/ClassLoader;
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getResourceAsStream(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/io/InputStream;
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getSystemClassLoader()Ljava/lang/ClassLoader;
+Lorg/apache/xml/dtm/ref/SecuritySupport;->getSystemProperty(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/res/XMLErrorResources;-><init>()V
+Lorg/apache/xml/res/XMLMessages;->createXMLMessage(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
+Lorg/apache/xml/serializer/CharInfo$CharKey;-><init>(C)V
+Lorg/apache/xml/serializer/CharInfo;-><init>(Ljava/lang/String;Ljava/lang/String;Z)V
+Lorg/apache/xml/serializer/CharInfo;->get(I)Z
+Lorg/apache/xml/serializer/CharInfo;->getCharInfo(Ljava/lang/String;Ljava/lang/String;)Lorg/apache/xml/serializer/CharInfo;
+Lorg/apache/xml/serializer/CharInfo;->set(I)V
+Lorg/apache/xml/serializer/dom3/LSSerializerImpl;-><init>()V
+Lorg/apache/xml/serializer/DOMSerializer;->serialize(Lorg/w3c/dom/Node;)V
+Lorg/apache/xml/serializer/ElemContext;->m_elementName:Ljava/lang/String;
+Lorg/apache/xml/serializer/ElemContext;->m_elementURI:Ljava/lang/String;
+Lorg/apache/xml/serializer/ElemContext;->m_startTagOpen:Z
+Lorg/apache/xml/serializer/ElemContext;->push(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/apache/xml/serializer/ElemContext;
+Lorg/apache/xml/serializer/ElemDesc;->isAttrFlagSet(Ljava/lang/String;I)Z
+Lorg/apache/xml/serializer/Encodings;->convertMime2JavaEncoding(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/serializer/Encodings;->getMimeEncoding(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/serializer/Encodings;->getWriter(Ljava/io/OutputStream;Ljava/lang/String;)Ljava/io/Writer;
+Lorg/apache/xml/serializer/NamespaceMappings;-><init>()V
+Lorg/apache/xml/serializer/NamespaceMappings;->generateNextPrefix()Ljava/lang/String;
+Lorg/apache/xml/serializer/NamespaceMappings;->lookupNamespace(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/serializer/NamespaceMappings;->lookupPrefix(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/serializer/OutputPropertiesFactory;->getDefaultMethodProperties(Ljava/lang/String;)Ljava/util/Properties;
+Lorg/apache/xml/serializer/OutputPropertyUtils;->getBooleanProperty(Ljava/lang/String;Ljava/util/Properties;)Z
+Lorg/apache/xml/serializer/OutputPropertyUtils;->getIntProperty(Ljava/lang/String;Ljava/util/Properties;)I
+Lorg/apache/xml/serializer/SerializationHandler;->close()V
+Lorg/apache/xml/serializer/SerializationHandler;->flushPending()V
+Lorg/apache/xml/serializer/SerializationHandler;->setEscaping(Z)Z
+Lorg/apache/xml/serializer/SerializationHandler;->setIndentAmount(I)V
+Lorg/apache/xml/serializer/SerializationHandler;->setNamespaceMappings(Lorg/apache/xml/serializer/NamespaceMappings;)V
+Lorg/apache/xml/serializer/Serializer;->asContentHandler()Lorg/xml/sax/ContentHandler;
+Lorg/apache/xml/serializer/Serializer;->asDOMSerializer()Lorg/apache/xml/serializer/DOMSerializer;
+Lorg/apache/xml/serializer/Serializer;->getOutputFormat()Ljava/util/Properties;
+Lorg/apache/xml/serializer/Serializer;->getOutputStream()Ljava/io/OutputStream;
+Lorg/apache/xml/serializer/Serializer;->getWriter()Ljava/io/Writer;
+Lorg/apache/xml/serializer/Serializer;->reset()Z
+Lorg/apache/xml/serializer/Serializer;->setOutputFormat(Ljava/util/Properties;)V
+Lorg/apache/xml/serializer/Serializer;->setOutputStream(Ljava/io/OutputStream;)V
+Lorg/apache/xml/serializer/Serializer;->setWriter(Ljava/io/Writer;)V
+Lorg/apache/xml/serializer/SerializerBase;->fireCharEvent([CII)V
+Lorg/apache/xml/serializer/SerializerBase;->fireCommentEvent([CII)V
+Lorg/apache/xml/serializer/SerializerBase;->fireEndDoc()V
+Lorg/apache/xml/serializer/SerializerBase;->fireEndElem(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->fireEscapingEvent(Ljava/lang/String;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->getDoctypePublic()Ljava/lang/String;
+Lorg/apache/xml/serializer/SerializerBase;->getDoctypeSystem()Ljava/lang/String;
+Lorg/apache/xml/serializer/SerializerBase;->getEncoding()Ljava/lang/String;
+Lorg/apache/xml/serializer/SerializerBase;->getPrefixPart(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/serializer/SerializerBase;->getVersion()Ljava/lang/String;
+Lorg/apache/xml/serializer/SerializerBase;->m_attributes:Lorg/apache/xml/serializer/AttributesImplSerializer;
+Lorg/apache/xml/serializer/SerializerBase;->m_charsBuff:[C
+Lorg/apache/xml/serializer/SerializerBase;->m_elemContext:Lorg/apache/xml/serializer/ElemContext;
+Lorg/apache/xml/serializer/SerializerBase;->m_needToCallStartDocument:Z
+Lorg/apache/xml/serializer/SerializerBase;->m_tracer:Lorg/apache/xml/serializer/SerializerTrace;
+Lorg/apache/xml/serializer/SerializerBase;->setDoctypePublic(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->setDoctypeSystem(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->setIndent(Z)V
+Lorg/apache/xml/serializer/SerializerBase;->setMediaType(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->setOmitXMLDeclaration(Z)V
+Lorg/apache/xml/serializer/SerializerBase;->setStandalone(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->setStandaloneInternal(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerBase;->setVersion(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/SerializerFactory;->getSerializer(Ljava/util/Properties;)Lorg/apache/xml/serializer/Serializer;
+Lorg/apache/xml/serializer/SerializerTraceWriter;-><init>(Ljava/io/Writer;Lorg/apache/xml/serializer/SerializerTrace;)V
+Lorg/apache/xml/serializer/ToHTMLStream;-><init>()V
+Lorg/apache/xml/serializer/ToHTMLStream;->getElemDesc(Ljava/lang/String;)Lorg/apache/xml/serializer/ElemDesc;
+Lorg/apache/xml/serializer/ToSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Lorg/xml/sax/ext/LexicalHandler;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToSAXHandler;->m_lexHandler:Lorg/xml/sax/ext/LexicalHandler;
+Lorg/apache/xml/serializer/ToSAXHandler;->m_saxHandler:Lorg/xml/sax/ContentHandler;
+Lorg/apache/xml/serializer/ToSAXHandler;->reset()Z
+Lorg/apache/xml/serializer/ToSAXHandler;->startDocumentInternal()V
+Lorg/apache/xml/serializer/ToSAXHandler;->startElement(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToStream;->setCdataSectionElements(Ljava/lang/String;Ljava/util/Properties;)V
+Lorg/apache/xml/serializer/ToStream;->setEncoding(Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToStream;->setIndentAmount(I)V
+Lorg/apache/xml/serializer/ToTextSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToTextSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Lorg/xml/sax/ext/LexicalHandler;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToTextStream;-><init>()V
+Lorg/apache/xml/serializer/ToUnknownStream;-><init>()V
+Lorg/apache/xml/serializer/ToXMLSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToXMLSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Lorg/xml/sax/ext/LexicalHandler;Ljava/lang/String;)V
+Lorg/apache/xml/serializer/ToXMLStream;-><init>()V
+Lorg/apache/xml/serializer/WriterToASCI;-><init>(Ljava/io/OutputStream;)V
+Lorg/apache/xml/serializer/WriterToUTF8Buffered;-><init>(Ljava/io/OutputStream;)V
+Lorg/apache/xml/utils/DefaultErrorHandler;-><init>()V
+Lorg/apache/xml/utils/DefaultErrorHandler;->printLocation(Ljava/io/PrintWriter;Ljava/lang/Throwable;)V
+Lorg/apache/xml/utils/DOMHelper;->isNodeAfter(Lorg/w3c/dom/Node;Lorg/w3c/dom/Node;)Z
+Lorg/apache/xml/utils/DOMHelper;->isNodeTheSame(Lorg/w3c/dom/Node;Lorg/w3c/dom/Node;)Z
+Lorg/apache/xml/utils/FastStringBuffer;->append(Ljava/lang/String;)V
+Lorg/apache/xml/utils/FastStringBuffer;->getString(II)Ljava/lang/String;
+Lorg/apache/xml/utils/FastStringBuffer;->length()I
+Lorg/apache/xml/utils/IntStack;->peek()I
+Lorg/apache/xml/utils/ObjectVector;->elementAt(I)Ljava/lang/Object;
+Lorg/apache/xml/utils/ObjectVector;->size()I
+Lorg/apache/xml/utils/PrefixResolverDefault;-><init>(Lorg/w3c/dom/Node;)V
+Lorg/apache/xml/utils/PrefixResolverDefault;->getNamespaceForPrefix(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/utils/QName;-><init>(Ljava/lang/String;)V
+Lorg/apache/xml/utils/QName;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lorg/apache/xml/utils/QName;->getLocalName()Ljava/lang/String;
+Lorg/apache/xml/utils/SAXSourceLocator;-><init>(Lorg/xml/sax/SAXParseException;)V
+Lorg/apache/xml/utils/StringBufferPool;->free(Lorg/apache/xml/utils/FastStringBuffer;)V
+Lorg/apache/xml/utils/StringBufferPool;->get()Lorg/apache/xml/utils/FastStringBuffer;
+Lorg/apache/xml/utils/StringVector;->elementAt(I)Ljava/lang/String;
+Lorg/apache/xml/utils/StringVector;->size()I
+Lorg/apache/xml/utils/StylesheetPIHandler;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lorg/apache/xml/utils/StylesheetPIHandler;->getAssociatedStylesheet()Ljavax/xml/transform/Source;
+Lorg/apache/xml/utils/StylesheetPIHandler;->setBaseId(Ljava/lang/String;)V
+Lorg/apache/xml/utils/StylesheetPIHandler;->setURIResolver(Ljavax/xml/transform/URIResolver;)V
+Lorg/apache/xml/utils/SuballocatedIntVector;-><init>(I)V
+Lorg/apache/xml/utils/SuballocatedIntVector;->elementAt(I)I
+Lorg/apache/xml/utils/SuballocatedIntVector;->setElementAt(II)V
+Lorg/apache/xml/utils/SuballocatedIntVector;->size()I
+Lorg/apache/xml/utils/SystemIDResolver;->getAbsoluteURI(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/utils/SystemIDResolver;->getAbsoluteURI(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/utils/SystemIDResolver;->getAbsoluteURIFromRelative(Ljava/lang/String;)Ljava/lang/String;
+Lorg/apache/xml/utils/SystemIDResolver;->isAbsoluteURI(Ljava/lang/String;)Z
+Lorg/apache/xml/utils/URI$MalformedURIException;-><init>(Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;-><init>(Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;-><init>(Lorg/apache/xml/utils/URI;)V
+Lorg/apache/xml/utils/URI;-><init>(Lorg/apache/xml/utils/URI;Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;->getFragment()Ljava/lang/String;
+Lorg/apache/xml/utils/URI;->getHost()Ljava/lang/String;
+Lorg/apache/xml/utils/URI;->getPath()Ljava/lang/String;
+Lorg/apache/xml/utils/URI;->getPort()I
+Lorg/apache/xml/utils/URI;->getQueryString()Ljava/lang/String;
+Lorg/apache/xml/utils/URI;->getScheme()Ljava/lang/String;
+Lorg/apache/xml/utils/URI;->getUserinfo()Ljava/lang/String;
+Lorg/apache/xml/utils/URI;->setFragment(Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;->setHost(Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;->setPort(I)V
+Lorg/apache/xml/utils/URI;->setScheme(Ljava/lang/String;)V
+Lorg/apache/xml/utils/URI;->setUserinfo(Ljava/lang/String;)V
+Lorg/apache/xml/utils/WrappedRuntimeException;-><init>(Ljava/lang/Exception;)V
+Lorg/apache/xml/utils/WrappedRuntimeException;->getException()Ljava/lang/Exception;
+Lorg/apache/xml/utils/XML11Char;->isXML11ValidNCName(Ljava/lang/String;)Z
+Lorg/apache/xml/utils/XML11Char;->isXML11ValidQName(Ljava/lang/String;)Z
+Lorg/apache/xml/utils/XMLReaderManager;->getInstance()Lorg/apache/xml/utils/XMLReaderManager;
+Lorg/apache/xml/utils/XMLReaderManager;->getXMLReader()Lorg/xml/sax/XMLReader;
+Lorg/apache/xml/utils/XMLReaderManager;->releaseXMLReader(Lorg/xml/sax/XMLReader;)V
+Lorg/apache/xml/utils/XMLString;->dispatchCharactersEvents(Lorg/xml/sax/ContentHandler;)V
+Lorg/apache/xml/utils/XMLString;->equals(Lorg/apache/xml/utils/XMLString;)Z
+Lorg/apache/xml/utils/XMLString;->fixWhiteSpace(ZZZ)Lorg/apache/xml/utils/XMLString;
+Lorg/apache/xml/utils/XMLStringDefault;-><init>(Ljava/lang/String;)V
+Lorg/apache/xml/utils/XMLStringFactory;-><init>()V
+Lorg/apache/xml/utils/XMLStringFactory;->emptystr()Lorg/apache/xml/utils/XMLString;
+Lorg/apache/xml/utils/XMLStringFactory;->newstr(Ljava/lang/String;)Lorg/apache/xml/utils/XMLString;
+Lorg/apache/xpath/axes/ChildTestIterator;-><init>(Lorg/apache/xml/dtm/DTMAxisTraverser;)V
+Lorg/apache/xpath/axes/DescendantIterator;-><init>()V
+Lorg/apache/xpath/axes/LocPathIterator;->getDTM(I)Lorg/apache/xml/dtm/DTM;
+Lorg/apache/xpath/axes/LocPathIterator;->getPrefixResolver()Lorg/apache/xml/utils/PrefixResolver;
+Lorg/apache/xpath/axes/LocPathIterator;->getXPathContext()Lorg/apache/xpath/XPathContext;
+Lorg/apache/xpath/axes/NodeSequence;->getContainedIter()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xpath/axes/NodeSequence;->nextNode()I
+Lorg/apache/xpath/axes/OneStepIterator;-><init>(Lorg/apache/xml/dtm/DTMAxisIterator;I)V
+Lorg/apache/xpath/CachedXPathAPI;-><init>()V
+Lorg/apache/xpath/CachedXPathAPI;-><init>(Lorg/apache/xpath/CachedXPathAPI;)V
+Lorg/apache/xpath/CachedXPathAPI;->eval(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/apache/xpath/objects/XObject;
+Lorg/apache/xpath/CachedXPathAPI;->getXPathContext()Lorg/apache/xpath/XPathContext;
+Lorg/apache/xpath/CachedXPathAPI;->selectNodeList(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/CachedXPathAPI;->selectNodeList(Lorg/w3c/dom/Node;Ljava/lang/String;Lorg/w3c/dom/Node;)Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/CachedXPathAPI;->selectSingleNode(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/w3c/dom/Node;
+Lorg/apache/xpath/CachedXPathAPI;->selectSingleNode(Lorg/w3c/dom/Node;Ljava/lang/String;Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node;
+Lorg/apache/xpath/compiler/FunctionTable;-><init>()V
+Lorg/apache/xpath/compiler/FunctionTable;->installFunction(Ljava/lang/String;Ljava/lang/Class;)I
+Lorg/apache/xpath/Expression;->assertion(ZLjava/lang/String;)V
+Lorg/apache/xpath/Expression;->error(Lorg/apache/xpath/XPathContext;Ljava/lang/String;[Ljava/lang/Object;)V
+Lorg/apache/xpath/Expression;->exprGetParent()Lorg/apache/xpath/ExpressionNode;
+Lorg/apache/xpath/ExpressionNode;->exprGetParent()Lorg/apache/xpath/ExpressionNode;
+Lorg/apache/xpath/functions/FuncCurrent;-><init>()V
+Lorg/apache/xpath/functions/FuncExtFunction;->getFunctionName()Ljava/lang/String;
+Lorg/apache/xpath/functions/FuncExtFunction;->getMethodKey()Ljava/lang/Object;
+Lorg/apache/xpath/functions/Function;-><init>()V
+Lorg/apache/xpath/functions/WrongNumberArgsException;-><init>(Ljava/lang/String;)V
+Lorg/apache/xpath/NodeSet;-><init>()V
+Lorg/apache/xpath/NodeSet;-><init>(Lorg/w3c/dom/Node;)V
+Lorg/apache/xpath/NodeSet;-><init>(Lorg/w3c/dom/NodeList;)V
+Lorg/apache/xpath/NodeSet;-><init>(Lorg/w3c/dom/traversal/NodeIterator;)V
+Lorg/apache/xpath/NodeSet;->addElement(Lorg/w3c/dom/Node;)V
+Lorg/apache/xpath/NodeSet;->addNode(Lorg/w3c/dom/Node;)V
+Lorg/apache/xpath/NodeSet;->contains(Lorg/w3c/dom/Node;)Z
+Lorg/apache/xpath/NodeSet;->elementAt(I)Lorg/w3c/dom/Node;
+Lorg/apache/xpath/NodeSet;->setShouldCacheNodes(Z)V
+Lorg/apache/xpath/NodeSetDTM;-><init>(Lorg/w3c/dom/NodeList;Lorg/apache/xpath/XPathContext;)V
+Lorg/apache/xpath/NodeSetDTM;-><init>(Lorg/w3c/dom/traversal/NodeIterator;Lorg/apache/xpath/XPathContext;)V
+Lorg/apache/xpath/NodeSetDTM;->addNode(I)V
+Lorg/apache/xpath/NodeSetDTM;->detach()V
+Lorg/apache/xpath/NodeSetDTM;->getLength()I
+Lorg/apache/xpath/NodeSetDTM;->item(I)I
+Lorg/apache/xpath/objects/XBoolean;-><init>(Z)V
+Lorg/apache/xpath/objects/XBoolean;->bool()Z
+Lorg/apache/xpath/objects/XBoolean;->str()Ljava/lang/String;
+Lorg/apache/xpath/objects/XBooleanStatic;-><init>(Z)V
+Lorg/apache/xpath/objects/XNodeSet;-><init>(ILorg/apache/xml/dtm/DTMManager;)V
+Lorg/apache/xpath/objects/XNodeSet;-><init>(Lorg/apache/xml/dtm/DTMIterator;)V
+Lorg/apache/xpath/objects/XNodeSet;-><init>(Lorg/apache/xml/dtm/DTMManager;)V
+Lorg/apache/xpath/objects/XNodeSet;->iterRaw()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xpath/objects/XNodeSet;->mutableNodeset()Lorg/apache/xpath/NodeSetDTM;
+Lorg/apache/xpath/objects/XNodeSet;->nodelist()Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/objects/XNumber;-><init>(D)V
+Lorg/apache/xpath/objects/XNumber;->num()D
+Lorg/apache/xpath/objects/XNumber;->str()Ljava/lang/String;
+Lorg/apache/xpath/objects/XObject;->bool()Z
+Lorg/apache/xpath/objects/XObject;->create(Ljava/lang/Object;)Lorg/apache/xpath/objects/XObject;
+Lorg/apache/xpath/objects/XObject;->getType()I
+Lorg/apache/xpath/objects/XObject;->getTypeString()Ljava/lang/String;
+Lorg/apache/xpath/objects/XObject;->iter()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xpath/objects/XObject;->nodelist()Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/objects/XObject;->nodeset()Lorg/w3c/dom/traversal/NodeIterator;
+Lorg/apache/xpath/objects/XObject;->num()D
+Lorg/apache/xpath/objects/XObject;->object()Ljava/lang/Object;
+Lorg/apache/xpath/objects/XObject;->str()Ljava/lang/String;
+Lorg/apache/xpath/objects/XObject;->xstr()Lorg/apache/xml/utils/XMLString;
+Lorg/apache/xpath/objects/XRTreeFrag;-><init>(ILorg/apache/xpath/XPathContext;)V
+Lorg/apache/xpath/objects/XRTreeFrag;->asNodeIterator()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xpath/objects/XRTreeFrag;->convertToNodeset()Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/objects/XString;-><init>(Ljava/lang/String;)V
+Lorg/apache/xpath/objects/XString;->num()D
+Lorg/apache/xpath/patterns/NodeTest;->setWhatToShow(I)V
+Lorg/apache/xpath/res/XPATHErrorResources;-><init>()V
+Lorg/apache/xpath/res/XPATHMessages;->createXPATHMessage(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
+Lorg/apache/xpath/XPath;-><init>(Ljava/lang/String;Ljavax/xml/transform/SourceLocator;Lorg/apache/xml/utils/PrefixResolver;I)V
+Lorg/apache/xpath/XPath;-><init>(Ljava/lang/String;Ljavax/xml/transform/SourceLocator;Lorg/apache/xml/utils/PrefixResolver;ILjavax/xml/transform/ErrorListener;)V
+Lorg/apache/xpath/XPath;->execute(Lorg/apache/xpath/XPathContext;ILorg/apache/xml/utils/PrefixResolver;)Lorg/apache/xpath/objects/XObject;
+Lorg/apache/xpath/XPath;->execute(Lorg/apache/xpath/XPathContext;Lorg/w3c/dom/Node;Lorg/apache/xml/utils/PrefixResolver;)Lorg/apache/xpath/objects/XObject;
+Lorg/apache/xpath/XPath;->getPatternString()Ljava/lang/String;
+Lorg/apache/xpath/XPathAPI;->selectNodeList(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/XPathAPI;->selectNodeList(Lorg/w3c/dom/Node;Ljava/lang/String;Lorg/w3c/dom/Node;)Lorg/w3c/dom/NodeList;
+Lorg/apache/xpath/XPathAPI;->selectSingleNode(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/w3c/dom/Node;
+Lorg/apache/xpath/XPathAPI;->selectSingleNode(Lorg/w3c/dom/Node;Ljava/lang/String;Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node;
+Lorg/apache/xpath/XPathContext$XPathExpressionContext;->getDTMManager()Lorg/apache/xml/dtm/DTMManager;
+Lorg/apache/xpath/XPathContext$XPathExpressionContext;->getXPathContext()Lorg/apache/xpath/XPathContext;
+Lorg/apache/xpath/XPathContext;-><init>()V
+Lorg/apache/xpath/XPathContext;-><init>(Ljava/lang/Object;)V
+Lorg/apache/xpath/XPathContext;->getAxesIteratorStackStacks()Ljava/util/Stack;
+Lorg/apache/xpath/XPathContext;->getContextNodeList()Lorg/apache/xml/dtm/DTMIterator;
+Lorg/apache/xpath/XPathContext;->getContextNodeListsStack()Ljava/util/Stack;
+Lorg/apache/xpath/XPathContext;->getCurrentExpressionNodeStack()Lorg/apache/xml/utils/IntStack;
+Lorg/apache/xpath/XPathContext;->getCurrentNode()I
+Lorg/apache/xpath/XPathContext;->getCurrentNodeStack()Lorg/apache/xml/utils/IntStack;
+Lorg/apache/xpath/XPathContext;->getDTM(I)Lorg/apache/xml/dtm/DTM;
+Lorg/apache/xpath/XPathContext;->getDTMHandleFromNode(Lorg/w3c/dom/Node;)I
+Lorg/apache/xpath/XPathContext;->getDTMManager()Lorg/apache/xml/dtm/DTMManager;
+Lorg/apache/xpath/XPathContext;->getExpressionContext()Lorg/apache/xalan/extensions/ExpressionContext;
+Lorg/apache/xpath/XPathContext;->getNamespaceContext()Lorg/apache/xml/utils/PrefixResolver;
+Lorg/apache/xpath/XPathContext;->getOwnerObject()Ljava/lang/Object;
+Lorg/apache/xpath/XPathContext;->getSAXLocator()Ljavax/xml/transform/SourceLocator;
+Lorg/apache/xpath/XPathContext;->getVarStack()Lorg/apache/xpath/VariableStack;
+Lorg/apache/xpath/XPathContext;->m_dtmManager:Lorg/apache/xml/dtm/DTMManager;
+Lorg/apache/xpath/XPathContext;->popContextNodeList()V
+Lorg/apache/xpath/XPathContext;->popCurrentNode()V
+Lorg/apache/xpath/XPathContext;->pushContextNodeList(Lorg/apache/xml/dtm/DTMIterator;)V
+Lorg/apache/xpath/XPathContext;->pushCurrentNode(I)V
+Lorg/apache/xpath/XPathContext;->reset()V
+Lorg/apache/xpath/XPathContext;->setAxesIteratorStackStacks(Ljava/util/Stack;)V
+Lorg/apache/xpath/XPathContext;->setContextNodeListsStack(Ljava/util/Stack;)V
+Lorg/apache/xpath/XPathContext;->setCurrentExpressionNodeStack(Lorg/apache/xml/utils/IntStack;)V
+Lorg/apache/xpath/XPathContext;->setCurrentNodeStack(Lorg/apache/xml/utils/IntStack;)V
+Lorg/apache/xpath/XPathContext;->setSecureProcessing(Z)V
+Lorg/apache/xpath/XPathContext;->setVarStack(Lorg/apache/xpath/VariableStack;)V
+Lorg/ccil/cowan/tagsoup/AttributesImpl;-><init>(Lorg/xml/sax/Attributes;)V
+Lorg/ccil/cowan/tagsoup/AttributesImpl;->addAttribute(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
 Lorg/ccil/cowan/tagsoup/AttributesImpl;->data:[Ljava/lang/String;
 Lorg/ccil/cowan/tagsoup/AttributesImpl;->length:I
+Lorg/ccil/cowan/tagsoup/AttributesImpl;->setAttribute(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lorg/ccil/cowan/tagsoup/AttributesImpl;->setValue(ILjava/lang/String;)V
+Lorg/ccil/cowan/tagsoup/AutoDetector;->autoDetectingReader(Ljava/io/InputStream;)Ljava/io/Reader;
+Lorg/ccil/cowan/tagsoup/Element;-><init>(Lorg/ccil/cowan/tagsoup/ElementType;Z)V
+Lorg/ccil/cowan/tagsoup/Element;->anonymize()V
+Lorg/ccil/cowan/tagsoup/Element;->atts()Lorg/ccil/cowan/tagsoup/AttributesImpl;
+Lorg/ccil/cowan/tagsoup/Element;->canContain(Lorg/ccil/cowan/tagsoup/Element;)Z
+Lorg/ccil/cowan/tagsoup/Element;->clean()V
+Lorg/ccil/cowan/tagsoup/Element;->flags()I
+Lorg/ccil/cowan/tagsoup/Element;->localName()Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Element;->name()Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Element;->namespace()Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Element;->next()Lorg/ccil/cowan/tagsoup/Element;
+Lorg/ccil/cowan/tagsoup/Element;->parent()Lorg/ccil/cowan/tagsoup/ElementType;
+Lorg/ccil/cowan/tagsoup/Element;->preclosed:Z
+Lorg/ccil/cowan/tagsoup/Element;->setAttribute(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lorg/ccil/cowan/tagsoup/Element;->setNext(Lorg/ccil/cowan/tagsoup/Element;)V
+Lorg/ccil/cowan/tagsoup/Element;->theAtts:Lorg/ccil/cowan/tagsoup/AttributesImpl;
+Lorg/ccil/cowan/tagsoup/Element;->theNext:Lorg/ccil/cowan/tagsoup/Element;
+Lorg/ccil/cowan/tagsoup/Element;->theType:Lorg/ccil/cowan/tagsoup/ElementType;
+Lorg/ccil/cowan/tagsoup/ElementType;-><init>(Ljava/lang/String;IIILorg/ccil/cowan/tagsoup/Schema;)V
+Lorg/ccil/cowan/tagsoup/ElementType;->atts()Lorg/ccil/cowan/tagsoup/AttributesImpl;
+Lorg/ccil/cowan/tagsoup/ElementType;->setAttribute(Lorg/ccil/cowan/tagsoup/AttributesImpl;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
 Lorg/ccil/cowan/tagsoup/ElementType;->theAtts:Lorg/ccil/cowan/tagsoup/AttributesImpl;
 Lorg/ccil/cowan/tagsoup/ElementType;->theFlags:I
 Lorg/ccil/cowan/tagsoup/ElementType;->theLocalName:Ljava/lang/String;
@@ -2292,10 +5437,500 @@
 Lorg/ccil/cowan/tagsoup/ElementType;->theNamespace:Ljava/lang/String;
 Lorg/ccil/cowan/tagsoup/ElementType;->theParent:Lorg/ccil/cowan/tagsoup/ElementType;
 Lorg/ccil/cowan/tagsoup/ElementType;->theSchema:Lorg/ccil/cowan/tagsoup/Schema;
+Lorg/ccil/cowan/tagsoup/HTMLScanner;-><init>()V
 Lorg/ccil/cowan/tagsoup/HTMLSchema;-><init>()V
+Lorg/ccil/cowan/tagsoup/jaxp/SAXFactoryImpl;-><init>()V
+Lorg/ccil/cowan/tagsoup/jaxp/SAXParserImpl;-><init>()V
+Lorg/ccil/cowan/tagsoup/jaxp/SAXParserImpl;->newInstance(Ljava/util/Map;)Lorg/ccil/cowan/tagsoup/jaxp/SAXParserImpl;
 Lorg/ccil/cowan/tagsoup/Parser;-><init>()V
+Lorg/ccil/cowan/tagsoup/Parser;->bogonsEmpty:Z
+Lorg/ccil/cowan/tagsoup/Parser;->CDATAElements:Z
+Lorg/ccil/cowan/tagsoup/Parser;->cleanPublicid(Ljava/lang/String;)Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->defaultAttributes:Z
+Lorg/ccil/cowan/tagsoup/Parser;->etagchars:[C
+Lorg/ccil/cowan/tagsoup/Parser;->expandEntities(Ljava/lang/String;)Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->getInputStream(Ljava/lang/String;Ljava/lang/String;)Ljava/io/InputStream;
+Lorg/ccil/cowan/tagsoup/Parser;->ignorableWhitespace:Z
+Lorg/ccil/cowan/tagsoup/Parser;->ignoreBogons:Z
+Lorg/ccil/cowan/tagsoup/Parser;->lookupEntity([CII)I
+Lorg/ccil/cowan/tagsoup/Parser;->makeName([CII)Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->pop()V
+Lorg/ccil/cowan/tagsoup/Parser;->push(Lorg/ccil/cowan/tagsoup/Element;)V
+Lorg/ccil/cowan/tagsoup/Parser;->rectify(Lorg/ccil/cowan/tagsoup/Element;)V
+Lorg/ccil/cowan/tagsoup/Parser;->restart(Lorg/ccil/cowan/tagsoup/Element;)V
+Lorg/ccil/cowan/tagsoup/Parser;->restartablyPop()V
+Lorg/ccil/cowan/tagsoup/Parser;->rootBogons:Z
+Lorg/ccil/cowan/tagsoup/Parser;->schemaProperty:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->split(Ljava/lang/String;)[Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->theAttributeName:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->theAutoDetector:Lorg/ccil/cowan/tagsoup/AutoDetector;
+Lorg/ccil/cowan/tagsoup/Parser;->theContentHandler:Lorg/xml/sax/ContentHandler;
+Lorg/ccil/cowan/tagsoup/Parser;->theDoctypeIsPresent:Z
+Lorg/ccil/cowan/tagsoup/Parser;->theDoctypeSystemId:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->theFeatures:Ljava/util/HashMap;
+Lorg/ccil/cowan/tagsoup/Parser;->theLexicalHandler:Lorg/xml/sax/ext/LexicalHandler;
+Lorg/ccil/cowan/tagsoup/Parser;->theNewElement:Lorg/ccil/cowan/tagsoup/Element;
+Lorg/ccil/cowan/tagsoup/Parser;->thePCDATA:Lorg/ccil/cowan/tagsoup/Element;
+Lorg/ccil/cowan/tagsoup/Parser;->thePITarget:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->theSaved:Lorg/ccil/cowan/tagsoup/Element;
+Lorg/ccil/cowan/tagsoup/Parser;->theScanner:Lorg/ccil/cowan/tagsoup/Scanner;
+Lorg/ccil/cowan/tagsoup/Parser;->theSchema:Lorg/ccil/cowan/tagsoup/Schema;
+Lorg/ccil/cowan/tagsoup/Parser;->theStack:Lorg/ccil/cowan/tagsoup/Element;
+Lorg/ccil/cowan/tagsoup/Parser;->trimquotes(Ljava/lang/String;)Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Parser;->virginStack:Z
+Lorg/ccil/cowan/tagsoup/PYXScanner;-><init>()V
+Lorg/ccil/cowan/tagsoup/PYXWriter;-><init>(Ljava/io/Writer;)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->aname([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->aval([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->entity([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->eof([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->etag([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->gi([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->pcdata([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->pi([CII)V
+Lorg/ccil/cowan/tagsoup/ScanHandler;->stagc([CII)V
+Lorg/ccil/cowan/tagsoup/Scanner;->startCDATA()V
+Lorg/ccil/cowan/tagsoup/Schema;->elementType(Ljava/lang/String;III)V
+Lorg/ccil/cowan/tagsoup/Schema;->getElementType(Ljava/lang/String;)Lorg/ccil/cowan/tagsoup/ElementType;
+Lorg/ccil/cowan/tagsoup/Schema;->getEntity(Ljava/lang/String;)I
+Lorg/ccil/cowan/tagsoup/Schema;->getPrefix()Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Schema;->getURI()Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/Schema;->parent(Ljava/lang/String;Ljava/lang/String;)V
 Lorg/ccil/cowan/tagsoup/Schema;->theElementTypes:Ljava/util/HashMap;
 Lorg/ccil/cowan/tagsoup/Schema;->theEntities:Ljava/util/HashMap;
 Lorg/ccil/cowan/tagsoup/Schema;->thePrefix:Ljava/lang/String;
 Lorg/ccil/cowan/tagsoup/Schema;->theRoot:Lorg/ccil/cowan/tagsoup/ElementType;
 Lorg/ccil/cowan/tagsoup/Schema;->theURI:Ljava/lang/String;
+Lorg/ccil/cowan/tagsoup/XMLWriter;-><init>(Ljava/io/Writer;)V
+Lorg/ccil/cowan/tagsoup/XMLWriter;->htmlMode:Z
+Lorg/ccil/cowan/tagsoup/XMLWriter;->setOutput(Ljava/io/Writer;)V
+Lorg/ccil/cowan/tagsoup/XMLWriter;->setOutputProperty(Ljava/lang/String;Ljava/lang/String;)V
+Lorg/ccil/cowan/tagsoup/XMLWriter;->setPrefix(Ljava/lang/String;Ljava/lang/String;)V
+Lorg/xml/sax/helpers/NamespaceSupport$Context;-><init>(Lorg/xml/sax/helpers/NamespaceSupport;)V
+Lorg/xml/sax/helpers/ParserAdapter$AttributeListAdapter;-><init>(Lorg/xml/sax/helpers/ParserAdapter;)V
+Lsun/misc/ASCIICaseInsensitiveComparator;->CASE_INSENSITIVE_ORDER:Ljava/util/Comparator;
+Lsun/misc/ASCIICaseInsensitiveComparator;->lowerCaseHashCode(Ljava/lang/String;)I
+Lsun/misc/BASE64Decoder;-><init>()V
+Lsun/misc/BASE64Decoder;->pem_convert_array:[B
+Lsun/misc/BASE64Encoder;-><init>()V
+Lsun/misc/BASE64Encoder;->pem_array:[C
+Lsun/misc/CEFormatException;-><init>(Ljava/lang/String;)V
+Lsun/misc/CEStreamExhausted;-><init>()V
+Lsun/misc/CharacterDecoder;-><init>()V
+Lsun/misc/CharacterEncoder;-><init>()V
+Lsun/misc/CharacterEncoder;->encodeBuffer([B)Ljava/lang/String;
+Lsun/misc/CharacterEncoder;->encodeBufferPrefix(Ljava/io/OutputStream;)V
+Lsun/misc/CharacterEncoder;->pStream:Ljava/io/PrintStream;
+Lsun/misc/Cleaner;->create(Ljava/lang/Object;Ljava/lang/Runnable;)Lsun/misc/Cleaner;
+Lsun/misc/FloatingDecimal;->$assertionsDisabled:Z
+Lsun/misc/FloatingDecimal;->getHexDigit(Ljava/lang/String;I)I
+Lsun/misc/FloatingDecimal;->stripLeadingZeros(Ljava/lang/String;)Ljava/lang/String;
+Lsun/misc/FormattedFloatingDecimal$Form;->COMPATIBLE:Lsun/misc/FormattedFloatingDecimal$Form;
+Lsun/misc/FormattedFloatingDecimal$Form;->DECIMAL_FLOAT:Lsun/misc/FormattedFloatingDecimal$Form;
+Lsun/misc/FormattedFloatingDecimal$Form;->SCIENTIFIC:Lsun/misc/FormattedFloatingDecimal$Form;
+Lsun/misc/FormattedFloatingDecimal;->$assertionsDisabled:Z
+Lsun/misc/FpUtils;->$assertionsDisabled:Z
+Lsun/misc/FpUtils;->rawCopySign(DD)D
+Lsun/misc/HexDumpEncoder;-><init>()V
+Lsun/misc/HexDumpEncoder;->currentByte:I
+Lsun/misc/HexDumpEncoder;->offset:I
+Lsun/misc/HexDumpEncoder;->thisLine:[B
+Lsun/misc/HexDumpEncoder;->thisLineLength:I
+Lsun/misc/IOUtils;->readFully(Ljava/io/InputStream;IZ)[B
+Lsun/misc/JarIndex;-><init>([Ljava/lang/String;)V
+Lsun/misc/JarIndex;->write(Ljava/io/OutputStream;)V
+Lsun/misc/MessageUtils;-><init>()V
+Lsun/misc/MetaIndex;->forJar(Ljava/io/File;)Lsun/misc/MetaIndex;
+Lsun/misc/MetaIndex;->registerDirectory(Ljava/io/File;)V
+Lsun/misc/VM;->maxDirectMemory()J
+Lsun/net/ftp/FtpClient;-><init>()V
+Lsun/net/util/IPAddressUtil;->isIPv4LiteralAddress(Ljava/lang/String;)Z
+Lsun/net/util/IPAddressUtil;->isIPv6LiteralAddress(Ljava/lang/String;)Z
+Lsun/net/www/MessageHeader;-><init>()V
+Lsun/net/www/MessageHeader;-><init>(Ljava/io/InputStream;)V
+Lsun/net/www/MessageHeader;->add(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/net/www/MessageHeader;->findValue(Ljava/lang/String;)Ljava/lang/String;
+Lsun/net/www/MessageHeader;->prepend(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/net/www/MessageHeader;->print(Ljava/io/PrintStream;)V
+Lsun/net/www/MessageHeader;->set(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/net/www/ParseUtil;->decode(Ljava/lang/String;)Ljava/lang/String;
+Lsun/net/www/ParseUtil;->encodePath(Ljava/lang/String;Z)Ljava/lang/String;
+Lsun/net/www/ParseUtil;->fileToEncodedURL(Ljava/io/File;)Ljava/net/URL;
+Lsun/net/www/URLConnection;-><init>(Ljava/net/URL;)V
+Lsun/net/www/URLConnection;->setProperties(Lsun/net/www/MessageHeader;)V
+Lsun/nio/ch/DirectBuffer;->address()J
+Lsun/nio/ch/FileChannelImpl;->unmap0(JJ)I
+Lsun/nio/ch/SelectorImpl;->publicSelectedKeys:Ljava/util/Set;
+Lsun/nio/ch/SelectorImpl;->selectedKeys:Ljava/util/Set;
+Lsun/nio/cs/HistoricallyNamedCharset;->historicalName()Ljava/lang/String;
+Lsun/nio/cs/ThreadLocalCoders;->decoderFor(Ljava/lang/Object;)Ljava/nio/charset/CharsetDecoder;
+Lsun/nio/fs/BasicFileAttributesHolder;->get()Ljava/nio/file/attribute/BasicFileAttributes;
+Lsun/reflect/misc/ReflectUtil;->checkPackageAccess(Ljava/lang/Class;)V
+Lsun/reflect/misc/ReflectUtil;->checkPackageAccess(Ljava/lang/String;)V
+Lsun/reflect/misc/ReflectUtil;->isPackageAccessible(Ljava/lang/Class;)Z
+Lsun/reflect/misc/ReflectUtil;->isSubclassOf(Ljava/lang/Class;Ljava/lang/Class;)Z
+Lsun/reflect/Reflection;->ensureMemberAccess(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;I)V
+Lsun/reflect/Reflection;->isSubclassOf(Ljava/lang/Class;Ljava/lang/Class;)Z
+Lsun/security/action/GetBooleanAction;-><init>(Ljava/lang/String;)V
+Lsun/security/action/GetIntegerAction;-><init>(Ljava/lang/String;I)V
+Lsun/security/action/GetPropertyAction;-><init>(Ljava/lang/String;)V
+Lsun/security/action/GetPropertyAction;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/security/jca/GetInstance$Instance;->impl:Ljava/lang/Object;
+Lsun/security/jca/GetInstance$Instance;->provider:Ljava/security/Provider;
+Lsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Lsun/security/jca/GetInstance$Instance;
+Lsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;)Lsun/security/jca/GetInstance$Instance;
+Lsun/security/jca/GetInstance;->getInstance(Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/Object;Ljava/security/Provider;)Lsun/security/jca/GetInstance$Instance;
+Lsun/security/jca/JCAUtil;->getSecureRandom()Ljava/security/SecureRandom;
+Lsun/security/jca/ProviderConfig;->argument:Ljava/lang/String;
+Lsun/security/jca/ProviderConfig;->CL_STRING:[Ljava/lang/Class;
+Lsun/security/jca/ProviderConfig;->disableLoad()V
+Lsun/security/jca/ProviderConfig;->hasArgument()Z
+Lsun/security/jca/ProviderList;->getService(Ljava/lang/String;Ljava/lang/String;)Ljava/security/Provider$Service;
+Lsun/security/jca/Providers;->getProviderList()Lsun/security/jca/ProviderList;
+Lsun/security/jca/Providers;->startJarVerification()Ljava/lang/Object;
+Lsun/security/jca/Providers;->stopJarVerification(Ljava/lang/Object;)V
+Lsun/security/pkcs/ContentInfo;-><init>(Lsun/security/util/ObjectIdentifier;Lsun/security/util/DerValue;)V
+Lsun/security/pkcs/ContentInfo;-><init>([B)V
+Lsun/security/pkcs/ContentInfo;->DATA_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/ContentInfo;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/pkcs/ContentInfo;->getData()[B
+Lsun/security/pkcs/ParsingException;-><init>(Ljava/lang/String;)V
+Lsun/security/pkcs/PKCS7;-><init>([B)V
+Lsun/security/pkcs/PKCS7;-><init>([Lsun/security/x509/AlgorithmId;Lsun/security/pkcs/ContentInfo;[Ljava/security/cert/X509Certificate;[Ljava/security/cert/X509CRL;[Lsun/security/pkcs/SignerInfo;)V
+Lsun/security/pkcs/PKCS7;-><init>([Lsun/security/x509/AlgorithmId;Lsun/security/pkcs/ContentInfo;[Ljava/security/cert/X509Certificate;[Lsun/security/pkcs/SignerInfo;)V
+Lsun/security/pkcs/PKCS7;->encodeSignedData(Ljava/io/OutputStream;)V
+Lsun/security/pkcs/PKCS7;->getCertificates()[Ljava/security/cert/X509Certificate;
+Lsun/security/pkcs/PKCS7;->getContentInfo()Lsun/security/pkcs/ContentInfo;
+Lsun/security/pkcs/PKCS7;->getSignerInfos()[Lsun/security/pkcs/SignerInfo;
+Lsun/security/pkcs/PKCS7;->verify(Lsun/security/pkcs/SignerInfo;[B)Lsun/security/pkcs/SignerInfo;
+Lsun/security/pkcs/PKCS7;->verify([B)[Lsun/security/pkcs/SignerInfo;
+Lsun/security/pkcs/PKCS8Key;-><init>()V
+Lsun/security/pkcs/PKCS8Key;->algid:Lsun/security/x509/AlgorithmId;
+Lsun/security/pkcs/PKCS8Key;->encodedKey:[B
+Lsun/security/pkcs/PKCS8Key;->key:[B
+Lsun/security/pkcs/PKCS9Attribute;-><init>(Ljava/lang/String;Ljava/lang/Object;)V
+Lsun/security/pkcs/PKCS9Attribute;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/pkcs/PKCS9Attribute;-><init>(Lsun/security/util/ObjectIdentifier;Ljava/lang/Object;)V
+Lsun/security/pkcs/PKCS9Attribute;->CONTENT_TYPE_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS9Attribute;->derEncode(Ljava/io/OutputStream;)V
+Lsun/security/pkcs/PKCS9Attribute;->EMAIL_ADDRESS_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS9Attribute;->getOID()Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS9Attribute;->getValue()Ljava/lang/Object;
+Lsun/security/pkcs/PKCS9Attribute;->MESSAGE_DIGEST_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS9Attribute;->SIGNING_TIME_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/pkcs/PKCS9Attributes;-><init>(Lsun/security/util/DerInputStream;)V
+Lsun/security/pkcs/PKCS9Attributes;-><init>(Lsun/security/util/DerInputStream;Z)V
+Lsun/security/pkcs/PKCS9Attributes;-><init>([Lsun/security/pkcs/PKCS9Attribute;)V
+Lsun/security/pkcs/PKCS9Attributes;->encode(BLjava/io/OutputStream;)V
+Lsun/security/pkcs/PKCS9Attributes;->getAttribute(Ljava/lang/String;)Lsun/security/pkcs/PKCS9Attribute;
+Lsun/security/pkcs/PKCS9Attributes;->getAttributeValue(Lsun/security/util/ObjectIdentifier;)Ljava/lang/Object;
+Lsun/security/pkcs/PKCS9Attributes;->getDerEncoding()[B
+Lsun/security/pkcs/SignerInfo;-><init>(Lsun/security/x509/X500Name;Ljava/math/BigInteger;Lsun/security/x509/AlgorithmId;Lsun/security/pkcs/PKCS9Attributes;Lsun/security/x509/AlgorithmId;[BLsun/security/pkcs/PKCS9Attributes;)V
+Lsun/security/pkcs/SignerInfo;-><init>(Lsun/security/x509/X500Name;Ljava/math/BigInteger;Lsun/security/x509/AlgorithmId;Lsun/security/x509/AlgorithmId;[B)V
+Lsun/security/pkcs/SignerInfo;->getCertificate(Lsun/security/pkcs/PKCS7;)Ljava/security/cert/X509Certificate;
+Lsun/security/pkcs/SignerInfo;->getCertificateChain(Lsun/security/pkcs/PKCS7;)Ljava/util/ArrayList;
+Lsun/security/pkcs/SignerInfo;->getDigestAlgorithmId()Lsun/security/x509/AlgorithmId;
+Lsun/security/pkcs/SignerInfo;->getDigestEncryptionAlgorithmId()Lsun/security/x509/AlgorithmId;
+Lsun/security/pkcs/SignerInfo;->getEncryptedDigest()[B
+Lsun/security/provider/certpath/X509CertificatePair;->clearCache()V
+Lsun/security/provider/certpath/X509CertPath;-><init>(Ljava/io/InputStream;)V
+Lsun/security/provider/certpath/X509CertPath;-><init>(Ljava/io/InputStream;Ljava/lang/String;)V
+Lsun/security/provider/certpath/X509CertPath;-><init>(Ljava/util/List;)V
+Lsun/security/provider/certpath/X509CertPath;->certs:Ljava/util/List;
+Lsun/security/provider/certpath/X509CertPath;->getEncodingsStatic()Ljava/util/Iterator;
+Lsun/security/provider/X509Factory;->addToCache(Lsun/security/util/Cache;[BLjava/lang/Object;)V
+Lsun/security/provider/X509Factory;->certCache:Lsun/security/util/Cache;
+Lsun/security/provider/X509Factory;->crlCache:Lsun/security/util/Cache;
+Lsun/security/provider/X509Factory;->getFromCache(Lsun/security/util/Cache;[B)Ljava/lang/Object;
+Lsun/security/provider/X509Factory;->intern(Ljava/security/cert/X509Certificate;)Lsun/security/x509/X509CertImpl;
+Lsun/security/provider/X509Factory;->intern(Ljava/security/cert/X509CRL;)Lsun/security/x509/X509CRLImpl;
+Lsun/security/timestamp/TimestampToken;-><init>([B)V
+Lsun/security/timestamp/TimestampToken;->getDate()Ljava/util/Date;
+Lsun/security/timestamp/TimestampToken;->getHashAlgorithm()Lsun/security/x509/AlgorithmId;
+Lsun/security/timestamp/TimestampToken;->getHashedMessage()[B
+Lsun/security/timestamp/TimestampToken;->getNonce()Ljava/math/BigInteger;
+Lsun/security/util/BitArray;-><init>(I[B)V
+Lsun/security/util/BitArray;->toByteArray()[B
+Lsun/security/util/Cache;-><init>()V
+Lsun/security/util/Cache;->clear()V
+Lsun/security/util/Cache;->get(Ljava/lang/Object;)Ljava/lang/Object;
+Lsun/security/util/Cache;->newHardMemoryCache(I)Lsun/security/util/Cache;
+Lsun/security/util/Cache;->put(Ljava/lang/Object;Ljava/lang/Object;)V
+Lsun/security/util/Debug;->getInstance(Ljava/lang/String;)Lsun/security/util/Debug;
+Lsun/security/util/Debug;->println()V
+Lsun/security/util/Debug;->println(Ljava/lang/String;)V
+Lsun/security/util/Debug;->toHexString(Ljava/math/BigInteger;)Ljava/lang/String;
+Lsun/security/util/DerIndefLenConverter;-><init>()V
+Lsun/security/util/DerIndefLenConverter;->convert([B)[B
+Lsun/security/util/DerIndefLenConverter;->data:[B
+Lsun/security/util/DerIndefLenConverter;->dataPos:I
+Lsun/security/util/DerIndefLenConverter;->dataSize:I
+Lsun/security/util/DerIndefLenConverter;->isIndefinite(I)Z
+Lsun/security/util/DerIndefLenConverter;->newData:[B
+Lsun/security/util/DerIndefLenConverter;->numOfTotalLenBytes:I
+Lsun/security/util/DerIndefLenConverter;->parseLength()I
+Lsun/security/util/DerIndefLenConverter;->parseTag()V
+Lsun/security/util/DerIndefLenConverter;->parseValue(I)V
+Lsun/security/util/DerIndefLenConverter;->writeLengthAndValue()V
+Lsun/security/util/DerIndefLenConverter;->writeTag()V
+Lsun/security/util/DerInputStream;-><init>([B)V
+Lsun/security/util/DerInputStream;->available()I
+Lsun/security/util/DerInputStream;->getBigInteger()Ljava/math/BigInteger;
+Lsun/security/util/DerInputStream;->getBitString()[B
+Lsun/security/util/DerInputStream;->getDerValue()Lsun/security/util/DerValue;
+Lsun/security/util/DerInputStream;->getInteger()I
+Lsun/security/util/DerInputStream;->getOctetString()[B
+Lsun/security/util/DerInputStream;->getOID()Lsun/security/util/ObjectIdentifier;
+Lsun/security/util/DerInputStream;->getSequence(I)[Lsun/security/util/DerValue;
+Lsun/security/util/DerInputStream;->getSet(I)[Lsun/security/util/DerValue;
+Lsun/security/util/DerInputStream;->getSet(IZ)[Lsun/security/util/DerValue;
+Lsun/security/util/DerInputStream;->getUTCTime()Ljava/util/Date;
+Lsun/security/util/DerInputStream;->getUTF8String()Ljava/lang/String;
+Lsun/security/util/DerInputStream;->mark(I)V
+Lsun/security/util/DerInputStream;->peekByte()I
+Lsun/security/util/DerInputStream;->reset()V
+Lsun/security/util/DerInputStream;->subStream(IZ)Lsun/security/util/DerInputStream;
+Lsun/security/util/DerInputStream;->tag:B
+Lsun/security/util/DerOutputStream;-><init>()V
+Lsun/security/util/DerOutputStream;-><init>(I)V
+Lsun/security/util/DerOutputStream;->putBitString([B)V
+Lsun/security/util/DerOutputStream;->putBoolean(Z)V
+Lsun/security/util/DerOutputStream;->putDerValue(Lsun/security/util/DerValue;)V
+Lsun/security/util/DerOutputStream;->putIA5String(Ljava/lang/String;)V
+Lsun/security/util/DerOutputStream;->putInteger(I)V
+Lsun/security/util/DerOutputStream;->putInteger(Ljava/math/BigInteger;)V
+Lsun/security/util/DerOutputStream;->putNull()V
+Lsun/security/util/DerOutputStream;->putOctetString([B)V
+Lsun/security/util/DerOutputStream;->putOID(Lsun/security/util/ObjectIdentifier;)V
+Lsun/security/util/DerOutputStream;->putOrderedSetOf(B[Lsun/security/util/DerEncoder;)V
+Lsun/security/util/DerOutputStream;->putPrintableString(Ljava/lang/String;)V
+Lsun/security/util/DerOutputStream;->putSequence([Lsun/security/util/DerValue;)V
+Lsun/security/util/DerOutputStream;->putUTCTime(Ljava/util/Date;)V
+Lsun/security/util/DerOutputStream;->putUTF8String(Ljava/lang/String;)V
+Lsun/security/util/DerOutputStream;->write(BLsun/security/util/DerOutputStream;)V
+Lsun/security/util/DerOutputStream;->write(B[B)V
+Lsun/security/util/DerValue;-><init>(B[B)V
+Lsun/security/util/DerValue;-><init>(Ljava/io/InputStream;)V
+Lsun/security/util/DerValue;-><init>(Ljava/lang/String;)V
+Lsun/security/util/DerValue;-><init>([B)V
+Lsun/security/util/DerValue;-><init>([BII)V
+Lsun/security/util/DerValue;->buffer:Lsun/security/util/DerInputBuffer;
+Lsun/security/util/DerValue;->createTag(BZB)B
+Lsun/security/util/DerValue;->data:Lsun/security/util/DerInputStream;
+Lsun/security/util/DerValue;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/util/DerValue;->getAsString()Ljava/lang/String;
+Lsun/security/util/DerValue;->getBigInteger()Ljava/math/BigInteger;
+Lsun/security/util/DerValue;->getBitString()[B
+Lsun/security/util/DerValue;->getData()Lsun/security/util/DerInputStream;
+Lsun/security/util/DerValue;->getDataBytes()[B
+Lsun/security/util/DerValue;->getOctetString()[B
+Lsun/security/util/DerValue;->getOID()Lsun/security/util/ObjectIdentifier;
+Lsun/security/util/DerValue;->getPositiveBigInteger()Ljava/math/BigInteger;
+Lsun/security/util/DerValue;->getUnalignedBitString()Lsun/security/util/BitArray;
+Lsun/security/util/DerValue;->isConstructed()Z
+Lsun/security/util/DerValue;->isContextSpecific()Z
+Lsun/security/util/DerValue;->isContextSpecific(B)Z
+Lsun/security/util/DerValue;->isPrintableStringChar(C)Z
+Lsun/security/util/DerValue;->resetTag(B)V
+Lsun/security/util/DerValue;->tag:B
+Lsun/security/util/DerValue;->toByteArray()[B
+Lsun/security/util/DerValue;->toDerInputStream()Lsun/security/util/DerInputStream;
+Lsun/security/util/ManifestDigester$Entry;->digest(Ljava/security/MessageDigest;)[B
+Lsun/security/util/ManifestDigester$Entry;->digestWorkaround(Ljava/security/MessageDigest;)[B
+Lsun/security/util/ManifestDigester;-><init>([B)V
+Lsun/security/util/ManifestDigester;->get(Ljava/lang/String;Z)Lsun/security/util/ManifestDigester$Entry;
+Lsun/security/util/ManifestDigester;->manifestDigest(Ljava/security/MessageDigest;)[B
+Lsun/security/util/MemoryCache$HardCacheEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;J)V
+Lsun/security/util/MemoryCache$SoftCacheEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;JLjava/lang/ref/ReferenceQueue;)V
+Lsun/security/util/ObjectIdentifier;-><init>(Ljava/lang/String;)V
+Lsun/security/util/ObjectIdentifier;-><init>([I)V
+Lsun/security/util/ObjectIdentifier;->equals(Lsun/security/util/ObjectIdentifier;)Z
+Lsun/security/util/ObjectIdentifier;->newInternal([I)Lsun/security/util/ObjectIdentifier;
+Lsun/security/util/PropertyExpander;->expand(Ljava/lang/String;)Ljava/lang/String;
+Lsun/security/util/ResourcesMgr;->getString(Ljava/lang/String;)Ljava/lang/String;
+Lsun/security/util/SecurityConstants;->CREATE_CLASSLOADER_PERMISSION:Ljava/lang/RuntimePermission;
+Lsun/security/util/SecurityConstants;->GET_CLASSLOADER_PERMISSION:Ljava/lang/RuntimePermission;
+Lsun/security/util/SecurityConstants;->MODIFY_THREADGROUP_PERMISSION:Ljava/lang/RuntimePermission;
+Lsun/security/util/SecurityConstants;->MODIFY_THREAD_PERMISSION:Ljava/lang/RuntimePermission;
+Lsun/security/util/SignatureFileVerifier;->isBlockOrSF(Ljava/lang/String;)Z
+Lsun/security/x509/AccessDescription;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/AccessDescription;->getAccessLocation()Lsun/security/x509/GeneralName;
+Lsun/security/x509/AccessDescription;->getAccessMethod()Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;-><init>()V
+Lsun/security/x509/AlgorithmId;-><init>(Lsun/security/util/ObjectIdentifier;)V
+Lsun/security/x509/AlgorithmId;-><init>(Lsun/security/util/ObjectIdentifier;Ljava/security/AlgorithmParameters;)V
+Lsun/security/x509/AlgorithmId;->derEncode(Ljava/io/OutputStream;)V
+Lsun/security/x509/AlgorithmId;->DSA_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->EC_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->encode()[B
+Lsun/security/x509/AlgorithmId;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/x509/AlgorithmId;->equals(Lsun/security/x509/AlgorithmId;)Z
+Lsun/security/x509/AlgorithmId;->getAlgorithmId(Ljava/lang/String;)Lsun/security/x509/AlgorithmId;
+Lsun/security/x509/AlgorithmId;->getDigAlgFromSigAlg(Ljava/lang/String;)Ljava/lang/String;
+Lsun/security/x509/AlgorithmId;->getEncAlgFromSigAlg(Ljava/lang/String;)Ljava/lang/String;
+Lsun/security/x509/AlgorithmId;->getEncodedParams()[B
+Lsun/security/x509/AlgorithmId;->getOID()Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->getParameters()Ljava/security/AlgorithmParameters;
+Lsun/security/x509/AlgorithmId;->MD2_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->MD5_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->params:Lsun/security/util/DerValue;
+Lsun/security/x509/AlgorithmId;->parse(Lsun/security/util/DerValue;)Lsun/security/x509/AlgorithmId;
+Lsun/security/x509/AlgorithmId;->RSAEncryption_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->sha1WithRSAEncryption_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->SHA256_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->SHA384_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->SHA512_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AlgorithmId;->SHA_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AttributeNameEnumeration;-><init>()V
+Lsun/security/x509/AVA;-><init>(Lsun/security/util/ObjectIdentifier;Lsun/security/util/DerValue;)V
+Lsun/security/x509/AVA;->getDerValue()Lsun/security/util/DerValue;
+Lsun/security/x509/AVA;->getObjectIdentifier()Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AVA;->getValueString()Ljava/lang/String;
+Lsun/security/x509/AVA;->toRFC2253CanonicalString()Ljava/lang/String;
+Lsun/security/x509/AVAComparator;->INSTANCE:Ljava/util/Comparator;
+Lsun/security/x509/AVAKeyword;->getOID(Ljava/lang/String;ILjava/util/Map;)Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AVAKeyword;->isCompliant(I)Z
+Lsun/security/x509/AVAKeyword;->keyword:Ljava/lang/String;
+Lsun/security/x509/AVAKeyword;->keywordMap:Ljava/util/Map;
+Lsun/security/x509/AVAKeyword;->oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/AVAKeyword;->oidMap:Ljava/util/Map;
+Lsun/security/x509/CertificateAlgorithmId;-><init>(Lsun/security/x509/AlgorithmId;)V
+Lsun/security/x509/CertificateExtensions;-><init>()V
+Lsun/security/x509/CertificateExtensions;-><init>(Lsun/security/util/DerInputStream;)V
+Lsun/security/x509/CertificateExtensions;->encode(Ljava/io/OutputStream;Z)V
+Lsun/security/x509/CertificateExtensions;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/CertificateExtensions;->set(Ljava/lang/String;Ljava/lang/Object;)V
+Lsun/security/x509/CertificateIssuerName;-><init>(Lsun/security/x509/X500Name;)V
+Lsun/security/x509/CertificateSerialNumber;-><init>(I)V
+Lsun/security/x509/CertificateSerialNumber;-><init>(Ljava/math/BigInteger;)V
+Lsun/security/x509/CertificateSubjectName;-><init>(Lsun/security/x509/X500Name;)V
+Lsun/security/x509/CertificateSubjectName;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/CertificateValidity;-><init>(Ljava/util/Date;Ljava/util/Date;)V
+Lsun/security/x509/CertificateVersion;-><init>(I)V
+Lsun/security/x509/CertificateX509Key;-><init>(Ljava/security/PublicKey;)V
+Lsun/security/x509/CRLDistributionPointsExtension;->encodeThis()V
+Lsun/security/x509/CRLNumberExtension;-><init>(Ljava/lang/Boolean;Ljava/lang/Object;)V
+Lsun/security/x509/CRLNumberExtension;->encodeThis()V
+Lsun/security/x509/CRLNumberExtension;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/Extension;-><init>(Lsun/security/x509/Extension;)V
+Lsun/security/x509/Extension;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/x509/Extension;->getExtensionId()Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/GeneralName;-><init>(Lsun/security/x509/GeneralNameInterface;)V
+Lsun/security/x509/GeneralName;->getName()Lsun/security/x509/GeneralNameInterface;
+Lsun/security/x509/GeneralName;->getType()I
+Lsun/security/x509/GeneralNames;-><init>()V
+Lsun/security/x509/GeneralNames;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/GeneralNames;->add(Lsun/security/x509/GeneralName;)Lsun/security/x509/GeneralNames;
+Lsun/security/x509/GeneralNames;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/x509/GeneralNames;->isEmpty()Z
+Lsun/security/x509/KeyIdentifier;-><init>(Ljava/security/PublicKey;)V
+Lsun/security/x509/KeyIdentifier;->getIdentifier()[B
+Lsun/security/x509/KeyIdentifier;->octetString:[B
+Lsun/security/x509/KeyUsageExtension;-><init>([Z)V
+Lsun/security/x509/KeyUsageExtension;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/NetscapeCertTypeExtension;-><init>([B)V
+Lsun/security/x509/NetscapeCertTypeExtension;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/OIDMap$OIDInfo;->clazz:Ljava/lang/Class;
+Lsun/security/x509/OIDMap;->getClass(Lsun/security/util/ObjectIdentifier;)Ljava/lang/Class;
+Lsun/security/x509/OIDMap;->nameMap:Ljava/util/Map;
+Lsun/security/x509/OIDMap;->oidMap:Ljava/util/Map;
+Lsun/security/x509/PKIXExtensions;->CertificateIssuer_Id:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/SerialNumber;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/SubjectAlternativeNameExtension;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/SubjectKeyIdentifierExtension;-><init>([B)V
+Lsun/security/x509/UniqueIdentity;-><init>(Lsun/security/util/DerInputStream;)V
+Lsun/security/x509/UniqueIdentity;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/UniqueIdentity;->encode(Lsun/security/util/DerOutputStream;B)V
+Lsun/security/x509/URIName;->getName()Ljava/lang/String;
+Lsun/security/x509/URIName;->getScheme()Ljava/lang/String;
+Lsun/security/x509/X500Name;-><init>(Ljava/lang/String;)V
+Lsun/security/x509/X500Name;-><init>(Ljava/lang/String;Ljava/lang/String;)V
+Lsun/security/x509/X500Name;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lsun/security/x509/X500Name;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+Lsun/security/x509/X500Name;-><init>(Lsun/security/util/DerInputStream;)V
+Lsun/security/x509/X500Name;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/X500Name;-><init>([B)V
+Lsun/security/x509/X500Name;->allAvas()Ljava/util/List;
+Lsun/security/x509/X500Name;->asX500Name(Ljavax/security/auth/x500/X500Principal;)Lsun/security/x509/X500Name;
+Lsun/security/x509/X500Name;->asX500Principal()Ljavax/security/auth/x500/X500Principal;
+Lsun/security/x509/X500Name;->commonName_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->countryName_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->DNQUALIFIER_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->DOMAIN_COMPONENT_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->encode(Lsun/security/util/DerOutputStream;)V
+Lsun/security/x509/X500Name;->GENERATIONQUALIFIER_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->getCommonName()Ljava/lang/String;
+Lsun/security/x509/X500Name;->GIVENNAME_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->INITIALS_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->ipAddress_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->isEmpty()Z
+Lsun/security/x509/X500Name;->localityName_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->orgName_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->orgUnitName_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->SERIALNUMBER_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->stateName_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->streetAddress_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->SURNAME_OID:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->title_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X500Name;->userid_oid:Lsun/security/util/ObjectIdentifier;
+Lsun/security/x509/X509CertImpl;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/X509CertImpl;-><init>(Lsun/security/x509/X509CertInfo;)V
+Lsun/security/x509/X509CertImpl;-><init>([B)V
+Lsun/security/x509/X509CertImpl;->algId:Lsun/security/x509/AlgorithmId;
+Lsun/security/x509/X509CertImpl;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/X509CertImpl;->getEncodedInternal()[B
+Lsun/security/x509/X509CertImpl;->parse(Lsun/security/util/DerValue;)V
+Lsun/security/x509/X509CertImpl;->readOnly:Z
+Lsun/security/x509/X509CertImpl;->sign(Ljava/security/PrivateKey;Ljava/lang/String;)V
+Lsun/security/x509/X509CertImpl;->signature:[B
+Lsun/security/x509/X509CertImpl;->signedCert:[B
+Lsun/security/x509/X509CertInfo;-><init>()V
+Lsun/security/x509/X509CertInfo;-><init>([B)V
+Lsun/security/x509/X509CertInfo;->get(Ljava/lang/String;)Ljava/lang/Object;
+Lsun/security/x509/X509CertInfo;->set(Ljava/lang/String;Ljava/lang/Object;)V
+Lsun/security/x509/X509CRLEntryImpl;->getExtension(Lsun/security/util/ObjectIdentifier;)Lsun/security/x509/Extension;
+Lsun/security/x509/X509CRLImpl;-><init>(Ljava/io/InputStream;)V
+Lsun/security/x509/X509CRLImpl;-><init>(Lsun/security/util/DerValue;)V
+Lsun/security/x509/X509CRLImpl;-><init>([B)V
+Lsun/security/x509/X509CRLImpl;->getEncodedInternal()[B
+Lsun/security/x509/X509Key;-><init>()V
+Lsun/security/x509/X509Key;->algid:Lsun/security/x509/AlgorithmId;
+Lsun/security/x509/X509Key;->encodedKey:[B
+Lsun/security/x509/X509Key;->key:[B
+Lsun/security/x509/X509Key;->parse(Lsun/security/util/DerValue;)Ljava/security/PublicKey;
+Lsun/security/x509/X509Key;->unusedBits:I
+Lsun/util/calendar/AbstractCalendar;->getDayOfWeekDateOnOrBefore(JI)J
+Lsun/util/calendar/AbstractCalendar;->getTimeOfDayValue(Lsun/util/calendar/CalendarDate;)J
+Lsun/util/calendar/BaseCalendar$Date;->getNormalizedYear()I
+Lsun/util/calendar/BaseCalendar$Date;->setNormalizedYear(I)V
+Lsun/util/calendar/CalendarDate;->getDayOfMonth()I
+Lsun/util/calendar/CalendarDate;->getMonth()I
+Lsun/util/calendar/CalendarDate;->getTimeOfDay()J
+Lsun/util/calendar/CalendarDate;->getYear()I
+Lsun/util/calendar/CalendarDate;->setDate(III)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarDate;->setDayOfMonth(I)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarDate;->setHours(I)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarDate;->setMillis(I)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarDate;->setMinutes(I)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarDate;->setSeconds(I)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarSystem;->forName(Ljava/lang/String;)Lsun/util/calendar/CalendarSystem;
+Lsun/util/calendar/CalendarSystem;->getGregorianCalendar()Lsun/util/calendar/Gregorian;
+Lsun/util/calendar/CalendarSystem;->getTime(Lsun/util/calendar/CalendarDate;)J
+Lsun/util/calendar/CalendarSystem;->newCalendarDate(Ljava/util/TimeZone;)Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/CalendarSystem;->validate(Lsun/util/calendar/CalendarDate;)Z
+Lsun/util/calendar/CalendarUtils;->floorDivide(II)I
+Lsun/util/calendar/CalendarUtils;->floorDivide(JJ)J
+Lsun/util/calendar/CalendarUtils;->mod(II)I
+Lsun/util/calendar/CalendarUtils;->mod(JJ)J
+Lsun/util/calendar/Era;-><init>(Ljava/lang/String;Ljava/lang/String;JZ)V
+Lsun/util/calendar/Era;->getAbbreviation()Ljava/lang/String;
+Lsun/util/calendar/Era;->getName()Ljava/lang/String;
+Lsun/util/calendar/Era;->getSinceDate()Lsun/util/calendar/CalendarDate;
+Lsun/util/calendar/ImmutableGregorianDate;->unsupported()V
+Lsun/util/calendar/LocalGregorianCalendar$Date;->getNormalizedYear()I
+Lsun/util/calendar/LocalGregorianCalendar$Date;->setEra(Lsun/util/calendar/Era;)Lsun/util/calendar/LocalGregorianCalendar$Date;
+Lsun/util/calendar/LocalGregorianCalendar$Date;->setNormalizedYear(I)V
+Lsun/util/calendar/LocalGregorianCalendar$Date;->setYear(I)Lsun/util/calendar/LocalGregorianCalendar$Date;
+Lsun/util/calendar/LocalGregorianCalendar;->newCalendarDate(Ljava/util/TimeZone;)Lsun/util/calendar/LocalGregorianCalendar$Date;
+Lsun/util/calendar/LocalGregorianCalendar;->normalize(Lsun/util/calendar/CalendarDate;)Z
+Lsun/util/calendar/LocalGregorianCalendar;->validate(Lsun/util/calendar/CalendarDate;)Z
diff --git a/config/preloaded-classes b/config/preloaded-classes
index b6bff9c..14597ee 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -3240,7 +3240,7 @@
 android.view.FocusFinder$FocusSorter
 android.view.FocusFinder$UserSpecifiedFocusComparator
 android.view.FocusFinder$UserSpecifiedFocusComparator$NextFocusGetter
-android.view.FrameInfo
+android.graphics.FrameInfo
 android.view.FrameMetrics
 android.view.FrameMetricsObserver
 android.view.FrameStats
@@ -4117,6 +4117,8 @@
 com.android.internal.util.VirtualRefBasePtr
 com.android.internal.util.XmlUtils
 com.android.internal.util.XmlUtils$WriteMapCallback
+com.android.internal.util.function.HeptConsumer
+com.android.internal.util.function.HeptFunction
 com.android.internal.util.function.HexConsumer
 com.android.internal.util.function.HexFunction
 com.android.internal.util.function.QuadConsumer
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index d7cca15..997ed25 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -76,7 +76,8 @@
  * @attr ref android.R.styleable#AccessibilityService_notificationTimeout
  * @attr ref android.R.styleable#AccessibilityService_packageNames
  * @attr ref android.R.styleable#AccessibilityService_settingsActivity
- * @attr ref android.R.styleable#AccessibilityService_minimumUiTimeout
+ * @attr ref android.R.styleable#AccessibilityService_nonInteractiveUiTimeout
+ * @attr ref android.R.styleable#AccessibilityService_interactiveUiTimeout
  * @see AccessibilityService
  * @see android.view.accessibility.AccessibilityEvent
  * @see android.view.accessibility.AccessibilityManager
@@ -434,11 +435,14 @@
     public boolean crashed;
 
     /**
-     * The minimum timeout in milliseconds that UI controls need to remain on the screen.
-     *
-     * @see #setMinimumUiTimeoutMillis
+     * A recommended timeout in milliseconds for non-interactive controls.
      */
-    private int mMinimumUiTimeout;
+    private int mNonInteractiveUiTimeout;
+
+    /**
+     * A recommended timeout in milliseconds for interactive controls.
+     */
+    private int mInteractiveUiTimeout;
 
     /**
      * The component name the accessibility service.
@@ -544,8 +548,11 @@
             notificationTimeout = asAttributes.getInt(
                     com.android.internal.R.styleable.AccessibilityService_notificationTimeout,
                     0);
-            mMinimumUiTimeout = asAttributes.getInt(
-                    com.android.internal.R.styleable.AccessibilityService_minimumUiTimeout,
+            mNonInteractiveUiTimeout = asAttributes.getInt(
+                    com.android.internal.R.styleable.AccessibilityService_nonInteractiveUiTimeout,
+                    0);
+            mInteractiveUiTimeout = asAttributes.getInt(
+                    com.android.internal.R.styleable.AccessibilityService_interactiveUiTimeout,
                     0);
             flags = asAttributes.getInt(
                     com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0);
@@ -616,7 +623,8 @@
         packageNames = other.packageNames;
         feedbackType = other.feedbackType;
         notificationTimeout = other.notificationTimeout;
-        mMinimumUiTimeout = other.mMinimumUiTimeout;
+        mNonInteractiveUiTimeout = other.mNonInteractiveUiTimeout;
+        mInteractiveUiTimeout = other.mInteractiveUiTimeout;
         flags = other.flags;
     }
 
@@ -775,26 +783,57 @@
     }
 
     /**
-     * Set the minimum time that controls need to remain on the screen to support the user.
+     * Set the recommended time that non-interactive controls need to remain on the screen to
+     * support the user.
      * <p>
-     *    <strong>This value can be dynamically set at runtime by
-     *    {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong>
+     *     <strong>This value can be dynamically set at runtime by
+     *     {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong>
      * </p>
      *
      * @param timeout The timeout in milliseconds.
+     *
+     * @see android.R.styleable#AccessibilityService_nonInteractiveUiTimeout
      */
-    public void setMinimumUiTimeoutMillis(int timeout) {
-        mMinimumUiTimeout = timeout;
+    public void setNonInteractiveUiTimeoutMillis(int timeout) {
+        mNonInteractiveUiTimeout = timeout;
     }
 
     /**
-     * Get the minimum ui timeout.
+     * Get the recommended timeout for non-interactive controls.
      *
-     * @see #setMinimumUiTimeoutMillis
      * @return The timeout in milliseconds.
+     *
+     * @see #setNonInteractiveUiTimeoutMillis(int)
      */
-    public int getMinimumUiTimeoutMillis() {
-        return mMinimumUiTimeout;
+    public int getNonInteractiveUiTimeoutMillis() {
+        return mNonInteractiveUiTimeout;
+    }
+
+    /**
+     * Set the recommended time that interactive controls need to remain on the screen to
+     * support the user.
+     * <p>
+     *     <strong>This value can be dynamically set at runtime by
+     *     {@link AccessibilityService#setServiceInfo(AccessibilityServiceInfo)}.</strong>
+     * </p>
+     *
+     * @param timeout The timeout in milliseconds.
+     *
+     * @see android.R.styleable#AccessibilityService_interactiveUiTimeout
+     */
+    public void setInteractiveUiTimeoutMillis(int timeout) {
+        mInteractiveUiTimeout = timeout;
+    }
+
+    /**
+     * Get the recommended timeout for interactive controls.
+     *
+     * @return The timeout in milliseconds.
+     *
+     * @see #setInteractiveUiTimeoutMillis(int)
+     */
+    public int getInteractiveUiTimeoutMillis() {
+        return mInteractiveUiTimeout;
     }
 
     /** {@hide} */
@@ -815,7 +854,8 @@
         parcel.writeStringArray(packageNames);
         parcel.writeInt(feedbackType);
         parcel.writeLong(notificationTimeout);
-        parcel.writeInt(mMinimumUiTimeout);
+        parcel.writeInt(mNonInteractiveUiTimeout);
+        parcel.writeInt(mInteractiveUiTimeout);
         parcel.writeInt(flags);
         parcel.writeInt(crashed ? 1 : 0);
         parcel.writeParcelable(mComponentName, flagz);
@@ -833,7 +873,8 @@
         packageNames = parcel.readStringArray();
         feedbackType = parcel.readInt();
         notificationTimeout = parcel.readLong();
-        mMinimumUiTimeout = parcel.readInt();
+        mNonInteractiveUiTimeout = parcel.readInt();
+        mInteractiveUiTimeout = parcel.readInt();
         flags = parcel.readInt();
         crashed = parcel.readInt() != 0;
         mComponentName = parcel.readParcelable(this.getClass().getClassLoader());
@@ -884,7 +925,9 @@
         stringBuilder.append(", ");
         stringBuilder.append("notificationTimeout: ").append(notificationTimeout);
         stringBuilder.append(", ");
-        stringBuilder.append("minimumUiTimeout: ").append(mMinimumUiTimeout);
+        stringBuilder.append("nonInteractiveUiTimeout: ").append(mNonInteractiveUiTimeout);
+        stringBuilder.append(", ");
+        stringBuilder.append("interactiveUiTimeout: ").append(mInteractiveUiTimeout);
         stringBuilder.append(", ");
         appendFlags(stringBuilder, flags);
         stringBuilder.append(", ");
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a666819..553acc8 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -31,6 +31,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.StyleRes;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.VoiceInteractor.Request;
 import android.app.admin.DevicePolicyManager;
@@ -120,6 +121,8 @@
 import android.view.autofill.AutofillManager.AutofillClient;
 import android.view.autofill.AutofillPopupWindow;
 import android.view.autofill.IAutofillWindowPresenter;
+import android.view.intelligence.ContentCaptureEvent;
+import android.view.intelligence.IntelligenceManager;
 import android.widget.AdapterView;
 import android.widget.Toast;
 import android.widget.Toolbar;
@@ -821,6 +824,10 @@
     /** The autofill manager. Always access via {@link #getAutofillManager()}. */
     @Nullable private AutofillManager mAutofillManager;
 
+    /** The screen observation manager. Always access via {@link #getIntelligenceManager()}. */
+    @Nullable private IntelligenceManager mIntelligenceManager;
+
+
     static final class NonConfigurationInstances {
         Object activity;
         HashMap<String, Object> children;
@@ -994,7 +1001,7 @@
     }
 
     /**
-     * (Create and) return the autofill manager
+     * (Creates, sets and) returns the autofill manager
      *
      * @return The autofill manager
      */
@@ -1006,6 +1013,43 @@
         return mAutofillManager;
     }
 
+    /**
+     * (Creates, sets, and ) returns the intelligence manager
+     *
+     * @return The intelligence manager
+     */
+    @NonNull private IntelligenceManager getIntelligenceManager() {
+        if (mIntelligenceManager == null) {
+            mIntelligenceManager = getSystemService(IntelligenceManager.class);
+        }
+        return mIntelligenceManager;
+    }
+
+    private void notifyIntelligenceManagerIfNeeded(@ContentCaptureEvent.EventType int event) {
+        final IntelligenceManager im = getIntelligenceManager();
+        if (im == null || !im.isContentCaptureEnabled()) {
+            return;
+        }
+        switch (event) {
+            case ContentCaptureEvent.TYPE_ACTIVITY_CREATED:
+                //TODO(b/111276913): decide whether the InteractionSessionId should be
+                // saved / restored in the activity bundle.
+                im.onActivityCreated(mToken, getComponentName());
+                break;
+            case ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED:
+                im.onActivityDestroyed();
+                break;
+            case ContentCaptureEvent.TYPE_ACTIVITY_STARTED:
+            case ContentCaptureEvent.TYPE_ACTIVITY_RESUMED:
+            case ContentCaptureEvent.TYPE_ACTIVITY_PAUSED:
+            case ContentCaptureEvent.TYPE_ACTIVITY_STOPPED:
+                im.onActivityLifecycleEvent(event);
+                break;
+            default:
+                Log.w(TAG, "notifyIntelligenceManagerIfNeeded(): invalid type " + event);
+        }
+    }
+
     @Override
     protected void attachBaseContext(Context newBase) {
         super.attachBaseContext(newBase);
@@ -1081,6 +1125,8 @@
         }
         mRestoredFromBundle = savedInstanceState != null;
         mCalled = true;
+
+        notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_CREATED);
     }
 
     /**
@@ -1314,6 +1360,7 @@
         if (mAutoFillResetNeeded) {
             getAutofillManager().onVisibleForAutofill();
         }
+        notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STARTED);
     }
 
     /**
@@ -1396,6 +1443,7 @@
                 }
             }
         }
+        notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_RESUMED);
         mCalled = true;
     }
 
@@ -1789,6 +1837,7 @@
                 mAutoFillIgnoreFirstResumePause = false;
             }
         }
+        notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_PAUSED);
         mCalled = true;
     }
 
@@ -1977,6 +2026,7 @@
                 getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_CANCEL,
                         mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN));
             }
+            notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_STOPPED);
         }
     }
 
@@ -2047,6 +2097,9 @@
         }
 
         getApplication().dispatchActivityDestroyed(this);
+
+        notifyIntelligenceManagerIfNeeded(ContentCaptureEvent.TYPE_ACTIVITY_DESTROYED);
+
     }
 
     /**
@@ -2294,6 +2347,7 @@
      * @see View#onMovedToDisplay(int, Configuration)
      * @hide
      */
+    @TestApi
     public void onMovedToDisplay(int displayId, Configuration config) {
     }
 
@@ -4786,6 +4840,7 @@
      * their launch had come from the original activity.
      * @param intent The Intent to start.
      * @param options ActivityOptions or null.
+     * @param permissionToken Token received from the system that permits this call to be made.
      * @param ignoreTargetSecurity If true, the activity manager will not check whether the
      * caller it is doing the start is, is actually allowed to start the target activity.
      * If you set this to true, you must set an explicit component in the Intent and do any
@@ -4794,7 +4849,7 @@
      * @hide
      */
     public void startActivityAsCaller(Intent intent, @Nullable Bundle options,
-            boolean ignoreTargetSecurity, int userId) {
+            IBinder permissionToken, boolean ignoreTargetSecurity, int userId) {
         if (mParent != null) {
             throw new RuntimeException("Can't be called from a child");
         }
@@ -4802,7 +4857,7 @@
         Instrumentation.ActivityResult ar =
                 mInstrumentation.execStartActivityAsCaller(
                         this, mMainThread.getApplicationThread(), mToken, this,
-                        intent, -1, options, ignoreTargetSecurity, userId);
+                        intent, -1, options, permissionToken, ignoreTargetSecurity, userId);
         if (ar != null) {
             mMainThread.sendActivityResult(
                 mToken, mEmbeddedID, -1, ar.getResultCode(),
@@ -6403,9 +6458,16 @@
 
     void dumpInner(@NonNull String prefix, @Nullable FileDescriptor fd,
             @NonNull PrintWriter writer, @Nullable String[] args) {
-        if (args != null && args.length > 0 && args[0].equals("--autofill")) {
-            dumpAutofillManager(prefix, writer);
-            return;
+        if (args != null && args.length > 0) {
+            // Handle special cases
+            switch (args[0]) {
+                case "--autofill":
+                    dumpAutofillManager(prefix, writer);
+                    return;
+                case "--intelligence":
+                    dumpIntelligenceManager(prefix, writer);
+                    return;
+            }
         }
         writer.print(prefix); writer.print("Local Activity ");
                 writer.print(Integer.toHexString(System.identityHashCode(this)));
@@ -6435,6 +6497,7 @@
         mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix);
 
         dumpAutofillManager(prefix, writer);
+        dumpIntelligenceManager(prefix, writer);
 
         ResourcesManager.getInstance().dump(prefix, writer);
     }
@@ -6450,6 +6513,15 @@
         }
     }
 
+    void dumpIntelligenceManager(String prefix, PrintWriter writer) {
+        final IntelligenceManager im = getIntelligenceManager();
+        if (im != null) {
+            im.dump(prefix, writer);
+        } else {
+            writer.print(prefix); writer.println("No IntelligenceManager");
+        }
+    }
+
     /**
      * Bit indicating that this activity is "immersive" and should not be
      * interrupted by notifications if possible.
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7330da3..1cf042f 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1751,6 +1751,8 @@
      */
     public static class TaskSnapshot implements Parcelable {
 
+        // Top activity in task when snapshot was taken
+        private final ComponentName mTopActivityComponent;
         private final GraphicBuffer mSnapshot;
         private final int mOrientation;
         private final Rect mContentInsets;
@@ -1765,9 +1767,11 @@
         private final int mSystemUiVisibility;
         private final boolean mIsTranslucent;
 
-        public TaskSnapshot(GraphicBuffer snapshot, int orientation, Rect contentInsets,
-                boolean reducedResolution, float scale, boolean isRealSnapshot, int windowingMode,
-                int systemUiVisibility, boolean isTranslucent) {
+        public TaskSnapshot(@NonNull ComponentName topActivityComponent, GraphicBuffer snapshot,
+                int orientation, Rect contentInsets, boolean reducedResolution, float scale,
+                boolean isRealSnapshot, int windowingMode, int systemUiVisibility,
+                boolean isTranslucent) {
+            mTopActivityComponent = topActivityComponent;
             mSnapshot = snapshot;
             mOrientation = orientation;
             mContentInsets = new Rect(contentInsets);
@@ -1780,6 +1784,7 @@
         }
 
         private TaskSnapshot(Parcel source) {
+            mTopActivityComponent = ComponentName.readFromParcel(source);
             mSnapshot = source.readParcelable(null /* classLoader */);
             mOrientation = source.readInt();
             mContentInsets = source.readParcelable(null /* classLoader */);
@@ -1792,6 +1797,13 @@
         }
 
         /**
+         * @return The top activity component for the task at the point this snapshot was taken.
+         */
+        public ComponentName getTopActivityComponent() {
+            return mTopActivityComponent;
+        }
+
+        /**
          * @return The graphic buffer representing the screenshot.
          */
         @UnsupportedAppUsage
@@ -1871,6 +1883,7 @@
 
         @Override
         public void writeToParcel(Parcel dest, int flags) {
+            ComponentName.writeToParcel(mTopActivityComponent, dest);
             dest.writeParcelable(mSnapshot, 0);
             dest.writeInt(mOrientation);
             dest.writeParcelable(mContentInsets, 0);
@@ -1886,7 +1899,9 @@
         public String toString() {
             final int width = mSnapshot != null ? mSnapshot.getWidth() : 0;
             final int height = mSnapshot != null ? mSnapshot.getHeight() : 0;
-            return "TaskSnapshot{mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")"
+            return "TaskSnapshot{"
+                    + " mTopActivityComponent=" + mTopActivityComponent.flattenToShortString()
+                    + " mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")"
                     + " mOrientation=" + mOrientation
                     + " mContentInsets=" + mContentInsets.toShortString()
                     + " mReducedResolution=" + mReducedResolution + " mScale=" + mScale
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 069effd..0e5b976 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -161,13 +161,6 @@
     public abstract List<ProcessMemoryState> getMemoryStateForProcesses();
 
     /**
-     * Returns a list that contains the memory stats for monitored native processes.
-     *
-     * The list of the monitored processes is defined in MemoryStatUtil class.
-     */
-    public abstract List<ProcessMemoryState> getMemoryStateForNativeProcesses();
-
-    /**
      * Checks to see if the calling pid is allowed to handle the user. Returns adjusted user id as
      * needed.
      */
@@ -277,7 +270,15 @@
     public abstract void startProcess(String processName, ApplicationInfo info,
             boolean knownToBeDead, String hostingType, ComponentName hostingName);
 
-    /** Starts up the starting activity process for debugging if needed. */
+    /** Starts up the starting activity process for debugging if needed.
+     * This function needs to be called synchronously from WindowManager context so the caller
+     * passes a lock {@code wmLock} and waits to be notified.
+     *
+     * @param wmLock calls {@code notify} on the object to wake up the caller.
+    */
     public abstract void setDebugFlagsForStartingActivity(ActivityInfo aInfo, int startFlags,
-            ProfilerInfo profilerInfo);
+            ProfilerInfo profilerInfo, Object wmLock);
+
+    /** Checks if process running with given pid has access to full external storage or not */
+    public abstract boolean isAppStorageSandboxed(int pid, int uid);
 }
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index b8fe2f1..56ccf6f 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -110,6 +110,32 @@
     public static final int RESIZE_MODE_USER_FORCED =
             RESIZE_MODE_PRESERVE_WINDOW | RESIZE_MODE_FORCED;
 
+    /**
+     * Extra included on intents that are delegating the call to
+     * ActivityManager#startActivityAsCaller to another app.  This token is necessary for that call
+     * to succeed.  Type is IBinder.
+     * @hide
+     */
+    public static final String EXTRA_PERMISSION_TOKEN = "android.app.extra.PERMISSION_TOKEN";
+
+    /**
+     * Extra included on intents that contain an EXTRA_INTENT, with options that the contained
+     * intent may want to be started with.  Type is Bundle.
+     * TODO: remove once the ChooserActivity moves to systemui
+     * @hide
+     */
+    public static final String EXTRA_OPTIONS = "android.app.extra.OPTIONS";
+
+    /**
+     * Extra included on intents that contain an EXTRA_INTENT, use this boolean value for the
+     * parameter of the same name when starting the contained intent.
+     * TODO: remove once the ChooserActivity moves to systemui
+     * @hide
+     */
+    public static final String EXTRA_IGNORE_TARGET_SECURITY =
+            "android.app.extra.EXTRA_IGNORE_TARGET_SECURITY";
+
+
     private static int sMaxRecentTasks = -1;
 
     ActivityTaskManager(Context context, Handler handler) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9079f1a..805fb68 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -72,6 +72,7 @@
 import android.database.sqlite.SQLiteDebug.DbStats;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.HardwareRenderer;
 import android.graphics.ImageDecoder;
 import android.hardware.display.DisplayManagerGlobal;
 import android.net.ConnectivityManager;
@@ -5652,7 +5653,7 @@
                     int uid = Process.myUid();
                     String[] packages = getPackageManager().getPackagesForUid(uid);
                     if (packages != null) {
-                        ThreadedRenderer.setupDiskCache(codeCacheDir);
+                        HardwareRenderer.setupDiskCache(codeCacheDir);
                         RenderScriptCacheDir.setupDiskCache(codeCacheDir);
                     }
                 } catch (RemoteException e) {
@@ -5887,7 +5888,8 @@
 
         // Allow renderer debugging features if we're debuggable.
         boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
-        ThreadedRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
+        HardwareRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
+        HardwareRenderer.setPackageName(data.appInfo.packageName);
 
         /**
          * Initialize the default http proxy in this process for the reasons we set the time zone.
@@ -5954,7 +5956,7 @@
                 StrictMode.setThreadPolicyMask(oldMask);
             }
         } else {
-            ThreadedRenderer.setIsolatedProcess(true);
+            HardwareRenderer.setIsolatedProcess(true);
         }
 
         // If we use profiles, setup the dex reporter to notify package manager
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 7df8de0..9e109c5 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -28,7 +28,9 @@
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
+import android.database.ContentObserver;
 import android.media.AudioAttributes.AttributeUsage;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -36,6 +38,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.util.ArrayMap;
 
 import com.android.internal.app.IAppOpsActiveCallback;
@@ -50,6 +53,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * API for interacting with "application operation" tracking.
@@ -1608,9 +1612,65 @@
      * @hide
      */
     public static int opToDefaultMode(int op) {
+        // STOPSHIP b/118520006: Hardcode the default values once the feature is stable.
+        switch (op) {
+            // SMS permissions
+            case AppOpsManager.OP_SEND_SMS:
+            case AppOpsManager.OP_RECEIVE_SMS:
+            case AppOpsManager.OP_READ_SMS:
+            case AppOpsManager.OP_RECEIVE_WAP_PUSH:
+            case AppOpsManager.OP_RECEIVE_MMS:
+            case AppOpsManager.OP_READ_CELL_BROADCASTS:
+            // CallLog permissions
+            case AppOpsManager.OP_READ_CALL_LOG:
+            case AppOpsManager.OP_WRITE_CALL_LOG:
+            case AppOpsManager.OP_PROCESS_OUTGOING_CALLS: {
+                if (sSmsAndCallLogRestrictionEnabled.get() == 1) {
+                    return AppOpsManager.MODE_DEFAULT;
+                }
+            }
+        }
         return sOpDefaultMode[op];
     }
 
+    // STOPSHIP b/118520006: Hardcode the default values once the feature is stable.
+    private static final AtomicInteger sSmsAndCallLogRestrictionEnabled = new AtomicInteger(-1);
+
+    // STOPSHIP b/118520006: Hardcode the default values once the feature is stable.
+    static {
+        final Context context = ActivityThread.currentApplication();
+        if (context != null) {
+            sSmsAndCallLogRestrictionEnabled.set(ActivityThread.currentActivityThread()
+                        .getIntCoreSetting(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
+
+            final Uri uri =
+                    Settings.Global.getUriFor(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED);
+            context.getContentResolver().registerContentObserver(uri, false, new ContentObserver(
+                    context.getMainThreadHandler()) {
+                @Override
+                public void onChange(boolean selfChange) {
+                    sSmsAndCallLogRestrictionEnabled.set(Settings.Global.getInt(
+                            context.getContentResolver(),
+                            Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
+                }
+            });
+        }
+    }
+
+    /**
+     * Retrieve the default mode for the app op.
+     *
+     * @param appOp The app op name
+     *
+     * @return the default mode for the app op
+     *
+     * @hide
+     */
+    @SystemApi
+    public static int opToDefaultMode(@NonNull String appOp) {
+        return opToDefaultMode(strOpToOp(appOp));
+    }
+
     /**
      * Retrieve the human readable mode.
      * @hide
@@ -2258,7 +2318,7 @@
          */
         private static long sum(@NonNull long[] counts, int start, int end) {
             long totalCount = 0;
-            for (int i = start; i <= end; i++) {
+            for (int i = start; i < end; i++) {
                 totalCount += counts[i];
             }
             return totalCount;
@@ -2483,26 +2543,6 @@
         }
     }
 
-    /**
-     * Resets given app op in its default mode for app ops in the UID.
-     * This applies to all apps currently in the UID or installed in this UID in the future.
-     *
-     * @param appOp The app op.
-     * @param uid The UID for which to set the app.
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
-    @SystemApi
-    public void resetUidMode(String appOp, int uid, boolean force) {
-        int code = strOpToOp(appOp);
-        if (!(opAllowsReset(code) || force)) {
-            return;
-        }
-        int mode = opToDefaultMode(code);
-        setUidMode(code, uid, mode);
-    }
-
     /** @hide */
     public void setUserRestriction(int code, boolean restricted, IBinder token) {
         setUserRestriction(code, restricted, token, /*exceptionPackages*/null);
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index f5d5e6e..7fe21b2 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.NonNull;
 import android.util.SparseIntArray;
 
 import com.android.internal.util.function.QuadFunction;
@@ -73,4 +74,21 @@
      * access to app ops for their user.
      */
     public abstract void setDeviceAndProfileOwners(SparseIntArray owners);
+
+    /**
+     * Sets the app-ops mode for a certain app-op and uid.
+     *
+     * <p>Similar as {@link AppOpsManager#setMode} but does not require the package manager to be
+     * working. Hence this can be used very early during boot.
+     *
+     * <p>Only for internal callers. Does <u>not</u> verify that package name belongs to uid.
+     *
+     * @param code The op code to set.
+     * @param uid The UID for which to set.
+     * @param packageName The package for which to set.
+     * @param mode The new mode to set.
+     * @param isPrivileged If the package is privileged
+     */
+    public abstract void setMode(int code, int uid, @NonNull String packageName, int mode,
+            boolean isPrivileged);
 }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index fcd9a05..8bb704d 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2277,6 +2277,15 @@
     }
 
     @Override
+    public boolean canSuspendPackage(String packageName) {
+        try {
+            return mPM.canSuspendPackageForUser(packageName, mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
     public Bundle getSuspendedPackageAppExtras() {
         final PersistableBundle extras;
         try {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index dc707e8..9837deb 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -140,6 +140,13 @@
         throw new ReceiverCallNotAllowedException(
                 "BroadcastReceiver components are not allowed to bind to services");
     }
+
+    @Override
+    public boolean bindIsolatedService(Intent service, ServiceConnection conn, int flags,
+            String instanceName) {
+        throw new ReceiverCallNotAllowedException(
+                "BroadcastReceiver components are not allowed to bind to services");
+    }
 }
 
 /**
@@ -1630,14 +1637,25 @@
     public boolean bindService(Intent service, ServiceConnection conn,
             int flags) {
         warnIfCallingFromSystemProcess();
-        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
+        return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), getUser());
+    }
+
+    @Override
+    public boolean bindIsolatedService(Intent service, ServiceConnection conn,
+            int flags, String instanceName) {
+        warnIfCallingFromSystemProcess();
+        if (instanceName == null) {
+            throw new NullPointerException("null instanceName");
+        }
+        return bindServiceCommon(service, conn, flags, instanceName, mMainThread.getHandler(),
+                getUser());
     }
 
     /** @hide */
     @Override
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
             UserHandle user) {
-        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), user);
+        return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), user);
     }
 
     /** @hide */
@@ -1647,7 +1665,7 @@
         if (handler == null) {
             throw new IllegalArgumentException("handler must not be null.");
         }
-        return bindServiceCommon(service, conn, flags, handler, user);
+        return bindServiceCommon(service, conn, flags, null, handler, user);
     }
 
     /** @hide */
@@ -1669,7 +1687,8 @@
         return mMainThread.getHandler();
     }
 
-    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
+    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
+            String instanceName, Handler
             handler, UserHandle user) {
         // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
         IServiceConnection sd;
@@ -1690,10 +1709,10 @@
                 flags |= BIND_WAIVE_PRIORITY;
             }
             service.prepareToLeaveProcess(this);
-            int res = ActivityManager.getService().bindService(
+            int res = ActivityManager.getService().bindIsolatedService(
                 mMainThread.getApplicationThread(), getActivityToken(), service,
                 service.resolveTypeIfNeeded(getContentResolver()),
-                sd, flags, getOpPackageName(), user.getIdentifier());
+                sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
             if (res < 0) {
                 throw new SecurityException(
                         "Not allowed to bind to service " + service);
diff --git a/core/java/android/app/DexLoadReporter.java b/core/java/android/app/DexLoadReporter.java
index 0643414..229bee5 100644
--- a/core/java/android/app/DexLoadReporter.java
+++ b/core/java/android/app/DexLoadReporter.java
@@ -87,7 +87,7 @@
     }
 
     @Override
-    public void report(List<BaseDexClassLoader> classLoadersChain, List<String> classPaths) {
+    public void report(List<ClassLoader> classLoadersChain, List<String> classPaths) {
         if (classLoadersChain.size() != classPaths.size()) {
             Slog.wtf(TAG, "Bad call to DexLoadReporter: argument size mismatch");
             return;
@@ -113,12 +113,12 @@
         registerSecondaryDexForProfiling(dexPathsForRegistration);
     }
 
-    private void notifyPackageManager(List<BaseDexClassLoader> classLoadersChain,
+    private void notifyPackageManager(List<ClassLoader> classLoadersChain,
             List<String> classPaths) {
         // Get the class loader names for the binder call.
         List<String> classLoadersNames = new ArrayList<>(classPaths.size());
-        for (BaseDexClassLoader bdc : classLoadersChain) {
-            classLoadersNames.add(bdc.getClass().getName());
+        for (ClassLoader classLoader : classLoadersChain) {
+            classLoadersNames.add(classLoader.getClass().getName());
         }
         String packageName = ActivityThread.currentPackageName();
         try {
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 519a274..f27c667 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -133,9 +133,13 @@
             in String resolvedType, boolean requireForeground, in String callingPackage, int userId);
     int stopService(in IApplicationThread caller, in Intent service,
             in String resolvedType, int userId);
+    // Currently keeping old bindService because it is on the greylist
     int bindService(in IApplicationThread caller, in IBinder token, in Intent service,
             in String resolvedType, in IServiceConnection connection, int flags,
             in String callingPackage, int userId);
+    int bindIsolatedService(in IApplicationThread caller, in IBinder token, in Intent service,
+            in String resolvedType, in IServiceConnection connection, int flags,
+            in String instanceName, in String callingPackage, int userId);
     boolean unbindService(in IServiceConnection connection);
     void publishService(in IBinder token, in Intent intent, in IBinder service);
     void setDebugApp(in String packageName, boolean waitForDebugger, boolean persistent);
@@ -265,17 +269,6 @@
     void getMyMemoryState(out ActivityManager.RunningAppProcessInfo outInfo);
     boolean killProcessesBelowForeground(in String reason);
     UserInfo getCurrentUser();
-    /**
-     * Informs ActivityManagerService that the keyguard is showing.
-     *
-     * @param showingKeyguard True if the keyguard is showing, false otherwise.
-     * @param showingAod True if AOD is showing, false otherwise.
-     * @param secondaryDisplayShowing The displayId of the secondary display on which the keyguard
-     *        is showing, or INVALID_DISPLAY if there is no such display. Only meaningful if
-     *        showing is true.
-     */
-    void setLockScreenShown(boolean showingKeyguard, boolean showingAod,
-            int secondaryDisplayShowing);
     // This is not public because you need to be very careful in how you
     // manage your activity to make sure it is always the uid you expect.
     int getLaunchedFromUid(in IBinder activityToken);
@@ -486,7 +479,7 @@
      * instrumentation at a time. An active instrumentation is one running and
      * started from the shell.
      */
-    void startDelegateShellPermissionIdentity(int uid);
+    void startDelegateShellPermissionIdentity(int uid, in String[] permissions);
 
     /**
      * Method for the shell UID to stop deletating its permission identity to an
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index fcfcc21..09b77d5 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -118,7 +118,7 @@
     int startActivityAsCaller(in IApplicationThread caller, in String callingPackage,
             in Intent intent, in String resolvedType, in IBinder resultTo, in String resultWho,
             int requestCode, int flags, in ProfilerInfo profilerInfo, in Bundle options,
-            boolean ignoreTargetSecurity, int userId);
+            IBinder permissionToken, boolean ignoreTargetSecurity, int userId);
 
     void unhandledBack();
     boolean finishActivity(in IBinder token, int code, in Intent data, int finishTask);
@@ -193,6 +193,20 @@
             in ActivityManager.TaskDescription description, in Bitmap thumbnail);
     Point getAppTaskThumbnailSize();
     boolean releaseActivityInstance(in IBinder token);
+    /**
+     * Only callable from the system. This token grants a temporary permission to call
+     * #startActivityAsCallerWithToken. The token will time out after
+     * START_AS_CALLER_TOKEN_TIMEOUT if it is not used.
+     *
+     * @param delegatorToken The Binder token referencing the system Activity that wants to delegate
+     *        the #startActivityAsCaller to another app. The "caller" will be the caller of this
+     *        activity's token, not the delegate's caller (which is probably the delegator itself).
+     *
+     * @return Returns a token that can be given to a "delegate" app that may call
+     *         #startActivityAsCaller
+     */
+    IBinder requestStartActivityPermissionToken(in IBinder delegatorToken);
+
     void releaseSomeActivities(in IApplicationThread app);
     Bitmap getTaskDescriptionIcon(in String filename, int userId);
     void startInPlaceAnimationOnFrontMostApplication(in Bundle opts);
@@ -245,16 +259,16 @@
     ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType);
 
     /**
-     * Informs ActivityManagerService that the keyguard is showing.
+     * Informs ActivityTaskManagerService that the keyguard is showing.
      *
      * @param showingKeyguard True if the keyguard is showing, false otherwise.
      * @param showingAod True if AOD is showing, false otherwise.
-     * @param secondaryDisplayShowing The displayId of the secondary display on which the keyguard
-     *        is showing, or INVALID_DISPLAY if there is no such display. Only meaningful if
-     *        showing is true.
+     * @param secondaryDisplaysShowing The displayId's of the secondary displays on which the
+     * keyguard is showing, or {@code null} if there is no such display. Only meaningful if showing
+     * is {@code true}.
      */
     void setLockScreenShown(boolean showingKeyguard, boolean showingAod,
-            int secondaryDisplayShowing);
+            in int[] secondaryDisplaysShowing);
     Bundle getAssistContextExtras(int requestType);
     boolean launchAssistIntent(in Intent intent, int requestType, in String hint, int userHandle,
             in Bundle args);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index bd9cf6d..362f4ae 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -88,6 +88,8 @@
     ParceledListSlice getRecentNotifyingAppsForUser(int userId);
     int getBlockedAppCount(int userId);
     boolean areChannelsBypassingDnd();
+    int getAppsBypassingDndCount(int uid);
+    ParceledListSlice getNotificationChannelsBypassingDnd(String pkg, int userId);
 
     // TODO: Remove this when callers have been migrated to the equivalent
     // INotificationListener method.
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index ac4bf7d..96da72a 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -47,7 +47,7 @@
             in ParcelFileDescriptor source);
     void grantRuntimePermission(String packageName, String permission, int userId);
     void revokeRuntimePermission(String packageName, String permission, int userId);
-    void adoptShellPermissionIdentity(int uid);
+    void adoptShellPermissionIdentity(int uid, in String[] permissions);
     void dropShellPermissionIdentity();
     // Called from the system process.
     oneway void shutdown();
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 1144e26..015bc6c 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1009,7 +1009,7 @@
      * from its event processing, though it may <em>not</em> have completely
      * finished reacting from the event -- for example, if it needs to update
      * its display as a result, it may still be in the process of doing that.
-     * 
+     *
      * @param event The event to send to the current focus.
      */
     public void sendKeySync(KeyEvent event) {
@@ -1017,14 +1017,7 @@
 
         long downTime = event.getDownTime();
         long eventTime = event.getEventTime();
-        int action = event.getAction();
-        int code = event.getKeyCode();
-        int repeatCount = event.getRepeatCount();
-        int metaState = event.getMetaState();
-        int deviceId = event.getDeviceId();
-        int scancode = event.getScanCode();
         int source = event.getSource();
-        int flags = event.getFlags();
         if (source == InputDevice.SOURCE_UNKNOWN) {
             source = InputDevice.SOURCE_KEYBOARD;
         }
@@ -1034,12 +1027,14 @@
         if (downTime == 0) {
             downTime = eventTime;
         }
-        KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
-                deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
+        KeyEvent newEvent = new KeyEvent(event);
+        newEvent.setTime(downTime, eventTime);
+        newEvent.setSource(source);
+        newEvent.setFlags(event.getFlags() | KeyEvent.FLAG_FROM_SYSTEM);
         InputManager.getInstance().injectInputEvent(newEvent,
                 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
     }
-    
+
     /**
      * Sends an up and down key event sync to the currently focused window.
      * 
@@ -1902,8 +1897,8 @@
     @UnsupportedAppUsage
     public ActivityResult execStartActivityAsCaller(
             Context who, IBinder contextThread, IBinder token, Activity target,
-            Intent intent, int requestCode, Bundle options, boolean ignoreTargetSecurity,
-            int userId) {
+            Intent intent, int requestCode, Bundle options, IBinder permissionToken,
+            boolean ignoreTargetSecurity, int userId) {
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         if (mActivityMonitors != null) {
             synchronized (mSync) {
@@ -1934,7 +1929,8 @@
                 .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
                         intent.resolveTypeIfNeeded(who.getContentResolver()),
                         token, target != null ? target.mEmbeddedID : null,
-                        requestCode, 0, null, options, ignoreTargetSecurity, userId);
+                        requestCode, 0, null, options, permissionToken,
+                        ignoreTargetSecurity, userId);
             checkStartActivityResult(result, intent);
         } catch (RemoteException e) {
             throw new RuntimeException("Failure from system", e);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 6d464fb..450efdf 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -207,7 +207,8 @@
     private static final int MAX_REPLY_HISTORY = 5;
 
     /**
-     * Maximum numbers of action buttons in a notification.
+     * Maximum number of (generic) action buttons in a notification (contextual action buttons are
+     * handled separately).
      * @hide
      */
     public static final int MAX_ACTION_BUTTONS = 3;
@@ -1421,6 +1422,12 @@
          */
         public static final int SEMANTIC_ACTION_CALL = 10;
 
+        /**
+         * {@code SemanticAction}: Contextual action - dependent on the current notification. E.g.
+         * open a Map application with an address shown in the notification.
+         */
+        public static final int SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION = 11;
+
         private final Bundle mExtras;
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         private Icon mIcon;
@@ -2042,7 +2049,8 @@
                 SEMANTIC_ACTION_UNMUTE,
                 SEMANTIC_ACTION_THUMBS_UP,
                 SEMANTIC_ACTION_THUMBS_DOWN,
-                SEMANTIC_ACTION_CALL
+                SEMANTIC_ACTION_CALL,
+                SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION
         })
         @Retention(RetentionPolicy.SOURCE)
         public @interface SemanticAction {}
@@ -4457,6 +4465,7 @@
             contentView.setViewVisibility(R.id.time, View.GONE);
             contentView.setImageViewIcon(R.id.profile_badge, null);
             contentView.setViewVisibility(R.id.profile_badge, View.GONE);
+            contentView.setViewVisibility(R.id.alerted_icon, View.GONE);
             mN.mUsesStandardHeader = false;
         }
 
@@ -4961,6 +4970,18 @@
                     result);
         }
 
+        private static List<Notification.Action> filterOutContextualActions(
+                List<Notification.Action> actions) {
+            List<Notification.Action> nonContextualActions = new ArrayList<>();
+            for (Notification.Action action : actions) {
+                if (action.getSemanticAction()
+                        != Action.SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION) {
+                    nonContextualActions.add(action);
+                }
+            }
+            return nonContextualActions;
+        }
+
         private RemoteViews applyStandardTemplateWithActions(int layoutId,
                 StandardTemplateParams p, TemplateBindResult result) {
             RemoteViews big = applyStandardTemplate(layoutId, p, result);
@@ -4969,7 +4990,11 @@
 
             boolean validRemoteInput = false;
 
-            int N = mActions.size();
+            // In the UI contextual actions appear separately from the standard actions, so we
+            // filter them out here.
+            List<Notification.Action> nonContextualActions = filterOutContextualActions(mActions);
+
+            int N = nonContextualActions.size();
             boolean emphazisedMode = mN.fullScreenIntent != null && !p.ambient;
             big.setBoolean(R.id.actions, "setEmphasizedMode", emphazisedMode);
             if (N > 0) {
@@ -4978,7 +5003,8 @@
                 big.setViewLayoutMarginBottomDimen(R.id.notification_action_list_margin_target, 0);
                 if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS;
                 for (int i=0; i<N; i++) {
-                    Action action = mActions.get(i);
+                    Action action = nonContextualActions.get(i);
+
                     boolean actionHasValidInput = hasValidRemoteInput(action);
                     validRemoteInput |= actionHasValidInput;
 
@@ -5936,8 +5962,9 @@
 
     /**
      * @return whether this notification is a foreground service notification
+     * @hide
      */
-    private boolean isForegroundService() {
+    public boolean isForegroundService() {
         return (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
     }
 
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 508ea3b..0123551 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -23,6 +23,7 @@
 import android.app.admin.IDevicePolicyManager;
 import android.app.job.IJobScheduler;
 import android.app.job.JobScheduler;
+import android.app.role.RoleManager;
 import android.app.slice.SliceManager;
 import android.app.timedetector.TimeDetector;
 import android.app.timezone.RulesManager;
@@ -66,6 +67,8 @@
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.IHdmiControlService;
 import android.hardware.input.InputManager;
+import android.hardware.iris.IIrisService;
+import android.hardware.iris.IrisManager;
 import android.hardware.location.ContextHubManager;
 import android.hardware.radio.RadioManager;
 import android.hardware.usb.IUsbManager;
@@ -150,6 +153,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.euicc.EuiccCardManager;
 import android.telephony.euicc.EuiccManager;
+import android.telephony.rcs.RcsManager;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
@@ -161,6 +165,8 @@
 import android.view.autofill.AutofillManager;
 import android.view.autofill.IAutoFillManager;
 import android.view.inputmethod.InputMethodManager;
+import android.view.intelligence.IIntelligenceManager;
+import android.view.intelligence.IntelligenceManager;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textservice.TextServicesManager;
 
@@ -542,6 +548,14 @@
                 return new SubscriptionManager(ctx.getOuterContext());
             }});
 
+        registerService(Context.TELEPHONY_RCS_SERVICE, RcsManager.class,
+                new CachedServiceFetcher<RcsManager>() {
+                    @Override
+                    public RcsManager createService(ContextImpl ctx) {
+                        return new RcsManager();
+                    }
+                });
+
         registerService(Context.CARRIER_CONFIG_SERVICE, CarrierConfigManager.class,
                 new CachedServiceFetcher<CarrierConfigManager>() {
             @Override
@@ -836,16 +850,34 @@
                     }
                 });
 
+        registerService(Context.IRIS_SERVICE, IrisManager.class,
+                new CachedServiceFetcher<IrisManager>() {
+                    @Override
+                    public IrisManager createService(ContextImpl ctx)
+                        throws ServiceNotFoundException {
+                        final IBinder binder =
+                                ServiceManager.getServiceOrThrow(Context.IRIS_SERVICE);
+                        IIrisService service = IIrisService.Stub.asInterface(binder);
+                        return new IrisManager(ctx.getOuterContext(), service);
+                    }
+                });
+
         registerService(Context.BIOMETRIC_SERVICE, BiometricManager.class,
                 new CachedServiceFetcher<BiometricManager>() {
                     @Override
                     public BiometricManager createService(ContextImpl ctx)
                             throws ServiceNotFoundException {
-                        final IBinder binder =
-                                ServiceManager.getServiceOrThrow(Context.BIOMETRIC_SERVICE);
-                        final IBiometricService service =
-                                IBiometricService.Stub.asInterface(binder);
-                        return new BiometricManager(ctx.getOuterContext(), service);
+                        if (BiometricManager.hasBiometrics(ctx)) {
+                            final IBinder binder =
+                                    ServiceManager.getServiceOrThrow(Context.BIOMETRIC_SERVICE);
+                            final IBiometricService service =
+                                    IBiometricService.Stub.asInterface(binder);
+                            return new BiometricManager(ctx.getOuterContext(), service);
+                        } else {
+                            // Allow access to the manager when service is null. This saves memory
+                            // on devices without biometric hardware.
+                            return new BiometricManager(ctx.getOuterContext(), null);
+                        }
                     }
                 });
 
@@ -1018,6 +1050,17 @@
                 return new AutofillManager(ctx.getOuterContext(), service);
             }});
 
+        registerService(Context.INTELLIGENCE_MANAGER_SERVICE, IntelligenceManager.class,
+                new CachedServiceFetcher<IntelligenceManager>() {
+            @Override
+            public IntelligenceManager createService(ContextImpl ctx)
+                    throws ServiceNotFoundException {
+                // Get the services without throwing as this is an optional feature
+                IBinder b = ServiceManager.getService(Context.INTELLIGENCE_MANAGER_SERVICE);
+                IIntelligenceManager service = IIntelligenceManager.Stub.asInterface(b);
+                return new IntelligenceManager(ctx.getOuterContext(), service);
+            }});
+
         registerService(Context.VR_SERVICE, VrManager.class, new CachedServiceFetcher<VrManager>() {
             @Override
             public VrManager createService(ContextImpl ctx) throws ServiceNotFoundException {
@@ -1087,6 +1130,14 @@
                     public PermissionManager createService(ContextImpl ctx) {
                         return new PermissionManager(ctx.getOuterContext());
                     }});
+
+        registerService(Context.ROLE_SERVICE, RoleManager.class,
+                new CachedServiceFetcher<RoleManager>() {
+                    @Override
+                    public RoleManager createService(ContextImpl ctx)
+                            throws ServiceNotFoundException {
+                        return new RoleManager(ctx.getOuterContext());
+                    }});
     }
 
     /**
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 5a25f5a..3f9627e 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -354,12 +354,17 @@
     }
 
     /**
-     * Adopt the permission identity of the shell UID. This allows you to call APIs protected
-     * permissions which normal apps cannot hold but are granted to the shell UID. If you
-     * already adopted the shell permission identity this method would be a no-op.
-     * Note that your permission state becomes that of the shell UID and it is not a
-     * combination of your and the shell UID permissions.
+     * Adopt the permission identity of the shell UID for all permissions. This allows
+     * you to call APIs protected permissions which normal apps cannot hold but are
+     * granted to the shell UID. If you already adopted all shell permissions by calling
+     * this method or {@link #adoptShellPermissionIdentity(String...)} a subsequent call
+     * would be a no-op. Note that your permission state becomes that of the shell UID
+     * and it is not a combination of your and the shell UID permissions.
+     * <p>
+     * <strong>Note:<strong/> Calling this method adopts all shell permissions and overrides
+     * any subset of adopted permissions via {@link #adoptShellPermissionIdentity(String...)}.
      *
+     * @see #adoptShellPermissionIdentity(String...)
      * @see #dropShellPermissionIdentity()
      */
     public void adoptShellPermissionIdentity() {
@@ -368,7 +373,33 @@
         }
         try {
             // Calling out without a lock held.
-            mUiAutomationConnection.adoptShellPermissionIdentity(Process.myUid());
+            mUiAutomationConnection.adoptShellPermissionIdentity(Process.myUid(), null);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error executing adopting shell permission identity!", re);
+        }
+    }
+
+    /**
+     * Adopt the permission identity of the shell UID only for the provided permissions.
+     * This allows you to call APIs protected permissions which normal apps cannot hold
+     * but are granted to the shell UID. If you already adopted the specified shell
+     * permissions by calling this method or {@link #adoptShellPermissionIdentity()} a
+     * subsequent call would be a no-op. Note that your permission state becomes that of the
+     * shell UID and it is not a combination of your and the shell UID permissions.
+     * <p>
+     * <strong>Note:<strong/> Calling this method adopts only the specified shell permissions
+     * and overrides all adopted permissions via {@link #adoptShellPermissionIdentity()}.
+     *
+     * @see #adoptShellPermissionIdentity()
+     * @see #dropShellPermissionIdentity()
+     */
+    public void adoptShellPermissionIdentity(String... permissions) {
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+        }
+        try {
+            // Calling out without a lock held.
+            mUiAutomationConnection.adoptShellPermissionIdentity(Process.myUid(), permissions);
         } catch (RemoteException re) {
             Log.e(LOG_TAG, "Error executing adopting shell permission identity!", re);
         }
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index b406d9e..dc2f983 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -18,7 +18,7 @@
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.IAccessibilityServiceClient;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.IPackageManager;
 import android.graphics.Bitmap;
@@ -279,7 +279,8 @@
     }
 
     @Override
-    public void adoptShellPermissionIdentity(int uid) throws RemoteException {
+    public void adoptShellPermissionIdentity(int uid, @Nullable String[] permissions)
+            throws RemoteException {
         synchronized (mLock) {
             throwIfCalledByNotTrustedUidLocked();
             throwIfShutdownLocked();
@@ -287,7 +288,7 @@
         }
         final long identity = Binder.clearCallingIdentity();
         try {
-            mActivityManager.startDelegateShellPermissionIdentity(uid);
+            mActivityManager.startDelegateShellPermissionIdentity(uid, permissions);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 096c7aa..78b7d48 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -20,6 +20,7 @@
 import static android.app.WindowConfigurationProto.ACTIVITY_TYPE;
 import static android.app.WindowConfigurationProto.APP_BOUNDS;
 import static android.app.WindowConfigurationProto.WINDOWING_MODE;
+import static android.view.Surface.rotationToString;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -60,6 +61,17 @@
      */
     private Rect mAppBounds;
 
+    /**
+     * The current rotation of this window container relative to the default
+     * orientation of the display it is on (regardless of how deep in the hierarchy
+     * it is). It is used by the configuration hierarchy to apply rotation-dependent
+     * policy during bounds calculation.
+     */
+    private int mRotation = ROTATION_UNDEFINED;
+
+    /** Rotation is not defined, use the parent containers rotation. */
+    public static final int ROTATION_UNDEFINED = -1;
+
     /** The current windowing mode of the configuration. */
     private @WindowingMode int mWindowingMode;
 
@@ -161,6 +173,9 @@
     /** Bit that indicates that the {@link #mAlwaysOnTop} changed.
      * @hide */
     public static final int WINDOW_CONFIG_ALWAYS_ON_TOP = 1 << 4;
+    /** Bit that indicates that the {@link #mRotation} changed.
+     * @hide */
+    public static final int WINDOW_CONFIG_ROTATION = 1 << 5;
     /** @hide */
     @IntDef(flag = true, prefix = { "WINDOW_CONFIG_" }, value = {
             WINDOW_CONFIG_BOUNDS,
@@ -168,6 +183,7 @@
             WINDOW_CONFIG_WINDOWING_MODE,
             WINDOW_CONFIG_ACTIVITY_TYPE,
             WINDOW_CONFIG_ALWAYS_ON_TOP,
+            WINDOW_CONFIG_ROTATION,
     })
     public @interface WindowConfig {}
 
@@ -194,6 +210,7 @@
         dest.writeInt(mWindowingMode);
         dest.writeInt(mActivityType);
         dest.writeInt(mAlwaysOnTop);
+        dest.writeInt(mRotation);
     }
 
     private void readFromParcel(Parcel source) {
@@ -202,6 +219,7 @@
         mWindowingMode = source.readInt();
         mActivityType = source.readInt();
         mAlwaysOnTop = source.readInt();
+        mRotation = source.readInt();
     }
 
     @Override
@@ -287,6 +305,14 @@
         return mBounds;
     }
 
+    public int getRotation() {
+        return mRotation;
+    }
+
+    public void setRotation(int rotation) {
+        mRotation = rotation;
+    }
+
     public void setWindowingMode(@WindowingMode int windowingMode) {
         mWindowingMode = windowingMode;
     }
@@ -324,6 +350,7 @@
         setWindowingMode(other.mWindowingMode);
         setActivityType(other.mActivityType);
         setAlwaysOnTop(other.mAlwaysOnTop);
+        setRotation(other.mRotation);
     }
 
     /** Set this object to completely undefined.
@@ -339,6 +366,7 @@
         setWindowingMode(WINDOWING_MODE_UNDEFINED);
         setActivityType(ACTIVITY_TYPE_UNDEFINED);
         setAlwaysOnTop(ALWAYS_ON_TOP_UNDEFINED);
+        setRotation(ROTATION_UNDEFINED);
     }
 
     /**
@@ -375,6 +403,10 @@
             changed |= WINDOW_CONFIG_ALWAYS_ON_TOP;
             setAlwaysOnTop(delta.mAlwaysOnTop);
         }
+        if (delta.mRotation != ROTATION_UNDEFINED && delta.mRotation != mRotation) {
+            changed |= WINDOW_CONFIG_ROTATION;
+            setRotation(delta.mRotation);
+        }
         return changed;
     }
 
@@ -418,6 +450,11 @@
             changes |= WINDOW_CONFIG_ALWAYS_ON_TOP;
         }
 
+        if ((compareUndefined || other.mRotation != ROTATION_UNDEFINED)
+                && mRotation != other.mRotation) {
+            changes |= WINDOW_CONFIG_ROTATION;
+        }
+
         return changes;
     }
 
@@ -454,6 +491,8 @@
         if (n != 0) return n;
         n = mAlwaysOnTop - that.mAlwaysOnTop;
         if (n != 0) return n;
+        n = mRotation - that.mRotation;
+        if (n != 0) return n;
 
         // if (n != 0) return n;
         return n;
@@ -482,6 +521,7 @@
         result = 31 * result + mWindowingMode;
         result = 31 * result + mActivityType;
         result = 31 * result + mAlwaysOnTop;
+        result = 31 * result + mRotation;
         return result;
     }
 
@@ -493,6 +533,8 @@
                 + " mWindowingMode=" + windowingModeToString(mWindowingMode)
                 + " mActivityType=" + activityTypeToString(mActivityType)
                 + " mAlwaysOnTop=" + alwaysOnTopToString(mAlwaysOnTop)
+                + " mRotation=" + (mRotation == ROTATION_UNDEFINED
+                        ? "undefined" : rotationToString(mRotation))
                 + "}";
     }
 
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 43f902a..cc4d4b1a 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -61,37 +61,39 @@
  * <a href="/guide/topics/text/autofill">Autofill Framework</a> guides.
  */
 public class AssistStructure implements Parcelable {
-    static final String TAG = "AssistStructure";
+    private static final String TAG = "AssistStructure";
 
-    static final boolean DEBUG_PARCEL = false;
-    static final boolean DEBUG_PARCEL_CHILDREN = false;
-    static final boolean DEBUG_PARCEL_TREE = false;
+    private static final boolean DEBUG_PARCEL = false;
+    private static final boolean DEBUG_PARCEL_CHILDREN = false;
+    private static final boolean DEBUG_PARCEL_TREE = false;
 
-    static final int VALIDATE_WINDOW_TOKEN = 0x11111111;
-    static final int VALIDATE_VIEW_TOKEN = 0x22222222;
+    private static final int VALIDATE_WINDOW_TOKEN = 0x11111111;
+    private static final int VALIDATE_VIEW_TOKEN = 0x22222222;
 
-    boolean mHaveData;
+    private boolean mHaveData;
 
-    ComponentName mActivityComponent;
+    // The task id and component of the activity which this assist structure is for
+    private int mTaskId;
+    private ComponentName mActivityComponent;
     private boolean mIsHomeActivity;
     private int mFlags;
     private int mAutofillFlags;
 
-    final ArrayList<WindowNode> mWindowNodes = new ArrayList<>();
+    private final ArrayList<WindowNode> mWindowNodes = new ArrayList<>();
 
-    final ArrayList<ViewNodeBuilder> mPendingAsyncChildren = new ArrayList<>();
+    private final ArrayList<ViewNodeBuilder> mPendingAsyncChildren = new ArrayList<>();
 
-    SendChannel mSendChannel;
-    IBinder mReceiveChannel;
+    private SendChannel mSendChannel;
+    private IBinder mReceiveChannel;
 
-    Rect mTmpRect = new Rect();
+    private Rect mTmpRect = new Rect();
 
-    boolean mSanitizeOnWrite = false;
+    private boolean mSanitizeOnWrite = false;
     private long mAcquisitionStartTime;
     private long mAcquisitionEndTime;
 
-    static final int TRANSACTION_XFER = Binder.FIRST_CALL_TRANSACTION+1;
-    static final String DESCRIPTOR = "android.app.AssistStructure";
+    private static final int TRANSACTION_XFER = Binder.FIRST_CALL_TRANSACTION+1;
+    private static final String DESCRIPTOR = "android.app.AssistStructure";
 
     /** @hide */
     public void setAcquisitionStartTime(long acquisitionStartTime) {
@@ -197,7 +199,6 @@
         ParcelTransferWriter(AssistStructure as, Parcel out) {
             mSanitizeOnWrite = as.mSanitizeOnWrite;
             mWriteStructure = as.waitForReady();
-            ComponentName.writeToParcel(as.mActivityComponent, out);
             out.writeInt(as.mFlags);
             out.writeInt(as.mAutofillFlags);
             out.writeLong(as.mAcquisitionStartTime);
@@ -353,7 +354,6 @@
 
         void go() {
             fetchData();
-            mActivityComponent = ComponentName.readFromParcel(mCurParcel);
             mFlags = mCurParcel.readInt();
             mAutofillFlags = mCurParcel.readInt();
             mAcquisitionStartTime = mCurParcel.readLong();
@@ -2129,7 +2129,6 @@
     /** @hide */
     public AssistStructure(Activity activity, boolean forAutoFill, int flags) {
         mHaveData = true;
-        mActivityComponent = activity.getComponentName();
         mFlags = flags;
         ArrayList<ViewRootImpl> views = WindowManagerGlobal.getInstance().getRootViews(
                 activity.getActivityToken());
@@ -2145,12 +2144,13 @@
 
     public AssistStructure() {
         mHaveData = true;
-        mActivityComponent = null;
         mFlags = 0;
     }
 
     /** @hide */
     public AssistStructure(Parcel in) {
+        mTaskId = in.readInt();
+        mActivityComponent = ComponentName.readFromParcel(in);
         mIsHomeActivity = in.readInt() == 1;
         mReceiveChannel = in.readStrongBinder();
     }
@@ -2171,7 +2171,10 @@
             Log.i(TAG, "dump(): calling ensureData() first");
             ensureData();
         }
-        Log.i(TAG, "Activity: " + mActivityComponent.flattenToShortString());
+        Log.i(TAG, "Task id: " + mTaskId);
+        Log.i(TAG, "Activity: " + (mActivityComponent != null 
+                ? mActivityComponent.flattenToShortString()
+                : null));
         Log.i(TAG, "Sanitize on write: " + mSanitizeOnWrite);
         Log.i(TAG, "Flags: " + mFlags);
         final int N = getWindowNodeCount();
@@ -2283,23 +2286,37 @@
     }
 
     /**
-     * Return the activity this AssistStructure came from.
+     * Sets the task id is associated with the activity from which this AssistStructure was
+     * generated.
+     * @hide
      */
-    public ComponentName getActivityComponent() {
-        ensureData();
-        return mActivityComponent;
+    public void setTaskId(int taskId) {
+        mTaskId = taskId;
     }
 
     /**
-     * Called by Autofill server when app forged a different value.
-     *
+     * @return The task id for the associated activity.
+     * @hide
+     */
+    public int getTaskId() {
+        return mTaskId;
+    }
+
+    /**
+     * Sets the activity that is associated with this AssistStructure.
      * @hide
      */
     public void setActivityComponent(ComponentName componentName) {
-        ensureData();
         mActivityComponent = componentName;
     }
 
+    /**
+     * Return the activity this AssistStructure came from.
+     */
+    public ComponentName getActivityComponent() {
+        return mActivityComponent;
+    }
+
     /** @hide */
     public int getFlags() {
         return mFlags;
@@ -2393,6 +2410,8 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mTaskId);
+        ComponentName.writeToParcel(mActivityComponent, out);
         out.writeInt(mIsHomeActivity ? 1 : 0);
         if (mHaveData) {
             // This object holds its data.  We want to write a send channel that the
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 308b39e..3a5975a 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -50,12 +50,20 @@
         public static final int NONE = 0;
 
         /**
-         * An event type denoting that a component moved to the foreground.
+         * An event type denoting that an {@link android.app.Activity} moved to the foreground.
+         * This event has a package name and class name associated with it and can be retrieved
+         * using {@link #getPackageName()} and {@link #getClassName()}.
+         * If a package has multiple activities, this event is reported for each activity that moves
+         * to foreground.
          */
         public static final int MOVE_TO_FOREGROUND = 1;
 
         /**
-         * An event type denoting that a component moved to the background.
+         * An event type denoting that an {@link android.app.Activity} moved to the background.
+         * This event has a package name and class name associated with it and can be retrieved
+         * using {@link #getPackageName()} and {@link #getClassName()}.
+         * If a package has multiple activities, this event is reported for each activity that moves
+         * to background.
          */
         public static final int MOVE_TO_BACKGROUND = 2;
 
@@ -166,10 +174,43 @@
         public static final int KEYGUARD_HIDDEN = 18;
 
         /**
+         * An event type denoting start of a foreground service.
+         * This event has a package name and class name associated with it and can be retrieved
+         * using {@link #getPackageName()} and {@link #getClassName()}.
+         * If a package has multiple foreground services, this event is reported for each service
+         * that is started.
+         */
+        public static final int FOREGROUND_SERVICE_START = 19;
+
+        /**
+         * An event type denoting stop of a foreground service.
+         * This event has a package name and class name associated with it and can be retrieved
+         * using {@link #getPackageName()} and {@link #getClassName()}.
+         * If a package has multiple foreground services, this event is reported for each service
+         * that is stopped.
+         */
+        public static final int FOREGROUND_SERVICE_STOP = 20;
+
+        /**
+         * An event type denoting that a foreground service is at started state at beginning of a
+         * time interval.
+         * This is effectively treated as a {@link #FOREGROUND_SERVICE_START}.
+         * {@hide}
+         */
+        public static final int CONTINUING_FOREGROUND_SERVICE = 21;
+
+        /**
+         * An event type denoting that a foreground service is at started state when the stats
+         * rolled-over at the end of a time interval.
+         * {@hide}
+         */
+        public static final int ROLLOVER_FOREGROUND_SERVICE = 22;
+
+        /**
          * Keep in sync with the greatest event type value.
          * @hide
          */
-        public static final int MAX_EVENT_TYPE = 18;
+        public static final int MAX_EVENT_TYPE = 22;
 
         /** @hide */
         public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 0659a23..73426e4 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -16,6 +16,15 @@
 
 package android.app.usage;
 
+import static android.app.usage.UsageEvents.Event.CONTINUE_PREVIOUS_DAY;
+import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
+import static android.app.usage.UsageEvents.Event.END_OF_DAY;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
+import static android.app.usage.UsageEvents.Event.MOVE_TO_BACKGROUND;
+import static android.app.usage.UsageEvents.Event.MOVE_TO_FOREGROUND;
+import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
+
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
@@ -48,19 +57,32 @@
     public long mEndTimeStamp;
 
     /**
-     * Last time used by the user with an explicit action (notification, activity launch).
+     * Last time used by the user with an explicit action (notification, activity launch)
      * {@hide}
      */
     @UnsupportedAppUsage
     public long mLastTimeUsed;
 
     /**
+     * Total time this package's activity is in foreground.
      * {@hide}
      */
     @UnsupportedAppUsage
     public long mTotalTimeInForeground;
 
     /**
+     * Last time foreground service is started.
+     * {@hide}
+     */
+    public long mLastTimeForegroundServiceUsed;
+
+    /**
+     * Total time this package's foreground service is started.
+     * {@hide}
+     */
+    public long mTotalTimeForegroundServiceUsed;
+
+    /**
      * {@hide}
      */
     @UnsupportedAppUsage
@@ -71,16 +93,36 @@
      */
     public int mAppLaunchCount;
 
-    /**
+    /** Last activity MOVE_TO_FOREGROUND or MOVE_TO_BACKGROUND event.
      * {@hide}
+     * @deprecated use {@link #mLastForegroundActivityEventMap} instead.
      */
     @UnsupportedAppUsage
+    @Deprecated
     public int mLastEvent;
 
     /**
+     * If an activity is in foreground, it has one entry in this map.
+     * When activity moves to background, it is removed from this map.
+     * Key is activity class name.
+     * Value is last time this activity MOVE_TO_FOREGROUND or MOVE_TO_BACKGROUND event.
+     * {@hide}
+     */
+    public ArrayMap<String, Integer> mLastForegroundActivityEventMap = new ArrayMap<>();
+
+    /**
+     * If a foreground service is started, it has one entry in this map.
+     * When a foreground service is stopped, it is removed from this map.
+     * Key is foreground service class name.
+     * Value is last foreground service FOREGROUND_SERVICE_START ot FOREGROUND_SERVICE_STOP event.
+     * {@hide}
+     */
+    public ArrayMap<String, Integer> mLastForegroundServiceEventMap = new ArrayMap<>();
+
+    /**
      * {@hide}
      */
-    public ArrayMap<String, ArrayMap<String, Integer>> mChooserCounts;
+    public ArrayMap<String, ArrayMap<String, Integer>> mChooserCounts = new ArrayMap<>();
 
     /**
      * {@hide}
@@ -93,10 +135,14 @@
         mBeginTimeStamp = stats.mBeginTimeStamp;
         mEndTimeStamp = stats.mEndTimeStamp;
         mLastTimeUsed = stats.mLastTimeUsed;
+        mLastTimeForegroundServiceUsed = stats.mLastTimeForegroundServiceUsed;
         mTotalTimeInForeground = stats.mTotalTimeInForeground;
+        mTotalTimeForegroundServiceUsed = stats.mTotalTimeForegroundServiceUsed;
         mLaunchCount = stats.mLaunchCount;
         mAppLaunchCount = stats.mAppLaunchCount;
         mLastEvent = stats.mLastEvent;
+        mLastForegroundActivityEventMap = stats.mLastForegroundActivityEventMap;
+        mLastForegroundServiceEventMap = stats.mLastForegroundServiceEventMap;
         mChooserCounts = stats.mChooserCounts;
     }
 
@@ -136,7 +182,7 @@
     }
 
     /**
-     * Get the last time this package was used, measured in milliseconds since the epoch.
+     * Get the last time this package's activity was used, measured in milliseconds since the epoch.
      * <p/>
      * See {@link System#currentTimeMillis()}.
      */
@@ -152,6 +198,23 @@
     }
 
     /**
+     * Get the last time this package's foreground service was used, measured in milliseconds since
+     * the epoch.
+     * <p/>
+     * See {@link System#currentTimeMillis()}.
+     */
+    public long getLastTimeForegroundServiceUsed() {
+        return mLastTimeForegroundServiceUsed;
+    }
+
+    /**
+     * Get the total time this package's foreground services are started, measured in milliseconds.
+     */
+    public long getTotalTimeForegroundServiceUsed() {
+        return mTotalTimeForegroundServiceUsed;
+    }
+
+    /**
      * Returns the number of times the app was launched as an activity from outside of the app.
      * Excludes intra-app activity transitions.
      * @hide
@@ -161,6 +224,19 @@
         return mAppLaunchCount;
     }
 
+    private void mergeEventMap(ArrayMap<String, Integer> left, ArrayMap<String, Integer> right) {
+        final int size = right.size();
+        for (int i = 0; i < size; i++) {
+            final String className = right.keyAt(i);
+            final Integer event = right.valueAt(i);
+            if (left.containsKey(className)) {
+                left.put(className, Math.max(left.get(className), event));
+            } else {
+                left.put(className, event);
+            }
+        }
+    }
+
     /**
      * Add the statistics from the right {@link UsageStats} to the left. The package name for
      * both {@link UsageStats} objects must be the same.
@@ -179,12 +255,16 @@
         if (right.mBeginTimeStamp > mBeginTimeStamp) {
             // Even though incoming UsageStat begins after this one, its last time used fields
             // may somehow be empty or chronologically preceding the older UsageStat.
-            mLastEvent = Math.max(mLastEvent, right.mLastEvent);
+            mergeEventMap(mLastForegroundActivityEventMap, right.mLastForegroundActivityEventMap);
+            mergeEventMap(mLastForegroundServiceEventMap, right.mLastForegroundServiceEventMap);
             mLastTimeUsed = Math.max(mLastTimeUsed, right.mLastTimeUsed);
+            mLastTimeForegroundServiceUsed = Math.max(mLastTimeForegroundServiceUsed,
+                    right.mLastTimeForegroundServiceUsed);
         }
         mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
         mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
         mTotalTimeInForeground += right.mTotalTimeInForeground;
+        mTotalTimeForegroundServiceUsed += right.mTotalTimeForegroundServiceUsed;
         mLaunchCount += right.mLaunchCount;
         mAppLaunchCount += right.mAppLaunchCount;
         if (mChooserCounts == null) {
@@ -209,6 +289,161 @@
         }
     }
 
+    /**
+     * Tell if an event indicate activity is in foreground or not.
+     * @param event the activity event.
+     * @return true if activity is in foreground, false otherwise.
+     * @hide
+     */
+    private boolean isActivityInForeground(int event) {
+        return event == MOVE_TO_FOREGROUND
+                || event == CONTINUE_PREVIOUS_DAY;
+    }
+
+    /**
+     * Tell if an event indicate foreground sevice is started or not.
+     * @param event the foreground service event.
+     * @return true if foreground service is started, false if stopped.
+     * @hide
+     */
+    private boolean isForegroundServiceStarted(int event) {
+        return event == FOREGROUND_SERVICE_START
+                || event == CONTINUING_FOREGROUND_SERVICE;
+    }
+
+    /**
+     * If any activity in foreground or any foreground service is started, the app is considered in
+     * use.
+     * @return true if in use, false otherwise.
+     * @hide
+     */
+    private boolean isAppInUse() {
+        return !mLastForegroundActivityEventMap.isEmpty()
+                || !mLastForegroundServiceEventMap.isEmpty();
+    }
+
+    /**
+     * Update by an event of an activity.
+     * @param className className of the activity.
+     * @param timeStamp timeStamp of the event.
+     * @param eventType type of the event.
+     * @hide
+     */
+    private void updateForegroundActivity(String className, long timeStamp, int eventType) {
+        if (eventType != MOVE_TO_BACKGROUND
+                && eventType != MOVE_TO_FOREGROUND
+                && eventType != END_OF_DAY) {
+            return;
+        }
+
+        final Integer lastEvent = mLastForegroundActivityEventMap.get(className);
+        if (lastEvent != null) {
+            if (isActivityInForeground(lastEvent)) {
+                if (timeStamp > mLastTimeUsed) {
+                    mTotalTimeInForeground += timeStamp - mLastTimeUsed;
+                    mLastTimeUsed = timeStamp;
+                }
+            }
+            if (eventType == MOVE_TO_BACKGROUND) {
+                mLastForegroundActivityEventMap.remove(className);
+            } else {
+                mLastForegroundActivityEventMap.put(className, eventType);
+            }
+        } else if (eventType == MOVE_TO_FOREGROUND) {
+            if (!isAppInUse()) {
+                mLastTimeUsed = timeStamp;
+            }
+            mLastForegroundActivityEventMap.put(className, eventType);
+        }
+    }
+
+    /**
+     * Update by an event of an foreground service.
+     * @param className className of the foreground service.
+     * @param timeStamp timeStamp of the event.
+     * @param eventType type of the event.
+     * @hide
+     */
+    private void updateForegroundService(String className, long timeStamp, int eventType) {
+        if (eventType != FOREGROUND_SERVICE_STOP
+                && eventType != FOREGROUND_SERVICE_START
+                && eventType != ROLLOVER_FOREGROUND_SERVICE) {
+            return;
+        }
+        final Integer lastEvent = mLastForegroundServiceEventMap.get(className);
+        if (lastEvent != null) {
+            if (isForegroundServiceStarted(lastEvent)) {
+                if (timeStamp > mLastTimeForegroundServiceUsed) {
+                    mTotalTimeForegroundServiceUsed +=
+                            timeStamp - mLastTimeForegroundServiceUsed;
+                    mLastTimeForegroundServiceUsed = timeStamp;
+                }
+            }
+            if (eventType == FOREGROUND_SERVICE_STOP) {
+                mLastForegroundServiceEventMap.remove(className);
+            } else {
+                mLastForegroundServiceEventMap.put(className, eventType);
+            }
+        } else if (eventType == FOREGROUND_SERVICE_START) {
+            if (!isAppInUse()) {
+                mLastTimeForegroundServiceUsed = timeStamp;
+            }
+            mLastForegroundServiceEventMap.put(className, eventType);
+        }
+    }
+
+    /**
+     * Update the UsageStats by a activity or foreground service event.
+     * @param className class name of a activity or foreground service, could be null to mark
+     *                  END_OF_DAY or rollover.
+     * @param timeStamp Epoch timestamp in milliseconds.
+     * @param eventType event type as in {@link UsageEvents.Event}
+     * @hide
+     */
+    public void update(String className, long timeStamp, int eventType) {
+        switch(eventType) {
+            case MOVE_TO_BACKGROUND:
+            case MOVE_TO_FOREGROUND:
+                updateForegroundActivity(className, timeStamp, eventType);
+                break;
+            case END_OF_DAY:
+                // END_OF_DAY means updating all activities.
+                final int size = mLastForegroundActivityEventMap.size();
+                for (int i = 0; i < size; i++) {
+                    final String name = mLastForegroundActivityEventMap.keyAt(i);
+                    updateForegroundActivity(name, timeStamp, eventType);
+                }
+                break;
+            case CONTINUE_PREVIOUS_DAY:
+                mLastTimeUsed = timeStamp;
+                mLastForegroundActivityEventMap.put(className, eventType);
+                break;
+            case FOREGROUND_SERVICE_STOP:
+            case FOREGROUND_SERVICE_START:
+                updateForegroundService(className, timeStamp, eventType);
+                break;
+            case ROLLOVER_FOREGROUND_SERVICE:
+                // ROLLOVER_FOREGROUND_SERVICE means updating all foreground services.
+                final int size2 = mLastForegroundServiceEventMap.size();
+                for (int i = 0; i < size2; i++) {
+                    final String name = mLastForegroundServiceEventMap.keyAt(i);
+                    updateForegroundService(name, timeStamp, eventType);
+                }
+                break;
+            case CONTINUING_FOREGROUND_SERVICE:
+                mLastTimeForegroundServiceUsed = timeStamp;
+                mLastForegroundServiceEventMap.put(className, eventType);
+                break;
+            default:
+                break;
+        }
+        mEndTimeStamp = timeStamp;
+
+        if (eventType == MOVE_TO_FOREGROUND) {
+            mLaunchCount += 1;
+        }
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -220,7 +455,9 @@
         dest.writeLong(mBeginTimeStamp);
         dest.writeLong(mEndTimeStamp);
         dest.writeLong(mLastTimeUsed);
+        dest.writeLong(mLastTimeForegroundServiceUsed);
         dest.writeLong(mTotalTimeInForeground);
+        dest.writeLong(mTotalTimeForegroundServiceUsed);
         dest.writeInt(mLaunchCount);
         dest.writeInt(mAppLaunchCount);
         dest.writeInt(mLastEvent);
@@ -239,6 +476,22 @@
             }
         }
         dest.writeBundle(allCounts);
+
+        final Bundle foregroundActivityEventBundle = new Bundle();
+        final int foregroundEventSize = mLastForegroundActivityEventMap.size();
+        for (int i = 0; i < foregroundEventSize; i++) {
+            foregroundActivityEventBundle.putInt(mLastForegroundActivityEventMap.keyAt(i),
+                    mLastForegroundActivityEventMap.valueAt(i));
+        }
+        dest.writeBundle(foregroundActivityEventBundle);
+
+        final Bundle foregroundServiceEventBundle = new Bundle();
+        final int foregroundServiceEventSize = mLastForegroundServiceEventMap.size();
+        for (int i = 0; i < foregroundServiceEventSize; i++) {
+            foregroundServiceEventBundle.putInt(mLastForegroundServiceEventMap.keyAt(i),
+                    mLastForegroundServiceEventMap.valueAt(i));
+        }
+        dest.writeBundle(foregroundServiceEventBundle);
     }
 
     public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
@@ -249,7 +502,9 @@
             stats.mBeginTimeStamp = in.readLong();
             stats.mEndTimeStamp = in.readLong();
             stats.mLastTimeUsed = in.readLong();
+            stats.mLastTimeForegroundServiceUsed = in.readLong();
             stats.mTotalTimeInForeground = in.readLong();
+            stats.mTotalTimeForegroundServiceUsed = in.readLong();
             stats.mLaunchCount = in.readInt();
             stats.mAppLaunchCount = in.readInt();
             stats.mLastEvent = in.readInt();
@@ -272,9 +527,20 @@
                     }
                 }
             }
+            readBundleToEventMap(stats.mLastForegroundActivityEventMap, in.readBundle());
+            readBundleToEventMap(stats.mLastForegroundServiceEventMap, in.readBundle());
             return stats;
         }
 
+        private void readBundleToEventMap(ArrayMap<String, Integer> eventMap, Bundle bundle) {
+            if (bundle != null) {
+                for (String className : bundle.keySet()) {
+                    final int event = bundle.getInt(className);
+                    eventMap.put(className, event);
+                }
+            }
+        }
+
         @Override
         public UsageStats[] newArray(int size) {
             return new UsageStats[size];
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 6d7400e..5514851 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -192,7 +192,10 @@
     public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE = 0x000C;
     /** @hide */
     public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000D;
-
+    /** @hide */
+    public static final int REASON_SUB_USAGE_FOREGROUND_SERVICE_START = 0x000E;
+    /** @hide */
+    public static final int REASON_SUB_USAGE_FOREGROUND_SERVICE_STOP = 0x000F;
     /** @hide */
     public static final int REASON_SUB_PREDICTED_RESTORED       = 0x0001;
 
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index c6e94c7..318dbee 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -24,6 +24,8 @@
 import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.graphics.Color;
@@ -622,6 +624,7 @@
                     }
                 }
                 defaultView = inflater.inflate(layoutId, this, false);
+                defaultView.setOnClickListener(this::onDefaultViewClicked);
             } else {
                 Log.w(TAG, "can't inflate defaultView because mInfo is missing");
             }
@@ -641,6 +644,19 @@
         return defaultView;
     }
 
+    private void onDefaultViewClicked(View view) {
+        if (mInfo != null) {
+            LauncherApps launcherApps = getContext().getSystemService(LauncherApps.class);
+            List<LauncherActivityInfo> activities = launcherApps.getActivityList(
+                    mInfo.provider.getPackageName(), mInfo.getProfile());
+            if (!activities.isEmpty()) {
+                LauncherActivityInfo ai = activities.get(0);
+                launcherApps.startMainActivity(ai.getComponentName(), ai.getUser(),
+                        RemoteViews.getSourceBounds(view), null);
+            }
+        }
+    }
+
     /**
      * Inflate and return a view that represents an error state.
      */
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index ed3d455..8777b67 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -27,6 +27,7 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 import android.os.StrictMode;
 import android.text.Html;
@@ -170,6 +171,11 @@
     static final String[] MIMETYPES_TEXT_INTENT = new String[] {
         ClipDescription.MIMETYPE_TEXT_INTENT };
 
+    // Constants used in {@link #writeHtmlTextToParcel}.
+    static final int PARCEL_MAX_SIZE_BYTES = 800 * 1024;
+    static final int PARCEL_TYPE_STRING = 0;
+    static final int PARCEL_TYPE_PFD = 1;
+
     final ClipDescription mClipDescription;
 
     final Bitmap mIcon;
@@ -225,6 +231,10 @@
          * with an alternative HTML formatted representation.  You <em>must</em>
          * supply a plain text representation in addition to HTML text; coercion
          * will not be done from HTML formatted text into plain text.
+         * <p class="note"><strong>Note:</strong> It is strongly recommended to
+         * use content: URI for sharing large clip data. Starting on API 30,
+         * ClipData.Item doesn't accept an HTML text if it's larger than 800KB.
+         * </p>
          */
         public Item(CharSequence text, String htmlText) {
             mText = text;
@@ -1132,7 +1142,7 @@
         for (int i=0; i<N; i++) {
             Item item = mItems.get(i);
             TextUtils.writeToParcel(item.mText, dest, flags);
-            dest.writeString(item.mHtmlText);
+            writeHtmlTextToParcel(item.mHtmlText, dest, flags);
             if (item.mIntent != null) {
                 dest.writeInt(1);
                 item.mIntent.writeToParcel(dest, flags);
@@ -1159,7 +1169,7 @@
         final int N = in.readInt();
         for (int i=0; i<N; i++) {
             CharSequence text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
-            String htmlText = in.readString();
+            String htmlText = readHtmlTextFromParcel(in);
             Intent intent = in.readInt() != 0 ? Intent.CREATOR.createFromParcel(in) : null;
             Uri uri = in.readInt() != 0 ? Uri.CREATOR.createFromParcel(in) : null;
             mItems.add(new Item(text, htmlText, intent, uri));
@@ -1179,4 +1189,61 @@
                 return new ClipData[size];
             }
         };
+
+    /**
+     * Helper function for writing an HTML text into a parcel.
+     * If the text size is larger than 400KB, it writes the text to a file descriptor to prevent the
+     * parcel from exceeding 800KB binder size limit. {@link android.os.Binder#checkParcel()}
+     * Otherwise, it directly writes the text into the parcel.
+     * Note: This function is a workaround for existing applications that still use HTML for sharing
+     * large clip data. We will ask application developers to use content: URI instead and remove
+     * this function in API 30.
+     */
+    private static void writeHtmlTextToParcel(String text, Parcel dest, int flags) {
+        byte[] textData = (text != null) ? text.getBytes() : new byte[0];
+        if (textData.length > PARCEL_MAX_SIZE_BYTES / 2
+                && Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
+            try {
+                ParcelFileDescriptor pfd = ParcelFileDescriptor.fromData(textData, null);
+                dest.writeInt(PARCEL_TYPE_PFD);
+                dest.writeParcelable(pfd, flags);
+            } catch (IOException e) {
+                throw new IllegalStateException(
+                        "Error creating the shared memory area: " + e.toString());
+            }
+        } else {
+            dest.writeInt(PARCEL_TYPE_STRING);
+            dest.writeString(text);
+        }
+    }
+
+    /**
+     * Reads a text written by writeHtmlTextToParcel.
+     */
+    private static String readHtmlTextFromParcel(Parcel in) {
+        if (in.readInt() == PARCEL_TYPE_STRING) {
+            return in.readString();
+        }
+        ParcelFileDescriptor pfd =
+                in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
+        if (pfd == null) {
+            throw new IllegalStateException("Error reading ParcelFileDescriptor from Parcel");
+        }
+        FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+        InputStreamReader reader = new InputStreamReader(fis);
+        StringBuilder builder = new StringBuilder();
+        char[] buffer = new char[4096];
+        int numRead;
+        try {
+            while ((numRead = reader.read(buffer)) != -1) {
+                builder.append(buffer, 0, numRead);
+            }
+            return builder.toString();
+        } catch (IOException e) {
+            throw new IllegalStateException(
+                    "Error reading data from ParcelFileDescriptor: "  + e.toString());
+        } finally {
+            IoUtils.closeQuietly(fis);
+        }
+    }
 }
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 4de1dfc..949cdd6 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -42,6 +42,7 @@
 import android.graphics.Point;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.DeadObjectException;
@@ -3243,8 +3244,18 @@
         Objects.requireNonNull(uri);
         Objects.requireNonNull(size);
 
+        // Older apps might be relying on mutable results, so only consider
+        // giving them hardware bitmaps once they target Q or higher. If modern
+        // apps need mutable thumbnails, they can always roll their own logic.
+        final int allocator;
+        if (getTargetSdkVersion() >= Build.VERSION_CODES.Q) {
+            allocator = ImageDecoder.ALLOCATOR_DEFAULT;
+        } else {
+            allocator = ImageDecoder.ALLOCATOR_SOFTWARE;
+        }
+
         try (ContentProviderClient client = acquireContentProviderClient(uri)) {
-            return loadThumbnail(client, uri, size, signal, ImageDecoder.ALLOCATOR_DEFAULT);
+            return loadThumbnail(client, uri, size, signal, allocator);
         }
     }
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index e378800..004417b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2906,8 +2906,9 @@
      * @param flags Operation options for the binding.  May be 0,
      *          {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND},
      *          {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},
-     *          {@link #BIND_ALLOW_OOM_MANAGEMENT}, or
-     *          {@link #BIND_WAIVE_PRIORITY}.
+     *          {@link #BIND_ALLOW_OOM_MANAGEMENT}, {@link #BIND_WAIVE_PRIORITY}.
+     *          {@link #BIND_IMPORTANT}, or
+     *          {@link #BIND_ADJUST_WITH_ACTIVITY}.
      * @return {@code true} if the system is in the process of bringing up a
      *         service that your client has permission to bind to; {@code false}
      *         if the system couldn't find the service or if your client doesn't
@@ -2923,11 +2924,38 @@
      * @see #BIND_AUTO_CREATE
      * @see #BIND_DEBUG_UNBIND
      * @see #BIND_NOT_FOREGROUND
+     * @see #BIND_ABOVE_CLIENT
+     * @see #BIND_ALLOW_OOM_MANAGEMENT
+     * @see #BIND_WAIVE_PRIORITY
+     * @see #BIND_IMPORTANT
+     * @see #BIND_ADJUST_WITH_ACTIVITY
      */
     public abstract boolean bindService(@RequiresPermission Intent service,
             @NonNull ServiceConnection conn, @BindServiceFlags int flags);
 
     /**
+     * Variation of {@link #bindService} that, in the specific case of isolated
+     * services, allows the caller to generate multiple instances of a service
+     * from a single component declaration.
+     *
+     * @param service Identifies the service to connect to.  The Intent must
+     *      specify an explicit component name.
+     * @param conn Receives information as the service is started and stopped.
+     *      This must be a valid ServiceConnection object; it must not be null.
+     * @param flags Operation options for the binding as per {@link #bindService}.
+     * @param instanceName Unique identifier for the service instance.  Each unique
+     *      name here will result in a different service instance being created.
+     * @return Returns success of binding as per {@link #bindService}.
+     *
+     * @throws SecurityException If the caller does not have permission to access the service
+     *
+     * @see #bindService
+     */
+    public abstract boolean bindIsolatedService(@RequiresPermission Intent service,
+            @NonNull ServiceConnection conn, @BindServiceFlags int flags,
+            @NonNull String instanceName);
+
+    /**
      * Same as {@link #bindService(Intent, ServiceConnection, int)}, but with an explicit userHandle
      * argument for use by system server and other multi-user aware code.
      * @hide
@@ -2941,7 +2969,7 @@
     }
 
     /**
-     * Same as {@link #bindService(Intent, ServiceConnection, int, UserHandle)}, but with an
+     * Same as {@link #bindServiceAsUser(Intent, ServiceConnection, int, UserHandle)}, but with an
      * explicit non-null Handler to run the ServiceConnection callbacks on.
      *
      * @hide
@@ -3706,6 +3734,17 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.hardware.iris.IrisManager} for handling management
+     * of iris authentication.
+     *
+     * @hide
+     * @see #getSystemService
+     * @see android.hardware.iris.IrisManager
+     */
+    public static final String IRIS_SERVICE = "iris";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.hardware.biometrics.BiometricManager} for handling management
      * of face authentication.
      *
@@ -3854,6 +3893,14 @@
     public static final String AUTOFILL_MANAGER_SERVICE = "autofill";
 
     /**
+     * Official published name of the intelligence service.
+     *
+     * @hide
+     * @see #getSystemService(String)
+     */
+    public static final String INTELLIGENCE_MANAGER_SERVICE = "intelligence";
+
+    /**
      * Use with {@link #getSystemService(String)} to access the
      * {@link com.android.server.voiceinteraction.SoundTriggerService}.
      *
@@ -4208,6 +4255,15 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.os.ThermalService} for accessing the thermal service.
+     *
+     * @see #getSystemService(String)
+     * @hide
+     */
+    public static final String THERMAL_SERVICE = "thermalservice";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.content.pm.ShortcutManager} for accessing the launcher shortcut service.
      *
      * @see #getSystemService(String)
@@ -4279,6 +4335,16 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
+     * {android.os.IIdmap2} for managing idmap files (used by overlay
+     * packages).
+     *
+     * @see #getSystemService(String)
+     * @hide
+     */
+    public static final String IDMAP_SERVICE = "idmap";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
      * {@link VrManager} for accessing the VR service.
      *
      * @see #getSystemService(String)
@@ -4339,6 +4405,13 @@
     public static final String APP_BINDING_SERVICE = "app_binding";
 
     /**
+     * Use with {@link #getSystemService(String)} to retrieve an
+     * {@link android.telephony.rcs.RcsManager}.
+     * @hide
+     */
+    public static final String TELEPHONY_RCS_SERVICE = "ircs";
+
+    /**
      * 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/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index bfad2b4..88696b0 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -705,6 +705,12 @@
         return mBase.bindService(service, conn, flags);
     }
 
+    @Override
+    public boolean bindIsolatedService(Intent service, ServiceConnection conn,
+            int flags, String instanceName) {
+        return mBase.bindIsolatedService(service, conn, flags, instanceName);
+    }
+
     /** @hide */
     @Override
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 6c0fa4c..e9b2404 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1727,10 +1727,14 @@
             = "android.intent.extra.UNINSTALL_ALL_USERS";
 
     /**
-     * A string associated with a {@link #ACTION_UPGRADE_SETUP} activity
-     * describing the last run version of the platform that was setup.
+     * A string that associates with a metadata entry, indicating the last run version of the
+     * platform that was setup.
+     *
+     * @see #ACTION_UPGRADE_SETUP
+     *
      * @hide
      */
+    @SystemApi
     public static final String METADATA_SETUP_VERSION = "android.SETUP_VERSION";
 
     /**
@@ -1753,6 +1757,30 @@
             "android.intent.action.MANAGE_APP_PERMISSIONS";
 
     /**
+     * Activity action: Launch UI to manage a specific permissions of an app.
+     * <p>
+     * Input: {@link #EXTRA_PACKAGE_NAME} specifies the package whose permission
+     * will be managed by the launched UI.
+     * </p>
+     * <p>
+     * Input: {@link #EXTRA_PERMISSION_NAME} specifies the (individual) permission
+     * that should be managed by the launched UI.
+     * </p>
+     * <p>
+     * Output: Nothing.
+     * </p>
+     *
+     * @see #EXTRA_PACKAGE_NAME
+     * @see #EXTRA_PERMISSION_NAME
+     *
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_MANAGE_APP_PERMISSION =
+            "android.intent.action.MANAGE_APP_PERMISSION";
+
+    /**
      * Activity action: Launch UI to manage permissions.
      * <p>
      * Input: Nothing.
@@ -1882,8 +1910,8 @@
     /**
      * Activity action: Launch UI to manage which apps have a given permission.
      * <p>
-     * Input: {@link #EXTRA_PERMISSION_NAME} specifies the permission access
-     * to which will be managed by the launched UI.
+     * Input: {@link #EXTRA_PERMISSION_NAME} specifies the permission group
+     * which will be managed by the launched UI.
      * </p>
      * <p>
      * Output: Nothing.
@@ -7480,7 +7508,7 @@
      *
      * @see #putExtra(String, String)
      */
-    public String getStringExtra(String name) {
+    public @Nullable String getStringExtra(String name) {
         return mExtras == null ? null : mExtras.getString(name);
     }
 
@@ -7494,7 +7522,7 @@
      *
      * @see #putExtra(String, CharSequence)
      */
-    public CharSequence getCharSequenceExtra(String name) {
+    public @Nullable CharSequence getCharSequenceExtra(String name) {
         return mExtras == null ? null : mExtras.getCharSequence(name);
     }
 
@@ -7508,7 +7536,7 @@
      *
      * @see #putExtra(String, Parcelable)
      */
-    public <T extends Parcelable> T getParcelableExtra(String name) {
+    public @Nullable <T extends Parcelable> T getParcelableExtra(String name) {
         return mExtras == null ? null : mExtras.<T>getParcelable(name);
     }
 
@@ -7522,7 +7550,7 @@
      *
      * @see #putExtra(String, Parcelable[])
      */
-    public Parcelable[] getParcelableArrayExtra(String name) {
+    public @Nullable Parcelable[] getParcelableArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getParcelableArray(name);
     }
 
@@ -7537,7 +7565,7 @@
      *
      * @see #putParcelableArrayListExtra(String, ArrayList)
      */
-    public <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) {
+    public @Nullable <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) {
         return mExtras == null ? null : mExtras.<T>getParcelableArrayList(name);
     }
 
@@ -7551,7 +7579,7 @@
      *
      * @see #putExtra(String, Serializable)
      */
-    public Serializable getSerializableExtra(String name) {
+    public @Nullable Serializable getSerializableExtra(String name) {
         return mExtras == null ? null : mExtras.getSerializable(name);
     }
 
@@ -7566,7 +7594,7 @@
      *
      * @see #putIntegerArrayListExtra(String, ArrayList)
      */
-    public ArrayList<Integer> getIntegerArrayListExtra(String name) {
+    public @Nullable ArrayList<Integer> getIntegerArrayListExtra(String name) {
         return mExtras == null ? null : mExtras.getIntegerArrayList(name);
     }
 
@@ -7581,7 +7609,7 @@
      *
      * @see #putStringArrayListExtra(String, ArrayList)
      */
-    public ArrayList<String> getStringArrayListExtra(String name) {
+    public @Nullable ArrayList<String> getStringArrayListExtra(String name) {
         return mExtras == null ? null : mExtras.getStringArrayList(name);
     }
 
@@ -7596,7 +7624,7 @@
      *
      * @see #putCharSequenceArrayListExtra(String, ArrayList)
      */
-    public ArrayList<CharSequence> getCharSequenceArrayListExtra(String name) {
+    public @Nullable ArrayList<CharSequence> getCharSequenceArrayListExtra(String name) {
         return mExtras == null ? null : mExtras.getCharSequenceArrayList(name);
     }
 
@@ -7610,7 +7638,7 @@
      *
      * @see #putExtra(String, boolean[])
      */
-    public boolean[] getBooleanArrayExtra(String name) {
+    public @Nullable boolean[] getBooleanArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getBooleanArray(name);
     }
 
@@ -7624,7 +7652,7 @@
      *
      * @see #putExtra(String, byte[])
      */
-    public byte[] getByteArrayExtra(String name) {
+    public @Nullable byte[] getByteArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getByteArray(name);
     }
 
@@ -7638,7 +7666,7 @@
      *
      * @see #putExtra(String, short[])
      */
-    public short[] getShortArrayExtra(String name) {
+    public @Nullable short[] getShortArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getShortArray(name);
     }
 
@@ -7652,7 +7680,7 @@
      *
      * @see #putExtra(String, char[])
      */
-    public char[] getCharArrayExtra(String name) {
+    public @Nullable char[] getCharArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getCharArray(name);
     }
 
@@ -7666,7 +7694,7 @@
      *
      * @see #putExtra(String, int[])
      */
-    public int[] getIntArrayExtra(String name) {
+    public @Nullable int[] getIntArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getIntArray(name);
     }
 
@@ -7680,7 +7708,7 @@
      *
      * @see #putExtra(String, long[])
      */
-    public long[] getLongArrayExtra(String name) {
+    public @Nullable long[] getLongArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getLongArray(name);
     }
 
@@ -7694,7 +7722,7 @@
      *
      * @see #putExtra(String, float[])
      */
-    public float[] getFloatArrayExtra(String name) {
+    public @Nullable float[] getFloatArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getFloatArray(name);
     }
 
@@ -7708,7 +7736,7 @@
      *
      * @see #putExtra(String, double[])
      */
-    public double[] getDoubleArrayExtra(String name) {
+    public @Nullable double[] getDoubleArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getDoubleArray(name);
     }
 
@@ -7722,7 +7750,7 @@
      *
      * @see #putExtra(String, String[])
      */
-    public String[] getStringArrayExtra(String name) {
+    public @Nullable String[] getStringArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getStringArray(name);
     }
 
@@ -7736,7 +7764,7 @@
      *
      * @see #putExtra(String, CharSequence[])
      */
-    public CharSequence[] getCharSequenceArrayExtra(String name) {
+    public @Nullable CharSequence[] getCharSequenceArrayExtra(String name) {
         return mExtras == null ? null : mExtras.getCharSequenceArray(name);
     }
 
@@ -7750,7 +7778,7 @@
      *
      * @see #putExtra(String, Bundle)
      */
-    public Bundle getBundleExtra(String name) {
+    public @Nullable Bundle getBundleExtra(String name) {
         return mExtras == null ? null : mExtras.getBundle(name);
     }
 
@@ -8556,7 +8584,7 @@
      * @see #removeExtra
      * @see #getStringExtra(String)
      */
-    public @NonNull Intent putExtra(String name, String value) {
+    public @NonNull Intent putExtra(String name, @Nullable String value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8579,7 +8607,7 @@
      * @see #removeExtra
      * @see #getCharSequenceExtra(String)
      */
-    public @NonNull Intent putExtra(String name, CharSequence value) {
+    public @NonNull Intent putExtra(String name, @Nullable CharSequence value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8602,7 +8630,7 @@
      * @see #removeExtra
      * @see #getParcelableExtra(String)
      */
-    public @NonNull Intent putExtra(String name, Parcelable value) {
+    public @NonNull Intent putExtra(String name, @Nullable Parcelable value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8625,7 +8653,7 @@
      * @see #removeExtra
      * @see #getParcelableArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, Parcelable[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable Parcelable[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8649,7 +8677,7 @@
      * @see #getParcelableArrayListExtra(String)
      */
     public @NonNull Intent putParcelableArrayListExtra(String name,
-            ArrayList<? extends Parcelable> value) {
+            @Nullable ArrayList<? extends Parcelable> value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8672,7 +8700,8 @@
      * @see #removeExtra
      * @see #getIntegerArrayListExtra(String)
      */
-    public @NonNull Intent putIntegerArrayListExtra(String name, ArrayList<Integer> value) {
+    public @NonNull Intent putIntegerArrayListExtra(String name,
+            @Nullable ArrayList<Integer> value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8695,7 +8724,7 @@
      * @see #removeExtra
      * @see #getStringArrayListExtra(String)
      */
-    public @NonNull Intent putStringArrayListExtra(String name, ArrayList<String> value) {
+    public @NonNull Intent putStringArrayListExtra(String name, @Nullable ArrayList<String> value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8719,7 +8748,7 @@
      * @see #getCharSequenceArrayListExtra(String)
      */
     public @NonNull Intent putCharSequenceArrayListExtra(String name,
-            ArrayList<CharSequence> value) {
+            @Nullable ArrayList<CharSequence> value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8742,7 +8771,7 @@
      * @see #removeExtra
      * @see #getSerializableExtra(String)
      */
-    public @NonNull Intent putExtra(String name, Serializable value) {
+    public @NonNull Intent putExtra(String name, @Nullable Serializable value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8765,7 +8794,7 @@
      * @see #removeExtra
      * @see #getBooleanArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, boolean[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable boolean[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8788,7 +8817,7 @@
      * @see #removeExtra
      * @see #getByteArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, byte[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable byte[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8811,7 +8840,7 @@
      * @see #removeExtra
      * @see #getShortArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, short[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable short[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8834,7 +8863,7 @@
      * @see #removeExtra
      * @see #getCharArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, char[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable char[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8857,7 +8886,7 @@
      * @see #removeExtra
      * @see #getIntArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, int[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable int[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8880,7 +8909,7 @@
      * @see #removeExtra
      * @see #getLongArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, long[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable long[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8903,7 +8932,7 @@
      * @see #removeExtra
      * @see #getFloatArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, float[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable float[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8926,7 +8955,7 @@
      * @see #removeExtra
      * @see #getDoubleArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, double[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable double[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8949,7 +8978,7 @@
      * @see #removeExtra
      * @see #getStringArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, String[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable String[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8972,7 +9001,7 @@
      * @see #removeExtra
      * @see #getCharSequenceArrayExtra(String)
      */
-    public @NonNull Intent putExtra(String name, CharSequence[] value) {
+    public @NonNull Intent putExtra(String name, @Nullable CharSequence[] value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
@@ -8995,7 +9024,7 @@
      * @see #removeExtra
      * @see #getBundleExtra(String)
      */
-    public @NonNull Intent putExtra(String name, Bundle value) {
+    public @NonNull Intent putExtra(String name, @Nullable Bundle value) {
         if (mExtras == null) {
             mExtras = new Bundle();
         }
diff --git a/core/java/android/content/MimeTypeFilter.java b/core/java/android/content/MimeTypeFilter.java
new file mode 100644
index 0000000..1c26fd9
--- /dev/null
+++ b/core/java/android/content/MimeTypeFilter.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2018 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;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.ArrayList;
+
+/**
+ * Provides utility methods for matching MIME type filters used in ContentProvider.
+ *
+ * <p>Wildcards are allowed only instead of the entire type or subtype with a tree prefix.
+ * Eg. image\/*, *\/* is a valid filter and will match image/jpeg, but image/j* is invalid and
+ * it will not match image/jpeg. Suffixes and parameters are not supported, and they are treated
+ * as part of the subtype during matching. Neither type nor subtype can be empty.
+ *
+ * <p><em>Note: MIME type matching in the Android framework is case-sensitive, unlike the formal
+ * RFC definitions. As a result, you should always write these elements with lower case letters,
+ * or use {@link android.content.Intent#normalizeMimeType} to ensure that they are converted to
+ * lower case.</em>
+ *
+ * <p>MIME types can be null or ill-formatted. In such case they won't match anything.
+ *
+ * <p>MIME type filters must be correctly formatted, or an exception will be thrown.
+ * Copied from support library.
+ * {@hide}
+ */
+public final class MimeTypeFilter {
+
+    private MimeTypeFilter() {
+    }
+
+    private static boolean mimeTypeAgainstFilter(
+            @NonNull String[] mimeTypeParts, @NonNull String[] filterParts) {
+        if (filterParts.length != 2) {
+            throw new IllegalArgumentException(
+                    "Ill-formatted MIME type filter. Must be type/subtype.");
+        }
+        if (filterParts[0].isEmpty() || filterParts[1].isEmpty()) {
+            throw new IllegalArgumentException(
+                    "Ill-formatted MIME type filter. Type or subtype empty.");
+        }
+        if (mimeTypeParts.length != 2) {
+            return false;
+        }
+        if (!"*".equals(filterParts[0])
+                && !filterParts[0].equals(mimeTypeParts[0])) {
+            return false;
+        }
+        if (!"*".equals(filterParts[1])
+                && !filterParts[1].equals(mimeTypeParts[1])) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Matches one nullable MIME type against one MIME type filter.
+     * @return True if the {@code mimeType} matches the {@code filter}.
+     */
+    public static boolean matches(@Nullable String mimeType, @NonNull String filter) {
+        if (mimeType == null) {
+            return false;
+        }
+
+        final String[] mimeTypeParts = mimeType.split("/");
+        final String[] filterParts = filter.split("/");
+
+        return mimeTypeAgainstFilter(mimeTypeParts, filterParts);
+    }
+
+    /**
+     * Matches one nullable MIME type against an array of MIME type filters.
+     * @return The first matching filter, or null if nothing matches.
+     */
+    @Nullable
+    public static String matches(
+            @Nullable String mimeType, @NonNull String[] filters) {
+        if (mimeType == null) {
+            return null;
+        }
+
+        final String[] mimeTypeParts = mimeType.split("/");
+        for (String filter : filters) {
+            final String[] filterParts = filter.split("/");
+            if (mimeTypeAgainstFilter(mimeTypeParts, filterParts)) {
+                return filter;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Matches multiple MIME types against an array of MIME type filters.
+     * @return The first matching MIME type, or null if nothing matches.
+     */
+    @Nullable
+    public static String matches(
+            @Nullable String[] mimeTypes, @NonNull String filter) {
+        if (mimeTypes == null) {
+            return null;
+        }
+
+        final String[] filterParts = filter.split("/");
+        for (String mimeType : mimeTypes) {
+            final String[] mimeTypeParts = mimeType.split("/");
+            if (mimeTypeAgainstFilter(mimeTypeParts, filterParts)) {
+                return mimeType;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Matches multiple MIME types against an array of MIME type filters.
+     * @return The list of matching MIME types, or empty array if nothing matches.
+     */
+    @NonNull
+    public static String[] matchesMany(
+            @Nullable String[] mimeTypes, @NonNull String filter) {
+        if (mimeTypes == null) {
+            return new String[] {};
+        }
+
+        final ArrayList<String> list = new ArrayList<>();
+        final String[] filterParts = filter.split("/");
+        for (String mimeType : mimeTypes) {
+            final String[] mimeTypeParts = mimeType.split("/");
+            if (mimeTypeAgainstFilter(mimeTypeParts, filterParts)) {
+                list.add(mimeType);
+            }
+        }
+
+        return list.toArray(new String[list.size()]);
+    }
+}
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index d3652e8..877dfee 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -57,6 +57,9 @@
          *
          * <p>This callback will be run on your main thread.
          *
+         * <p><em>Note: This callback will not be triggered when preferences are cleared via
+         * {@link Editor#clear()}.</em>
+         *
          * @param sharedPreferences The {@link SharedPreferences} that received
          *            the change.
          * @param key The key of the preference that was changed, added, or
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 6b5c659..48240db 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -27,7 +27,6 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
-import android.os.Build;
 import android.os.Environment;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -1171,11 +1170,11 @@
      * system apps.
      * @hide
      */
-    public static final int HIDDEN_API_ENFORCEMENT_NONE = 0;
+    public static final int HIDDEN_API_ENFORCEMENT_DISABLED = 0;
     /**
      * No API enforcement, but enable the detection logic and warnings. Observed behaviour is the
-     * same as {@link #HIDDEN_API_ENFORCEMENT_NONE} but you may see warnings in the log when APIs
-     * are accessed.
+     * same as {@link #HIDDEN_API_ENFORCEMENT_DISABLED} but you may see warnings in the log when
+     * APIs are accessed.
      * @hide
      * */
     public static final int HIDDEN_API_ENFORCEMENT_JUST_WARN = 1;
@@ -1183,14 +1182,10 @@
      * Dark grey list enforcement. Enforces the dark grey and black lists
      * @hide
      */
-    public static final int HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK = 2;
-    /**
-     * Blacklist enforcement only.
-     * @hide
-     */
-    public static final int HIDDEN_API_ENFORCEMENT_BLACK = 3;
+    public static final int HIDDEN_API_ENFORCEMENT_ENABLED = 2;
 
-    private static final int HIDDEN_API_ENFORCEMENT_MAX = HIDDEN_API_ENFORCEMENT_BLACK;
+    private static final int HIDDEN_API_ENFORCEMENT_MIN = HIDDEN_API_ENFORCEMENT_DEFAULT;
+    private static final int HIDDEN_API_ENFORCEMENT_MAX = HIDDEN_API_ENFORCEMENT_ENABLED;
 
     /**
      * Values in this IntDef MUST be kept in sync with enum hiddenapi::EnforcementPolicy in
@@ -1199,17 +1194,16 @@
      */
     @IntDef(prefix = { "HIDDEN_API_ENFORCEMENT_" }, value = {
             HIDDEN_API_ENFORCEMENT_DEFAULT,
-            HIDDEN_API_ENFORCEMENT_NONE,
+            HIDDEN_API_ENFORCEMENT_DISABLED,
             HIDDEN_API_ENFORCEMENT_JUST_WARN,
-            HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK,
-            HIDDEN_API_ENFORCEMENT_BLACK,
+            HIDDEN_API_ENFORCEMENT_ENABLED,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface HiddenApiEnforcementPolicy {}
 
     /** @hide */
     public static boolean isValidHiddenApiEnforcementPolicy(int policy) {
-        return policy >= HIDDEN_API_ENFORCEMENT_DEFAULT && policy <= HIDDEN_API_ENFORCEMENT_MAX;
+        return policy >= HIDDEN_API_ENFORCEMENT_MIN && policy <= HIDDEN_API_ENFORCEMENT_MAX;
     }
 
     private int mHiddenApiPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT;
@@ -1749,16 +1743,12 @@
      */
     public @HiddenApiEnforcementPolicy int getHiddenApiEnforcementPolicy() {
         if (isAllowedToUseHiddenApis()) {
-            return HIDDEN_API_ENFORCEMENT_NONE;
+            return HIDDEN_API_ENFORCEMENT_DISABLED;
         }
         if (mHiddenApiPolicy != HIDDEN_API_ENFORCEMENT_DEFAULT) {
             return mHiddenApiPolicy;
         }
-        if (targetSdkVersion < Build.VERSION_CODES.P) {
-            return HIDDEN_API_ENFORCEMENT_BLACK;
-        } else {
-            return HIDDEN_API_ENFORCEMENT_DARK_GREY_AND_BLACK;
-        }
+        return HIDDEN_API_ENFORCEMENT_ENABLED;
     }
 
     /**
@@ -1777,23 +1767,15 @@
      * This will have no effect if this app is not subject to hidden API enforcement, i.e. if it
      * is on the package whitelist.
      *
-     * @param policyPreP configured policy for pre-P apps, or {@link
-     *        #HIDDEN_API_ENFORCEMENT_DEFAULT} if nothing configured.
-     * @param policyP configured policy for apps targeting P or later, or {@link
-     *        #HIDDEN_API_ENFORCEMENT_DEFAULT} if nothing configured.
+     * @param policy configured policy for this app, or {@link #HIDDEN_API_ENFORCEMENT_DEFAULT}
+     *               if nothing configured.
      * @hide
      */
-    public void maybeUpdateHiddenApiEnforcementPolicy(
-            @HiddenApiEnforcementPolicy int policyPreP, @HiddenApiEnforcementPolicy int policyP) {
+    public void maybeUpdateHiddenApiEnforcementPolicy(@HiddenApiEnforcementPolicy int policy) {
         if (isPackageWhitelistedForHiddenApis()) {
             return;
         }
-        if (targetSdkVersion < Build.VERSION_CODES.P) {
-            setHiddenApiEnforcementPolicy(policyPreP);
-        } else if (targetSdkVersion >= Build.VERSION_CODES.P) {
-            setHiddenApiEnforcementPolicy(policyP);
-        }
-
+        setHiddenApiEnforcementPolicy(policy);
     }
 
     /**
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index 8fddb99..cef21f6 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -38,4 +38,9 @@
     void commit(in IntentSender statusReceiver, boolean forTransferred);
     void transfer(in String packageName);
     void abandon();
+    boolean isMultiPackage();
+    int[] getChildSessionIds();
+    void addChildSessionId(in int sessionId);
+    void removeChildSessionId(in int sessionId);
+    int getParentSessionId();
 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 4a4de51..d0eff2e 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -276,6 +276,8 @@
             in PersistableBundle appExtras, in PersistableBundle launcherExtras,
             in SuspendDialogInfo dialogInfo, String callingPackage, int userId);
 
+    boolean canSuspendPackageForUser(String packageName, int userId);
+
     boolean isPackageSuspendedForUser(String packageName, int userId);
 
     PersistableBundle getSuspendedPackageAppExtras(String packageName, int userId);
@@ -475,7 +477,7 @@
      * @param classPaths the class paths corresponding to the class loaders names from
      *     {@param classLoadersNames}. The the first element corresponds to the first class loader
      *     and so on. A classpath is represented as a list of dex files separated by
-     *     {@code File.pathSeparator}.
+     *     {@code File.pathSeparator}, or null if the class loader's classpath is not known.
      *     The dex files found in the first class path will be recorded in the usage file.
      * @param loaderIsa the ISA of the loader process
      */
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index e9cfa78..8f90199 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -365,12 +365,14 @@
      */
     public @NonNull Session openSession(int sessionId) throws IOException {
         try {
-            return new Session(mInstaller.openSession(sessionId));
+            try {
+                return new Session(mInstaller.openSession(sessionId));
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
         } catch (RuntimeException e) {
             ExceptionUtils.maybeUnwrapIOException(e);
             throw e;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -769,9 +771,18 @@
      * If an APK included in this session is already defined by the existing
      * installation (for example, the same split name), the APK in this session
      * will replace the existing APK.
+     * <p>
+     * In such a case that multiple packages need to be commited simultaneously,
+     * multiple sessions can be referenced by a single multi-package session.
+     * This session is created with no package name and calling
+     * {@link SessionParams#setMultiPackage()} with {@code true}. The
+     * individual session IDs can be added with {@link #addChildSessionId(int)}
+     * and commit of the multi-package session will result in all child sessions
+     * being committed atomically.
      */
     public static class Session implements Closeable {
-        private IPackageInstallerSession mSession;
+        /** {@hide} */
+        protected final IPackageInstallerSession mSession;
 
         /** {@hide} */
         public Session(IPackageInstallerSession session) {
@@ -1080,6 +1091,71 @@
                 throw e.rethrowFromSystemServer();
             }
         }
+
+        /**
+         * @return {@code true} if this session will commit more than one package when it is
+         * committed.
+         */
+        public boolean isMultiPackage() {
+            try {
+                return mSession.isMultiPackage();
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
+         * @return the session ID of the multi-package session that this belongs to or
+         * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session.
+         */
+        public int getParentSessionId() {
+            try {
+                return mSession.getParentSessionId();
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
+         * @return the set of session IDs that will be committed atomically when this session is
+         * committed if this is a multi-package session or null if none exist.
+         */
+        @NonNull
+        public int[] getChildSessionIds() {
+            try {
+                return mSession.getChildSessionIds();
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
+         * Adds a session ID to the set of sessions that will be committed atomically
+         * when this session is committed.
+         *
+         * @param sessionId the session ID to add to this multi-package session.
+         */
+        public void addChildSessionId(int sessionId) {
+            try {
+                mSession.addChildSessionId(sessionId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
+         * Removes a session ID from the set of sessions that will be committed
+         * atomically when this session is committed.
+         *
+         * @param sessionId the session ID to remove from this multi-package session.
+         */
+        public void removeChildSessionId(int sessionId) {
+            try {
+                mSession.removeChildSessionId(sessionId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
     }
 
     /**
@@ -1149,6 +1225,8 @@
         public String[] grantedRuntimePermissions;
         /** {@hide} */
         public String installerPackageName;
+        /** {@hide} */
+        public boolean isMultiPackage;
 
         /**
          * Construct parameters for a new package install session.
@@ -1178,6 +1256,7 @@
             volumeUuid = source.readString();
             grantedRuntimePermissions = source.readStringArray();
             installerPackageName = source.readString();
+            isMultiPackage = source.readBoolean();
         }
 
         /**
@@ -1392,6 +1471,18 @@
             this.installerPackageName = installerPackageName;
         }
 
+        /**
+         * Set this session to be the parent of a multi-package install.
+         *
+         * A multi-package install session contains no APKs and only references other install
+         * sessions via ID. When a multi-package session is committed, all of its children
+         * are committed to the system in an atomic manner. If any children fail to install,
+         * all of them do, including the multi-package session.
+         */
+        public void setMultiPackage() {
+            this.isMultiPackage = true;
+        }
+
         /** {@hide} */
         public void dump(IndentingPrintWriter pw) {
             pw.printPair("mode", mode);
@@ -1408,6 +1499,7 @@
             pw.printPair("volumeUuid", volumeUuid);
             pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions);
             pw.printPair("installerPackageName", installerPackageName);
+            pw.printPair("isMultiPackage", isMultiPackage);
             pw.println();
         }
 
@@ -1433,6 +1525,7 @@
             dest.writeString(volumeUuid);
             dest.writeStringArray(grantedRuntimePermissions);
             dest.writeString(installerPackageName);
+            dest.writeBoolean(isMultiPackage);
         }
 
         public static final Parcelable.Creator<SessionParams>
@@ -1454,6 +1547,12 @@
      */
     public static class SessionInfo implements Parcelable {
 
+        /**
+         * A session ID that does not exist or is invalid.
+         */
+        public static final int INVALID_ID = -1;
+        /** {@hide} */
+        private static final int[] NO_SESSIONS = {};
         /** {@hide} */
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
         public int sessionId;
@@ -1503,6 +1602,12 @@
         public String[] grantedRuntimePermissions;
         /** {@hide} */
         public int installFlags;
+        /** {@hide} */
+        public boolean isMultiPackage;
+        /** {@hide} */
+        public int parentSessionId = INVALID_ID;
+        /** {@hide} */
+        public int[] childSessionIds = NO_SESSIONS;
 
         /** {@hide} */
         @UnsupportedAppUsage
@@ -1531,6 +1636,12 @@
             referrerUri = source.readParcelable(null);
             grantedRuntimePermissions = source.readStringArray();
             installFlags = source.readInt();
+            isMultiPackage = source.readBoolean();
+            parentSessionId = source.readInt();
+            childSessionIds = source.createIntArray();
+            if (childSessionIds == null) {
+                childSessionIds = NO_SESSIONS;
+            }
         }
 
         /**
@@ -1784,6 +1895,30 @@
             return createDetailsIntent();
         }
 
+        /**
+         * Returns true if this session is a multi-package session containing references to other
+         * sessions.
+         */
+        public boolean isMultiPackage() {
+            return isMultiPackage;
+        }
+
+        /**
+         * Returns the parent multi-package session ID if this session belongs to one,
+         * {@link #INVALID_ID} otherwise.
+         */
+        public int getParentSessionId() {
+            return parentSessionId;
+        }
+
+        /**
+         * Returns the set of session IDs that will be committed when this session is commited if
+         * this session is a multi-package session.
+         */
+        public int[] getChildSessionIds() {
+            return childSessionIds;
+        }
+
         @Override
         public int describeContents() {
             return 0;
@@ -1811,6 +1946,9 @@
             dest.writeParcelable(referrerUri, flags);
             dest.writeStringArray(grantedRuntimePermissions);
             dest.writeInt(installFlags);
+            dest.writeBoolean(isMultiPackage);
+            dest.writeInt(parentSessionId);
+            dest.writeIntArray(childSessionIds);
         }
 
         public static final Parcelable.Creator<SessionInfo>
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1f700f7..e14b17e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -855,6 +855,14 @@
      */
     public static final int INSTALL_VIRTUAL_PRELOAD = 0x00010000;
 
+    /**
+     * Flag parameter for {@link #installPackage} to indicate that this package
+     * is an APEX package
+     *
+     * @hide
+     */
+    public static final int INSTALL_APEX = 0x00020000;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "DONT_KILL_APP" }, value = {
             DONT_KILL_APP
@@ -907,6 +915,11 @@
     public static final int INSTALL_REASON_USER = 4;
 
     /**
+     * @hide
+     */
+    public static final int INSTALL_UNKNOWN = 0;
+
+    /**
      * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
      * on success.
      *
@@ -2935,6 +2948,15 @@
     public static final int FLAG_PERMISSION_REVIEW_REQUIRED =  1 << 6;
 
     /**
+     * Permission flag: The permission has not been explicitly requested by
+     * the app but has been added automatically by the system. Revoke once
+     * the app does explicitly request it.
+     *
+     * @hide
+     */
+    public static final int FLAG_PERMISSION_REVOKE_WHEN_REQUESTED =  1 << 7;
+
+    /**
      * Mask for all permission flags.
      *
      * @hide
@@ -3585,7 +3607,10 @@
             FLAG_PERMISSION_POLICY_FIXED,
             FLAG_PERMISSION_REVOKE_ON_UPGRADE,
             FLAG_PERMISSION_SYSTEM_FIXED,
-            FLAG_PERMISSION_GRANTED_BY_DEFAULT
+            FLAG_PERMISSION_GRANTED_BY_DEFAULT,
+            /*
+            FLAG_PERMISSION_REVOKE_WHEN_REQUESED
+            */
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface PermissionFlags {}
@@ -5772,6 +5797,30 @@
     }
 
     /**
+     * Returns whether or not a given package can be suspended via a call to {@link
+     * #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle,
+     * SuspendDialogInfo) setPackagesSuspended}. The platform prevents suspending certain critical
+     * packages to keep the device in a functioning state, e.g. the default dialer.
+     * Apps need to hold {@link Manifest.permission#SUSPEND_APPS SUSPEND_APPS} to call this api.
+     *
+     * <p>
+     * Note that this set of critical packages can change with time, so <em>a value of {@code true}
+     * returned by this api does not guarantee that a following call to {@link
+     * #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle,
+     * SuspendDialogInfo) setPackagesSuspended} for the same package will succeed</em>, especially
+     * if considerable time elapsed between the two calls.
+     *
+     * @param packageName The package to check.
+     * @return {@code true} if the given package can be suspended, {@code false} otherwise.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.SUSPEND_APPS)
+    public boolean canSuspendPackage(@NonNull String packageName) {
+        throw new UnsupportedOperationException("canSuspendPackage not implemented");
+    }
+
+    /**
      * @see #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle, String)
      * @param packageName The name of the package to get the suspended status of.
      * @param userId The user id.
@@ -5800,16 +5849,16 @@
      * {@code android.permission.SUSPEND_APPS} can put any app on the device into a suspended state.
      *
      * <p>While in this state, the application's notifications will be hidden, any of its started
-     * activities will be stopped and it will not be able to show toasts or dialogs or ring the
-     * device. When the user tries to launch a suspended app, the system will, instead, show a
+     * activities will be stopped and it will not be able to show toasts or dialogs or play audio.
+     * When the user tries to launch a suspended app, the system will, instead, show a
      * dialog to the user informing them that they cannot use this app while it is suspended.
      *
      * <p>When an app is put into this state, the broadcast action
      * {@link Intent#ACTION_MY_PACKAGE_SUSPENDED} will be delivered to any of its broadcast
      * receivers that included this action in their intent-filters, <em>including manifest
      * receivers.</em> Similarly, a broadcast action {@link Intent#ACTION_MY_PACKAGE_UNSUSPENDED}
-     * is delivered when a previously suspended app is taken out of this state.
-     * </p>
+     * is delivered when a previously suspended app is taken out of this state. Apps are expected to
+     * use these to gracefully deal with transitions to and from this state.
      *
      * @return {@code true} if the calling package has been suspended, {@code false} otherwise.
      *
@@ -6125,6 +6174,7 @@
             case FLAG_PERMISSION_REVOKE_ON_UPGRADE: return "REVOKE_ON_UPGRADE";
             case FLAG_PERMISSION_USER_FIXED: return "USER_FIXED";
             case FLAG_PERMISSION_REVIEW_REQUIRED: return "REVIEW_REQUIRED";
+            case FLAG_PERMISSION_REVOKE_WHEN_REQUESTED: return "REVOKE_WHEN_REQUESTED";
             default: return Integer.toString(flag);
         }
     }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index dc33bde..7ef5264 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2435,7 +2435,7 @@
         }
 
         final int NP = PackageParser.NEW_PERMISSIONS.length;
-        StringBuilder implicitPerms = null;
+        StringBuilder newPermsMsg = null;
         for (int ip=0; ip<NP; ip++) {
             final PackageParser.NewPermissionInfo npi
                     = PackageParser.NEW_PERMISSIONS[ip];
@@ -2443,19 +2443,20 @@
                 break;
             }
             if (!pkg.requestedPermissions.contains(npi.name)) {
-                if (implicitPerms == null) {
-                    implicitPerms = new StringBuilder(128);
-                    implicitPerms.append(pkg.packageName);
-                    implicitPerms.append(": compat added ");
+                if (newPermsMsg == null) {
+                    newPermsMsg = new StringBuilder(128);
+                    newPermsMsg.append(pkg.packageName);
+                    newPermsMsg.append(": compat added ");
                 } else {
-                    implicitPerms.append(' ');
+                    newPermsMsg.append(' ');
                 }
-                implicitPerms.append(npi.name);
+                newPermsMsg.append(npi.name);
                 pkg.requestedPermissions.add(npi.name);
+                pkg.implicitPermissions.add(npi.name);
             }
         }
-        if (implicitPerms != null) {
-            Slog.i(TAG, implicitPerms.toString());
+        if (newPermsMsg != null) {
+            Slog.i(TAG, newPermsMsg.toString());
         }
 
 
@@ -2472,6 +2473,7 @@
                 final String perm = newPerms.get(in);
                 if (!pkg.requestedPermissions.contains(perm)) {
                     pkg.requestedPermissions.add(perm);
+                    pkg.implicitPermissions.add(perm);
                 }
             }
         }
@@ -6394,6 +6396,9 @@
         @UnsupportedAppUsage
         public final ArrayList<String> requestedPermissions = new ArrayList<String>();
 
+        /** Permissions requested but not in the manifest. */
+        public final ArrayList<String> implicitPermissions = new ArrayList<>();
+
         @UnsupportedAppUsage
         public ArrayList<String> protectedBroadcasts;
 
@@ -6923,6 +6928,8 @@
 
             dest.readStringList(requestedPermissions);
             internStringArrayList(requestedPermissions);
+            dest.readStringList(implicitPermissions);
+            internStringArrayList(implicitPermissions);
             protectedBroadcasts = dest.createStringArrayList();
             internStringArrayList(protectedBroadcasts);
 
@@ -7087,6 +7094,7 @@
             dest.writeParcelableList(instrumentation, flags);
 
             dest.writeStringList(requestedPermissions);
+            dest.writeStringList(implicitPermissions);
             dest.writeStringList(protectedBroadcasts);
 
             // TODO: This doesn't work: b/64295061
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index a8bbeab..096301c 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -25,6 +25,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -78,6 +79,7 @@
     private final @Type int mType;
     private final VersionedPackage mDeclaringPackage;
     private final List<VersionedPackage> mDependentPackages;
+    private List<SharedLibraryInfo> mDependencies;
 
     /**
      * Creates a new instance.
@@ -91,7 +93,8 @@
      * @hide
      */
     public SharedLibraryInfo(String path, String packageName, String name, long version, int type,
-            VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages) {
+            VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages,
+            List<SharedLibraryInfo> dependencies) {
         mPath = path;
         mPackageName = packageName;
         mName = name;
@@ -99,11 +102,13 @@
         mType = type;
         mDeclaringPackage = declaringPackage;
         mDependentPackages = dependentPackages;
+        mDependencies = dependencies;
     }
 
     private SharedLibraryInfo(Parcel parcel) {
         this(parcel.readString(), parcel.readString(), parcel.readString(), parcel.readLong(),
-                parcel.readInt(), parcel.readParcelable(null), parcel.readArrayList(null));
+                parcel.readInt(), parcel.readParcelable(null), parcel.readArrayList(null),
+                parcel.createTypedArrayList(SharedLibraryInfo.CREATOR));
     }
 
     /**
@@ -150,6 +155,47 @@
     }
 
     /**
+     * Add a library dependency to that library. Note that this
+     * should be called under the package manager lock.
+     *
+     * @hide
+     */
+    public void addDependency(@Nullable SharedLibraryInfo info) {
+        if (info == null) {
+            // For convenience of the caller, allow null to be passed.
+            // This can happen when we create the dependencies of builtin
+            // libraries.
+            return;
+        }
+        if (mDependencies == null) {
+            mDependencies = new ArrayList<>();
+        }
+        mDependencies.add(info);
+    }
+
+    /**
+     * Clear all dependencies.
+     *
+     * @hide
+     */
+    public void clearDependencies() {
+        mDependencies = null;
+    }
+
+    /**
+     * Gets the libraries this library directly depends on. Note that
+     * the package manager prevents recursive dependencies when installing
+     * a package.
+     *
+     * @return The dependencies.
+     *
+     * @hide
+     */
+    public @Nullable List<SharedLibraryInfo> getDependencies() {
+        return mDependencies;
+    }
+
+    /**
      * @deprecated Use {@link #getLongVersion()} instead.
      */
     @Deprecated
@@ -232,6 +278,7 @@
         parcel.writeInt(mType);
         parcel.writeParcelable(mDeclaringPackage, flags);
         parcel.writeList(mDependentPackages);
+        parcel.writeTypedList(mDependencies);
     }
 
     private static String typeToString(int type) {
diff --git a/core/java/android/content/pm/SharedLibraryNames.java b/core/java/android/content/pm/SharedLibraryNames.java
index 387d29e8..5afc8a9 100644
--- a/core/java/android/content/pm/SharedLibraryNames.java
+++ b/core/java/android/content/pm/SharedLibraryNames.java
@@ -22,15 +22,15 @@
  */
 public class SharedLibraryNames {
 
-    static final String ANDROID_HIDL_BASE = "android.hidl.base-V1.0-java";
+    public static final String ANDROID_HIDL_BASE = "android.hidl.base-V1.0-java";
 
-    static final String ANDROID_HIDL_MANAGER = "android.hidl.manager-V1.0-java";
+    public static final String ANDROID_HIDL_MANAGER = "android.hidl.manager-V1.0-java";
 
-    static final String ANDROID_TEST_BASE = "android.test.base";
+    public static final String ANDROID_TEST_BASE = "android.test.base";
 
-    static final String ANDROID_TEST_MOCK = "android.test.mock";
+    public static final String ANDROID_TEST_MOCK = "android.test.mock";
 
-    static final String ANDROID_TEST_RUNNER = "android.test.runner";
+    public static final String ANDROID_TEST_RUNNER = "android.test.runner";
 
-    static final String ORG_APACHE_HTTP_LEGACY = "org.apache.http.legacy";
+    public static final String ORG_APACHE_HTTP_LEGACY = "org.apache.http.legacy";
 }
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 5f23749..4371c77 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -58,6 +58,7 @@
 public final class AssetManager implements AutoCloseable {
     private static final String TAG = "AssetManager";
     private static final boolean DEBUG_REFS = false;
+    private static final boolean FEATURE_FLAG_IDMAP2 = false;
 
     private static final String FRAMEWORK_APK_PATH = "/system/framework/framework-res.apk";
 
@@ -195,13 +196,23 @@
             return;
         }
 
-        // Make sure that all IDMAPs are up to date.
-        nativeVerifySystemIdmaps();
 
         try {
             final ArrayList<ApkAssets> apkAssets = new ArrayList<>();
             apkAssets.add(ApkAssets.loadFromPath(FRAMEWORK_APK_PATH, true /*system*/));
-            loadStaticRuntimeOverlays(apkAssets);
+            if (FEATURE_FLAG_IDMAP2) {
+                final String[] systemIdmapPaths =
+                    nativeCreateIdmapsForStaticOverlaysTargetingAndroid();
+                if (systemIdmapPaths == null) {
+                    throw new IOException("idmap2 scan failed");
+                }
+                for (String idmapPath : systemIdmapPaths) {
+                    apkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, true /*system*/));
+                }
+            } else {
+                nativeVerifySystemIdmaps();
+                loadStaticRuntimeOverlays(apkAssets);
+            }
 
             sSystemApkAssetsSet = new ArraySet<>(apkAssets);
             sSystemApkAssets = apkAssets.toArray(new ApkAssets[apkAssets.size()]);
@@ -1404,6 +1415,7 @@
     private static native long nativeAssetGetRemainingLength(long assetPtr);
 
     private static native void nativeVerifySystemIdmaps();
+    private static native String[] nativeCreateIdmapsForStaticOverlaysTargetingAndroid();
 
     // Global debug native methods.
     /**
diff --git a/core/java/android/database/TranslatingCursor.java b/core/java/android/database/TranslatingCursor.java
new file mode 100644
index 0000000..58e65b2
--- /dev/null
+++ b/core/java/android/database/TranslatingCursor.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2018 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.database;
+
+import android.annotation.NonNull;
+import android.content.ContentResolver;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.os.CancellationSignal;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Cursor that supports deprecation of {@code _data} like columns which represent raw filepaths,
+ * typically by replacing values with fake paths that the OS then offers to redirect to
+ * {@link ContentResolver#openFileDescriptor(Uri, String)}, which developers
+ * should be using directly.
+ *
+ * @hide
+ */
+public class TranslatingCursor extends CrossProcessCursorWrapper {
+    public static class Config {
+        public final Uri baseUri;
+        public final String idColumn;
+        public final String[] filePathColumns;
+
+        public Config(Uri baseUri, String idColumn, String... filePathColumns) {
+            this.baseUri = baseUri;
+            this.idColumn = idColumn;
+            this.filePathColumns = filePathColumns;
+        }
+    }
+
+    public interface Translator {
+        String translate(String data, long id);
+    }
+
+    private final @NonNull Config mConfig;
+    private final @NonNull Translator mTranslator;
+    private final boolean mDropLast;
+
+    private final int mIdIndex;
+    private final int[] mFilePathColIndices;
+
+    private TranslatingCursor(@NonNull Cursor cursor, @NonNull Config config,
+            @NonNull Translator translator, boolean dropLast) {
+        super(cursor);
+
+        mConfig = Objects.requireNonNull(config);
+        mTranslator = Objects.requireNonNull(translator);
+        mDropLast = dropLast;
+
+        mIdIndex = cursor.getColumnIndexOrThrow(config.idColumn);
+        mFilePathColIndices = new int[config.filePathColumns.length];
+        for (int i = mFilePathColIndices.length - 1; i >= 0; --i) {
+            mFilePathColIndices[i] = cursor.getColumnIndex(config.filePathColumns[i]);
+        }
+    }
+
+    @Override
+    public int getColumnCount() {
+        if (mDropLast) {
+            return super.getColumnCount() - 1;
+        } else {
+            return super.getColumnCount();
+        }
+    }
+
+    @Override
+    public String[] getColumnNames() {
+        if (mDropLast) {
+            return Arrays.copyOfRange(super.getColumnNames(), 0, super.getColumnCount() - 1);
+        } else {
+            return super.getColumnNames();
+        }
+    }
+
+    public static Cursor query(@NonNull Config config, @NonNull Translator translator,
+            SQLiteQueryBuilder qb, SQLiteDatabase db, String[] projectionIn, String selection,
+            String[] selectionArgs, String groupBy, String having, String sortOrder, String limit,
+            CancellationSignal signal) {
+        final boolean requestedId = ArrayUtils.isEmpty(projectionIn)
+                || ArrayUtils.contains(projectionIn, config.idColumn);
+        final boolean requestedData = ArrayUtils.isEmpty(projectionIn)
+                || ArrayUtils.containsAny(projectionIn, config.filePathColumns);
+
+        // If caller didn't request data, we have nothing to redirect
+        if (!requestedData || !ContentResolver.DEPRECATE_DATA_COLUMNS) {
+            return qb.query(db, projectionIn, selection, selectionArgs,
+                    groupBy, having, sortOrder, limit, signal);
+        }
+
+        // If caller didn't request id, we need to splice it in
+        if (!requestedId) {
+            projectionIn = ArrayUtils.appendElement(String.class, projectionIn,
+                    config.idColumn);
+        }
+
+        final Cursor c = qb.query(db, projectionIn, selection, selectionArgs,
+                groupBy, having, sortOrder);
+        return new TranslatingCursor(c, config, translator, !requestedId);
+    }
+
+    @Override
+    public void fillWindow(int position, CursorWindow window) {
+        // Fill window directly to ensure data is rewritten
+        DatabaseUtils.cursorFillWindow(this, position, window);
+    }
+
+    @Override
+    public CursorWindow getWindow() {
+        // Returning underlying window risks leaking data
+        return null;
+    }
+
+    @Override
+    public Cursor getWrappedCursor() {
+        throw new UnsupportedOperationException(
+                "Returning underlying cursor risks leaking data");
+    }
+
+    @Override
+    public double getDouble(int columnIndex) {
+        if (ArrayUtils.contains(mFilePathColIndices, columnIndex)) {
+            throw new IllegalArgumentException();
+        } else {
+            return super.getDouble(columnIndex);
+        }
+    }
+
+    @Override
+    public float getFloat(int columnIndex) {
+        if (ArrayUtils.contains(mFilePathColIndices, columnIndex)) {
+            throw new IllegalArgumentException();
+        } else {
+            return super.getFloat(columnIndex);
+        }
+    }
+
+    @Override
+    public int getInt(int columnIndex) {
+        if (ArrayUtils.contains(mFilePathColIndices, columnIndex)) {
+            throw new IllegalArgumentException();
+        } else {
+            return super.getInt(columnIndex);
+        }
+    }
+
+    @Override
+    public long getLong(int columnIndex) {
+        if (ArrayUtils.contains(mFilePathColIndices, columnIndex)) {
+            throw new IllegalArgumentException();
+        } else {
+            return super.getLong(columnIndex);
+        }
+    }
+
+    @Override
+    public short getShort(int columnIndex) {
+        if (ArrayUtils.contains(mFilePathColIndices, columnIndex)) {
+            throw new IllegalArgumentException();
+        } else {
+            return super.getShort(columnIndex);
+        }
+    }
+
+    @Override
+    public String getString(int columnIndex) {
+        if (ArrayUtils.contains(mFilePathColIndices, columnIndex)) {
+            return mTranslator.translate(super.getString(columnIndex), super.getLong(mIdIndex));
+        } else {
+            return super.getString(columnIndex);
+        }
+    }
+
+    @Override
+    public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
+        if (ArrayUtils.contains(mFilePathColIndices, columnIndex)) {
+            throw new IllegalArgumentException();
+        } else {
+            super.copyStringToBuffer(columnIndex, buffer);
+        }
+    }
+
+    @Override
+    public byte[] getBlob(int columnIndex) {
+        if (ArrayUtils.contains(mFilePathColIndices, columnIndex)) {
+            throw new IllegalArgumentException();
+        } else {
+            return super.getBlob(columnIndex);
+        }
+    }
+
+    @Override
+    public int getType(int columnIndex) {
+        if (ArrayUtils.contains(mFilePathColIndices, columnIndex)) {
+            return Cursor.FIELD_TYPE_STRING;
+        } else {
+            return super.getType(columnIndex);
+        }
+    }
+
+    @Override
+    public boolean isNull(int columnIndex) {
+        if (ArrayUtils.contains(mFilePathColIndices, columnIndex)) {
+            return getString(columnIndex) == null;
+        } else {
+            return super.isNull(columnIndex);
+        }
+    }
+}
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index fe00604..ff58c75 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -22,6 +22,7 @@
 import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.RemoteException;
 import android.util.Slog;
 
@@ -64,6 +65,19 @@
 
     private final Context mContext;
     private final IBiometricService mService;
+    private final boolean mHasHardware;
+
+    /**
+     * @param context
+     * @return
+     * @hide
+     */
+    public static boolean hasBiometrics(Context context) {
+        final PackageManager pm = context.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
+                || pm.hasSystemFeature(PackageManager.FEATURE_IRIS)
+                || pm.hasSystemFeature(PackageManager.FEATURE_FACE);
+    }
 
     /**
      * @hide
@@ -73,6 +87,8 @@
     public BiometricManager(Context context, IBiometricService service) {
         mContext = context;
         mService = service;
+
+        mHasHardware = hasBiometrics(context);
     }
 
     /**
@@ -93,8 +109,12 @@
                 throw e.rethrowFromSystemServer();
             }
         } else {
-            Slog.w(TAG, "hasEnrolledBiometrics(): Service not connected");
-            return BIOMETRIC_ERROR_UNAVAILABLE;
+            if (!mHasHardware) {
+                return BIOMETRIC_ERROR_NO_HARDWARE;
+            } else {
+                Slog.w(TAG, "hasEnrolledBiometrics(): Service not connected");
+                return BIOMETRIC_ERROR_UNAVAILABLE;
+            }
         }
     }
 
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 7952c41..bd149fd 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -426,6 +426,31 @@
     }
 
     /**
+     * Authenticates for the given user.
+     * @param cancel An object that can be used to cancel authentication
+     * @param executor An executor to handle callback events
+     * @param callback An object to receive authentication events
+     * @param userId The user to authenticate
+     * @hide
+     */
+    @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+    public void authenticateUser(@NonNull CancellationSignal cancel,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull AuthenticationCallback callback,
+            int userId) {
+        if (cancel == null) {
+            throw new IllegalArgumentException("Must supply a cancellation signal");
+        }
+        if (executor == null) {
+            throw new IllegalArgumentException("Must supply an executor");
+        }
+        if (callback == null) {
+            throw new IllegalArgumentException("Must supply a callback");
+        }
+        authenticateInternal(null /* crypto */, cancel, executor, callback, userId);
+    }
+
+    /**
      * This call warms up the biometric hardware, displays a system-provided dialog, and starts
      * scanning for a biometric. It terminates when {@link
      * AuthenticationCallback#onAuthenticationError(int, CharSequence)} is called, when {@link
@@ -465,7 +490,7 @@
         if (callback == null) {
             throw new IllegalArgumentException("Must supply a callback");
         }
-        authenticateInternal(crypto, cancel, executor, callback);
+        authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId());
     }
 
     /**
@@ -502,7 +527,7 @@
         if (callback == null) {
             throw new IllegalArgumentException("Must supply a callback");
         }
-        authenticateInternal(null /* crypto */, cancel, executor, callback);
+        authenticateInternal(null /* crypto */, cancel, executor, callback, mContext.getUserId());
     }
 
     private void cancelAuthentication() {
@@ -518,7 +543,8 @@
     private void authenticateInternal(@Nullable CryptoObject crypto,
             @NonNull CancellationSignal cancel,
             @NonNull @CallbackExecutor Executor executor,
-            @NonNull AuthenticationCallback callback) {
+            @NonNull AuthenticationCallback callback,
+            int userId) {
         try {
             if (cancel.isCanceled()) {
                 Log.w(TAG, "Authentication already canceled");
@@ -531,7 +557,7 @@
             mExecutor = executor;
             mAuthenticationCallback = callback;
             final long sessionId = crypto != null ? crypto.getOpId() : 0;
-            mService.authenticate(mToken, sessionId, mContext.getUserId(),
+            mService.authenticate(mToken, sessionId, userId,
                     mBiometricServiceReceiver, 0 /* flags */, mContext.getOpPackageName(),
                     mBundle, mDialogReceiver);
         } catch (RemoteException e) {
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 46e66e0..7148b12 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -22,11 +22,13 @@
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.impl.PublicKey;
 import android.hardware.camera2.impl.SyntheticKey;
+import android.hardware.camera2.params.RecommendedStreamConfigurationMap;
 import android.hardware.camera2.params.SessionConfiguration;
 import android.hardware.camera2.utils.ArrayUtils;
 import android.hardware.camera2.utils.TypeReference;
 import android.util.Rational;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
@@ -193,6 +195,7 @@
     private List<CaptureRequest.Key<?>> mAvailableSessionKeys;
     private List<CaptureRequest.Key<?>> mAvailablePhysicalRequestKeys;
     private List<CaptureResult.Key<?>> mAvailableResultKeys;
+    private ArrayList<RecommendedStreamConfigurationMap> mRecommendedConfigurations;
 
     /**
      * Takes ownership of the passed-in properties object
@@ -313,6 +316,103 @@
     }
 
     /**
+     * <p>Retrieve camera device recommended stream configuration map
+     * {@link RecommendedStreamConfigurationMap} for a given use case.</p>
+     *
+     * <p>The stream configurations advertised here are efficient in terms of power and performance
+     * for common use cases like preview, video, snapshot, etc. The recommended maps are usually
+     * only small subsets of the exhaustive list provided in
+     * {@link #SCALER_STREAM_CONFIGURATION_MAP} and suggested for a particular use case by the
+     * camera device implementation. For further information about the expected configurations in
+     * various scenarios please refer to:
+     * <ul>
+     * <li>{@link RecommendedStreamConfigurationMap#USECASE_PREVIEW}</li>
+     * <li>{@link RecommendedStreamConfigurationMap#USECASE_RECORD}</li>
+     * <li>{@link RecommendedStreamConfigurationMap#USECASE_VIDEO_SNAPSHOT}</li>
+     * <li>{@link RecommendedStreamConfigurationMap#USECASE_SNAPSHOT}</li>
+     * <li>{@link RecommendedStreamConfigurationMap#USECASE_RAW}</li>
+     * <li>{@link RecommendedStreamConfigurationMap#USECASE_ZSL}</li>
+     * </ul>
+     * </p>
+     *
+     * <p>For example on how this can be used by camera clients to find out the maximum recommended
+     * preview and snapshot resolution, consider the following pseudo-code:
+     * </p>
+     * <pre><code>
+     * public static Size getMaxSize(Size... sizes) {
+     *     if (sizes == null || sizes.length == 0) {
+     *         throw new IllegalArgumentException("sizes was empty");
+     *     }
+     *
+     *     Size sz = sizes[0];
+     *     for (Size size : sizes) {
+     *         if (size.getWidth() * size.getHeight() &gt; sz.getWidth() * sz.getHeight()) {
+     *             sz = size;
+     *         }
+     *     }
+     *
+     *     return sz;
+     * }
+     *
+     * CameraCharacteristics characteristics =
+     *         cameraManager.getCameraCharacteristics(cameraId);
+     * RecommendedStreamConfigurationMap previewConfig =
+     *         characteristics.getRecommendedStreamConfigurationMap(
+     *                  RecommendedStreamConfigurationMap.USECASE_PREVIEW);
+     * RecommendedStreamConfigurationMap snapshotConfig =
+     *         characteristics.getRecommendedStreamConfigurationMap(
+     *                  RecommendedStreamConfigurationMap.USECASE_SNAPSHOT);
+     *
+     * if ((previewConfig != null) &amp;&amp; (snapshotConfig != null)) {
+     *
+     *      Set<Size> snapshotSizeSet = snapshotConfig.getOutputSizes(
+     *              ImageFormat.JPEG);
+     *      Size[] snapshotSizes = new Size[snapshotSizeSet.size()];
+     *      snapshotSizes = snapshotSizeSet.toArray(snapshotSizes);
+     *      Size suggestedMaxJpegSize = getMaxSize(snapshotSizes);
+     *
+     *      Set<Size> previewSizeSet = snapshotConfig.getOutputSizes(
+     *              ImageFormat.PRIVATE);
+     *      Size[] previewSizes = new Size[previewSizeSet.size()];
+     *      previewSizes = previewSizeSet.toArray(previewSizes);
+     *      Size suggestedMaxPreviewSize = getMaxSize(previewSizes);
+     * }
+     *
+     * </code></pre>
+     *
+     * <p>Similar logic can be used for other use cases as well.</p>
+     *
+     * <p>Support for recommended stream configurations is optional. In case there a no
+     * suggested configurations for the particular use case, please refer to
+     * {@link #SCALER_STREAM_CONFIGURATION_MAP} for the exhaustive available list.</p>
+     *
+     * @param usecase Use case id.
+     *
+     * @throws IllegalArgumentException In case the use case argument is invalid.
+     * @return Valid {@link RecommendedStreamConfigurationMap} or null in case the camera device
+     *         doesn't have any recommendation for this use case or the recommended configurations
+     *         are invalid.
+     */
+    public RecommendedStreamConfigurationMap getRecommendedStreamConfigurationMap(
+            @RecommendedStreamConfigurationMap.RecommendedUsecase int usecase) {
+        if (((usecase >= RecommendedStreamConfigurationMap.USECASE_PREVIEW) &&
+                (usecase <= RecommendedStreamConfigurationMap.USECASE_RAW)) ||
+                ((usecase >= RecommendedStreamConfigurationMap.USECASE_VENDOR_START) &&
+                (usecase < RecommendedStreamConfigurationMap.MAX_USECASE_COUNT))) {
+            if (mRecommendedConfigurations == null) {
+                mRecommendedConfigurations = mProperties.getRecommendedStreamConfigurations();
+                if (mRecommendedConfigurations == null) {
+                    return null;
+                }
+            }
+
+            return mRecommendedConfigurations.get(usecase);
+        }
+
+        throw new IllegalArgumentException(String.format("Invalid use case: %d", usecase));
+    }
+
+    /**
      * <p>Returns a subset of {@link #getAvailableCaptureRequestKeys} keys that the
      * camera device can pass as part of the capture session initialization.</p>
      *
@@ -329,7 +429,7 @@
      * but clients should be aware and expect delays during their application.
      * An example usage scenario could look like this:</p>
      * <ul>
-     * <li>The camera client starts by quering the session parameter key list via
+     * <li>The camera client starts by querying the session parameter key list via
      *   {@link android.hardware.camera2.CameraCharacteristics#getAvailableSessionKeys }.</li>
      * <li>Before triggering the capture session create sequence, a capture request
      *   must be built via {@link CameraDevice#createCaptureRequest } using an
@@ -1583,7 +1683,7 @@
      *   {@link android.graphics.ImageFormat#RAW12 RAW12}.</li>
      * <li>Processed (but not-stalling): any non-RAW format without a stall duration.  Typically
      *   {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888},
-     *   {@link android.graphics.ImageFormat#NV21 NV21}, or {@link android.graphics.ImageFormat#YV12 YV12}.</li>
+     *   {@link android.graphics.ImageFormat#NV21 NV21}, {@link android.graphics.ImageFormat#YV12 YV12}, or {@link android.graphics.ImageFormat#Y8 Y8} .</li>
      * </ul>
      * <p><b>Range of valid values:</b><br></p>
      * <p>For processed (and stalling) format streams, &gt;= 1.</p>
@@ -1646,6 +1746,7 @@
      * <li>{@link android.graphics.ImageFormat#NV21 NV21}</li>
      * <li>{@link android.graphics.ImageFormat#YV12 YV12}</li>
      * <li>Implementation-defined formats, i.e. {@link android.hardware.camera2.params.StreamConfigurationMap#isOutputSupportedFor(Class) }</li>
+     * <li>{@link android.graphics.ImageFormat#Y8 Y8}</li>
      * </ul>
      * <p>For full guarantees, query {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration } with a
      * processed format -- it will return 0 for a non-stalling stream.</p>
@@ -2122,6 +2223,35 @@
      * or output will never hurt maximum frame rate (i.e.  {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputStallDuration getOutputStallDuration(ImageFormat.PRIVATE, size)} is always 0),</p>
      * <p>Attempting to configure an input stream with output streams not
      * listed as available in this map is not valid.</p>
+     * <p>Additionally, if the camera device is MONOCHROME with Y8 support, it will also support
+     * the following map of formats if its dependent capability
+     * ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}) is supported:</p>
+     * <table>
+     * <thead>
+     * <tr>
+     * <th align="left">Input Format</th>
+     * <th align="left">Output Format</th>
+     * <th align="left">Capability</th>
+     * </tr>
+     * </thead>
+     * <tbody>
+     * <tr>
+     * <td align="left">{@link android.graphics.ImageFormat#PRIVATE }</td>
+     * <td align="left">{@link android.graphics.ImageFormat#Y8 }</td>
+     * <td align="left">PRIVATE_REPROCESSING</td>
+     * </tr>
+     * <tr>
+     * <td align="left">{@link android.graphics.ImageFormat#Y8 }</td>
+     * <td align="left">{@link android.graphics.ImageFormat#JPEG }</td>
+     * <td align="left">YUV_REPROCESSING</td>
+     * </tr>
+     * <tr>
+     * <td align="left">{@link android.graphics.ImageFormat#Y8 }</td>
+     * <td align="left">{@link android.graphics.ImageFormat#Y8 }</td>
+     * <td align="left">YUV_REPROCESSING</td>
+     * </tr>
+     * </tbody>
+     * </table>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
@@ -2297,6 +2427,7 @@
      * <li>{@link android.graphics.ImageFormat#YUV_420_888 }</li>
      * <li>{@link android.graphics.ImageFormat#RAW10 }</li>
      * <li>{@link android.graphics.ImageFormat#RAW12 }</li>
+     * <li>{@link android.graphics.ImageFormat#Y8 }</li>
      * </ul>
      * <p>All other formats may or may not have an allowed stall duration on
      * a per-capability basis; refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
@@ -2447,6 +2578,37 @@
             new Key<Integer>("android.scaler.croppingType", int.class);
 
     /**
+     * <p>Recommended stream configurations for common client use cases.</p>
+     * <p>Optional subset of the android.scaler.availableStreamConfigurations that contains
+     * similar tuples listed as
+     * (i.e. width, height, format, output/input stream, usecase bit field).
+     * Camera devices will be able to suggest particular stream configurations which are
+     * power and performance efficient for specific use cases. For more information about
+     * retrieving the suggestions see
+     * {@link android.hardware.camera2.CameraCharacteristics#getRecommendedStreamConfigurationMap }.</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * @hide
+     */
+    public static final Key<android.hardware.camera2.params.RecommendedStreamConfiguration[]> SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS =
+            new Key<android.hardware.camera2.params.RecommendedStreamConfiguration[]>("android.scaler.availableRecommendedStreamConfigurations", android.hardware.camera2.params.RecommendedStreamConfiguration[].class);
+
+    /**
+     * <p>Recommended mappings of image formats that are supported by this
+     * camera device for input streams, to their corresponding output formats.</p>
+     * <p>This is a recommended subset of the complete list of mappings found in
+     * android.scaler.availableInputOutputFormatsMap. The same requirements apply here as well.
+     * The list however doesn't need to contain all available and supported mappings. Instead of
+     * this developers must list only recommended and efficient entries.
+     * If set, the information will be available in the ZERO_SHUTTER_LAG recommended stream
+     * configuration see
+     * {@link android.hardware.camera2.CameraCharacteristics#getRecommendedStreamConfigurationMap }.</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * @hide
+     */
+    public static final Key<android.hardware.camera2.params.ReprocessFormatsMap> SCALER_AVAILABLE_RECOMMENDED_INPUT_OUTPUT_FORMATS_MAP =
+            new Key<android.hardware.camera2.params.ReprocessFormatsMap>("android.scaler.availableRecommendedInputOutputFormatsMap", android.hardware.camera2.params.ReprocessFormatsMap.class);
+
+    /**
      * <p>The area of the image sensor which corresponds to active pixels after any geometric
      * distortion correction has been applied.</p>
      * <p>This is the rectangle representing the size of the active region of the sensor (i.e.
@@ -2506,7 +2668,8 @@
     /**
      * <p>The arrangement of color filters on sensor;
      * represents the colors in the top-left 2x2 section of
-     * the sensor, in reading order.</p>
+     * the sensor, in reading order, for a Bayer camera, or the
+     * light spectrum it captures for MONOCHROME camera.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB RGGB}</li>
@@ -2514,6 +2677,8 @@
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG GBRG}</li>
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR BGGR}</li>
      *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB RGB}</li>
+     *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO MONO}</li>
+     *   <li>{@link #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR NIR}</li>
      * </ul></p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Full capability</b> -
@@ -2526,6 +2691,8 @@
      * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG
      * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR
      * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB
+     * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO
+     * @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR
      */
     @PublicKey
     public static final Key<Integer> SENSOR_INFO_COLOR_FILTER_ARRANGEMENT =
@@ -2757,6 +2924,8 @@
      * <p>Some devices may choose to provide a second set of calibration
      * information for improved quality, including
      * {@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2 android.sensor.referenceIlluminant2} and its corresponding matrices.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Possible values:</b>
      * <ul>
      *   <li>{@link #SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT DAYLIGHT}</li>
@@ -2819,6 +2988,8 @@
      * <p>If this key is present, then {@link CameraCharacteristics#SENSOR_COLOR_TRANSFORM2 android.sensor.colorTransform2},
      * {@link CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM2 android.sensor.calibrationTransform2}, and
      * {@link CameraCharacteristics#SENSOR_FORWARD_MATRIX2 android.sensor.forwardMatrix2} will also be present.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Range of valid values:</b><br>
      * Any value listed in {@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1 android.sensor.referenceIlluminant1}</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -2844,6 +3015,8 @@
      * colorspace) into this camera device's native sensor color
      * space under the first reference illuminant
      * ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1 android.sensor.referenceIlluminant1}).</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -2867,6 +3040,8 @@
      * ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2 android.sensor.referenceIlluminant2}).</p>
      * <p>This matrix will only be present if the second reference
      * illuminant is present.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -2891,6 +3066,8 @@
      * and the CIE XYZ colorspace when calculating this transform will
      * match the standard white point for the first reference illuminant
      * (i.e. no chromatic adaptation will be applied by this transform).</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -2917,6 +3094,8 @@
      * (i.e. no chromatic adaptation will be applied by this transform).</p>
      * <p>This matrix will only be present if the second reference
      * illuminant is present.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -2939,6 +3118,8 @@
      * this matrix is chosen so that the standard white point for this reference
      * illuminant in the reference sensor colorspace is mapped to D50 in the
      * CIE XYZ colorspace.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -2963,6 +3144,8 @@
      * CIE XYZ colorspace.</p>
      * <p>This matrix will only be present if the second reference
      * illuminant is present.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      * <p><b>Permission {@link android.Manifest.permission#CAMERA } is needed to access this property</b></p>
      *
@@ -2991,6 +3174,7 @@
      * level values. For raw capture in particular, it is recommended to use
      * pixels from {@link CameraCharacteristics#SENSOR_OPTICAL_BLACK_REGIONS android.sensor.opticalBlackRegions} to calculate black
      * level values for each frame.</p>
+     * <p>For a MONOCHROME camera device, all of the 2x2 channels must have the same values.</p>
      * <p><b>Range of valid values:</b><br>
      * &gt;= 0 for each.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -3487,6 +3671,21 @@
             new Key<Boolean>("android.depth.depthIsExclusive", boolean.class);
 
     /**
+     * <p>Recommended depth stream configurations for common client use cases.</p>
+     * <p>Optional subset of the android.depth.availableDepthStreamConfigurations that
+     * contains similar tuples listed as
+     * (i.e. width, height, format, output/input stream, usecase bit field).
+     * Camera devices will be able to suggest particular depth stream configurations which are
+     * power and performance efficient for specific use cases. For more information about
+     * retrieving the suggestions see
+     * {@link android.hardware.camera2.CameraCharacteristics#getRecommendedStreamConfigurationMap }.</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     * @hide
+     */
+    public static final Key<android.hardware.camera2.params.RecommendedStreamConfiguration[]> DEPTH_AVAILABLE_RECOMMENDED_DEPTH_STREAM_CONFIGURATIONS =
+            new Key<android.hardware.camera2.params.RecommendedStreamConfiguration[]>("android.depth.availableRecommendedDepthStreamConfigurations", android.hardware.camera2.params.RecommendedStreamConfiguration[].class);
+
+    /**
      * <p>String containing the ids of the underlying physical cameras.</p>
      * <p>For a logical camera, this is concatenation of all underlying physical camera ids.
      * The null terminator for physical camera id must be preserved so that the whole string
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index ce88697..dc6cffc 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -356,6 +356,12 @@
      * </table><br>
      * </p>
      *
+     * <p>MONOCHROME-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}
+     * includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME}) devices
+     * supporting {@link android.graphics.ImageFormat#Y8 Y8} support substituting {@code YUV}
+     * streams with {@code Y8} in all guaranteed stream combinations for the device's hardware level
+     * and capabilities.</p>
+     *
      * <p>FULL-level ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
      * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices
      * support at least the following stream combinations in addition to those for
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index d4dc181..402472a 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -539,6 +539,8 @@
      * <li>{@link android.graphics.ImageFormat#PRIVATE } will be reprocessable into both
      *   {@link android.graphics.ImageFormat#YUV_420_888 } and
      *   {@link android.graphics.ImageFormat#JPEG } formats.</li>
+     * <li>For a MONOCHROME camera supporting Y8 format, {@link android.graphics.ImageFormat#PRIVATE } will be reprocessable into
+     *   {@link android.graphics.ImageFormat#Y8 }.</li>
      * <li>The maximum available resolution for PRIVATE streams
      *   (both input/output) will match the maximum available
      *   resolution of JPEG streams.</li>
@@ -612,7 +614,7 @@
      * then the list of resolutions for YUV_420_888 from {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputSizes } contains at
      * least one resolution &gt;= 8 megapixels, with a minimum frame duration of &lt;= 1/20
      * s.</p>
-     * <p>If the device supports the {@link android.graphics.ImageFormat#RAW10 }, {@link android.graphics.ImageFormat#RAW12 }, then those can also be
+     * <p>If the device supports the {@link android.graphics.ImageFormat#RAW10 }, {@link android.graphics.ImageFormat#RAW12 }, {@link android.graphics.ImageFormat#Y8 }, then those can also be
      * captured at the same rate as the maximum-size YUV_420_888 resolution is.</p>
      * <p>If the device supports the PRIVATE_REPROCESSING capability, then the same guarantees
      * as for the YUV_420_888 format also apply to the {@link android.graphics.ImageFormat#PRIVATE } format.</p>
@@ -646,6 +648,8 @@
      *   {@link android.graphics.ImageFormat#YUV_420_888 } and {@link android.graphics.ImageFormat#JPEG } formats.</li>
      * <li>The maximum available resolution for {@link android.graphics.ImageFormat#YUV_420_888 } streams (both input/output) will match the
      *   maximum available resolution of {@link android.graphics.ImageFormat#JPEG } streams.</li>
+     * <li>For a MONOCHROME camera with Y8 format support, all the requirements mentioned
+     *   above for YUV_420_888 apply for Y8 format as well.</li>
      * <li>Static metadata {@link CameraCharacteristics#REPROCESS_MAX_CAPTURE_STALL android.reprocess.maxCaptureStall}.</li>
      * <li>Only the below controls are effective for reprocessing requests and will be present
      *   in capture results. The reprocess requests are from the original capture results
@@ -692,8 +696,8 @@
      * <li>The {@link CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE android.depth.depthIsExclusive} entry is listed by this device.</li>
      * <li>As of Android P, the {@link CameraCharacteristics#LENS_POSE_REFERENCE android.lens.poseReference} entry is listed by this device.</li>
      * <li>A LIMITED camera with only the DEPTH_OUTPUT capability does not have to support
-     *   normal YUV_420_888, JPEG, and PRIV-format outputs. It only has to support the DEPTH16
-     *   format.</li>
+     *   normal YUV_420_888, Y8, JPEG, and PRIV-format outputs. It only has to support the
+     *   DEPTH16 format.</li>
      * </ul>
      * <p>Generally, depth output operates at a slower frame rate than standard color capture,
      * so the DEPTH16 and DEPTH_POINT_CLOUD formats will commonly have a stall duration that
@@ -876,7 +880,15 @@
 
     /**
      * <p>The camera device is a monochrome camera that doesn't contain a color filter array,
-     * and the pixel values on U and V planes are all 128.</p>
+     * and for YUV_420_888 stream, the pixel values on U and V planes are all 128.</p>
+     * <p>A MONOCHROME camera must support the guaranteed stream combinations required for
+     * its device level and capabilities. Additionally, if the monochrome camera device
+     * supports Y8 format, all mandatory stream combination requirements related to {@link android.graphics.ImageFormat#YUV_420_888 YUV_420_888} apply
+     * to {@link android.graphics.ImageFormat#Y8 Y8} as well. There are no
+     * mandatory stream combination requirements with regard to
+     * {@link android.graphics.ImageFormat#Y8 Y8} for Bayer camera devices.</p>
+     * <p>Starting from Android Q, the SENSOR_INFO_COLOR_FILTER_ARRANGEMENT of a MONOCHROME
+     * camera will be either MONO or NIR.</p>
      * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      */
     public static final int REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME = 12;
@@ -929,6 +941,23 @@
      */
     public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4;
 
+    /**
+     * <p>Sensor doesn't have any Bayer color filter.
+     * Such sensor captures visible light in monochrome. The exact weighting and
+     * wavelengths captured is not specified, but generally only includes the visible
+     * frequencies. This value implies a MONOCHROME camera.</p>
+     * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+     */
+    public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO = 5;
+
+    /**
+     * <p>Sensor has a near infrared filter capturing light with wavelength between
+     * roughly 750nm and 1400nm, and the same filter covers the whole sensor array. This
+     * value implies a MONOCHROME camera.</p>
+     * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+     */
+    public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR = 6;
+
     //
     // Enumeration values for CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE
     //
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 4a20468..8ebaf2f 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -24,8 +24,8 @@
 import android.hardware.camera2.impl.SyntheticKey;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.hardware.camera2.utils.HashCodeHelpers;
-import android.hardware.camera2.utils.TypeReference;
 import android.hardware.camera2.utils.SurfaceUtils;
+import android.hardware.camera2.utils.TypeReference;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArraySet;
@@ -2947,8 +2947,8 @@
      * of points can be less than max (that is, the request doesn't have to
      * always provide a curve with number of points equivalent to
      * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}).</p>
-     * <p>For devices with MONOCHROME capability, only red channel is used. Green and blue channels
-     * are ignored.</p>
+     * <p>For devices with MONOCHROME capability, all three channels must have the same set of
+     * control points.</p>
      * <p>A few examples, and their corresponding graphical mappings; these
      * only specify the red channel and the precision is limited to 4
      * digits, for conciseness.</p>
@@ -3011,8 +3011,8 @@
      * of points can be less than max (that is, the request doesn't have to
      * always provide a curve with number of points equivalent to
      * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}).</p>
-     * <p>For devices with MONOCHROME capability, only red channel is used. Green and blue channels
-     * are ignored.</p>
+     * <p>For devices with MONOCHROME capability, all three channels must have the same set of
+     * control points.</p>
      * <p>A few examples, and their corresponding graphical mappings; these
      * only specify the red channel and the precision is limited to 4
      * digits, for conciseness.</p>
@@ -3277,8 +3277,8 @@
      * will not slow down capture rate when applying correction. FAST may be the same as OFF if
      * any correction at all would slow down capture rate.  Every output stream will have a
      * similar amount of enhancement applied.</p>
-     * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
-     * applied to any RAW output.</p>
+     * <p>The correction only applies to processed outputs such as YUV, Y8, JPEG, or DEPTH16; it is
+     * not applied to any RAW output.</p>
      * <p>This control will be on by default on devices that support this control. Applications
      * disabling distortion correction need to pay extra attention with the coordinate system of
      * metering regions, crop region, and face rectangles. When distortion correction is OFF,
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index a7e185c..3d70c51 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -3417,6 +3417,8 @@
      * used to interpolate between the provided color transforms when
      * processing raw sensor data.</p>
      * <p>The order of the values is R, G, B; where R is in the lowest index.</p>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      */
     @PublicKey
@@ -3442,6 +3444,8 @@
      * that channel.</p>
      * <p>A more detailed description of the noise model can be found in the
      * Adobe DNG specification for the NoiseProfile tag.</p>
+     * <p>For a MONOCHROME camera, there is only one color channel. So the noise model coefficients
+     * will only contain one S and one O.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      *
      * @see CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
@@ -3482,6 +3486,8 @@
      * <li>R &gt; 1.20 will require strong software correction to produce
      * a usuable image (&gt;20% divergence).</li>
      * </ul>
+     * <p>Starting from Android Q, this key will not be present for a MONOCHROME camera, even if
+     * the camera device has RAW capability.</p>
      * <p><b>Range of valid values:</b><br></p>
      * <p>&gt;= 0</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -3592,6 +3598,7 @@
      * layout key (see {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT android.sensor.info.colorFilterArrangement}), i.e. the
      * nth value given corresponds to the black level offset for the nth
      * color channel listed in the CFA.</p>
+     * <p>For a MONOCHROME camera, all of the 2x2 channels must have the same values.</p>
      * <p>This key will be available if {@link CameraCharacteristics#SENSOR_OPTICAL_BLACK_REGIONS android.sensor.opticalBlackRegions} is available or the
      * camera device advertises this key via {@link android.hardware.camera2.CameraCharacteristics#getAvailableCaptureResultKeys }.</p>
      * <p><b>Range of valid values:</b><br>
@@ -3852,6 +3859,17 @@
      * <p>As a visualization only, inverting the full-color map to recover an
      * image of a gray wall (using bicubic interpolation for visual quality) as captured by the sensor gives:</p>
      * <p><img alt="Image of a uniform white wall (inverse shading map)" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png" /></p>
+     * <p>For a MONOCHROME camera, all of the 2x2 channels must have the same values. An example
+     * shading map for such a camera is defined as:</p>
+     * <pre><code>android.lens.info.shadingMapSize = [ 4, 3 ]
+     * android.statistics.lensShadingMap =
+     * [ 1.3, 1.3, 1.3, 1.3,  1.2, 1.2, 1.2, 1.2,
+     *     1.1, 1.1, 1.1, 1.1,  1.3, 1.3, 1.3, 1.3,
+     *   1.2, 1.2, 1.2, 1.2,  1.1, 1.1, 1.1, 1.1,
+     *     1.0, 1.0, 1.0, 1.0,  1.2, 1.2, 1.2, 1.2,
+     *   1.3, 1.3, 1.3, 1.3,   1.2, 1.2, 1.2, 1.2,
+     *     1.2, 1.2, 1.2, 1.2,  1.3, 1.3, 1.3, 1.3 ]
+     * </code></pre>
      * <p><b>Range of valid values:</b><br>
      * Each gain factor is &gt;= 1</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
@@ -3894,13 +3912,13 @@
      * (x,y) ϵ (0 ... N-1, 0 ... M-1) is the value of the shading map at
      * pixel ( ((W-1)/(N-1)) * x, ((H-1)/(M-1)) * y) for the four color channels.
      * The map is assumed to be bilinearly interpolated between the sample points.</p>
-     * <p>The channel order is [R, Geven, Godd, B], where Geven is the green
-     * channel for the even rows of a Bayer pattern, and Godd is the odd rows.
+     * <p>For a Bayer camera, the channel order is [R, Geven, Godd, B], where Geven is
+     * the green channel for the even rows of a Bayer pattern, and Godd is the odd rows.
      * The shading map is stored in a fully interleaved format, and its size
      * is provided in the camera static metadata by android.lens.info.shadingMapSize.</p>
      * <p>The shading map will generally have on the order of 30-40 rows and columns,
      * and will be smaller than 64x64.</p>
-     * <p>As an example, given a very small map defined as:</p>
+     * <p>As an example, given a very small map for a Bayer camera defined as:</p>
      * <pre><code>android.lens.info.shadingMapSize = [ 4, 3 ]
      * android.statistics.lensShadingMap =
      * [ 1.3, 1.2, 1.15, 1.2,  1.2, 1.2, 1.15, 1.2,
@@ -3920,6 +3938,17 @@
      * image of a gray wall (using bicubic interpolation for visual quality)
      * as captured by the sensor gives:</p>
      * <p><img alt="Image of a uniform white wall (inverse shading map)" src="/reference/images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png" /></p>
+     * <p>For a MONOCHROME camera, all of the 2x2 channels must have the same values. An example
+     * shading map for such a camera is defined as:</p>
+     * <pre><code>android.lens.info.shadingMapSize = [ 4, 3 ]
+     * android.statistics.lensShadingMap =
+     * [ 1.3, 1.3, 1.3, 1.3,  1.2, 1.2, 1.2, 1.2,
+     *     1.1, 1.1, 1.1, 1.1,  1.3, 1.3, 1.3, 1.3,
+     *   1.2, 1.2, 1.2, 1.2,  1.1, 1.1, 1.1, 1.1,
+     *     1.0, 1.0, 1.0, 1.0,  1.2, 1.2, 1.2, 1.2,
+     *   1.3, 1.3, 1.3, 1.3,   1.2, 1.2, 1.2, 1.2,
+     *     1.2, 1.2, 1.2, 1.2,  1.3, 1.3, 1.3, 1.3 ]
+     * </code></pre>
      * <p>Note that the RAW image data might be subject to lens shading
      * correction not reported on this map. Query
      * {@link CameraCharacteristics#SENSOR_INFO_LENS_SHADING_APPLIED android.sensor.info.lensShadingApplied} to see if RAW image data has subject
@@ -4250,8 +4279,8 @@
      * of points can be less than max (that is, the request doesn't have to
      * always provide a curve with number of points equivalent to
      * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}).</p>
-     * <p>For devices with MONOCHROME capability, only red channel is used. Green and blue channels
-     * are ignored.</p>
+     * <p>For devices with MONOCHROME capability, all three channels must have the same set of
+     * control points.</p>
      * <p>A few examples, and their corresponding graphical mappings; these
      * only specify the red channel and the precision is limited to 4
      * digits, for conciseness.</p>
@@ -4314,8 +4343,8 @@
      * of points can be less than max (that is, the request doesn't have to
      * always provide a curve with number of points equivalent to
      * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS android.tonemap.maxCurvePoints}).</p>
-     * <p>For devices with MONOCHROME capability, only red channel is used. Green and blue channels
-     * are ignored.</p>
+     * <p>For devices with MONOCHROME capability, all three channels must have the same set of
+     * control points.</p>
      * <p>A few examples, and their corresponding graphical mappings; these
      * only specify the red channel and the precision is limited to 4
      * digits, for conciseness.</p>
@@ -4620,8 +4649,8 @@
      * will not slow down capture rate when applying correction. FAST may be the same as OFF if
      * any correction at all would slow down capture rate.  Every output stream will have a
      * similar amount of enhancement applied.</p>
-     * <p>The correction only applies to processed outputs such as YUV, JPEG, or DEPTH16; it is not
-     * applied to any RAW output.</p>
+     * <p>The correction only applies to processed outputs such as YUV, Y8, JPEG, or DEPTH16; it is
+     * not applied to any RAW output.</p>
      * <p>This control will be on by default on devices that support this control. Applications
      * disabling distortion correction need to pay extra attention with the coordinate system of
      * metering regions, crop region, and face rectangles. When distortion correction is OFF,
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 0610d7a..f81bd13 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -21,6 +21,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.marshal.MarshalQueryable;
@@ -38,6 +39,7 @@
 import android.hardware.camera2.marshal.impl.MarshalQueryableParcelable;
 import android.hardware.camera2.marshal.impl.MarshalQueryablePrimitive;
 import android.hardware.camera2.marshal.impl.MarshalQueryableRange;
+import android.hardware.camera2.marshal.impl.MarshalQueryableRecommendedStreamConfiguration;
 import android.hardware.camera2.marshal.impl.MarshalQueryableRect;
 import android.hardware.camera2.marshal.impl.MarshalQueryableReprocessFormatsMap;
 import android.hardware.camera2.marshal.impl.MarshalQueryableRggbChannelVector;
@@ -50,6 +52,8 @@
 import android.hardware.camera2.params.HighSpeedVideoConfiguration;
 import android.hardware.camera2.params.LensShadingMap;
 import android.hardware.camera2.params.OisSample;
+import android.hardware.camera2.params.RecommendedStreamConfiguration;
+import android.hardware.camera2.params.RecommendedStreamConfigurationMap;
 import android.hardware.camera2.params.ReprocessFormatsMap;
 import android.hardware.camera2.params.StreamConfiguration;
 import android.hardware.camera2.params.StreamConfigurationDuration;
@@ -911,6 +915,252 @@
         return true;
     }
 
+    private void parseRecommendedConfigurations(RecommendedStreamConfiguration[] configurations,
+            StreamConfigurationMap fullMap, boolean isDepth,
+            ArrayList<ArrayList<StreamConfiguration>> /*out*/streamConfigList,
+            ArrayList<ArrayList<StreamConfigurationDuration>> /*out*/streamDurationList,
+            ArrayList<ArrayList<StreamConfigurationDuration>> /*out*/streamStallList,
+            boolean[] /*out*/supportsPrivate) {
+
+        streamConfigList.ensureCapacity(RecommendedStreamConfigurationMap.MAX_USECASE_COUNT);
+        streamDurationList.ensureCapacity(RecommendedStreamConfigurationMap.MAX_USECASE_COUNT);
+        streamStallList.ensureCapacity(RecommendedStreamConfigurationMap.MAX_USECASE_COUNT);
+        for (int i = 0; i < RecommendedStreamConfigurationMap.MAX_USECASE_COUNT; i++) {
+            streamConfigList.add(new ArrayList<StreamConfiguration> ());
+            streamDurationList.add(new ArrayList<StreamConfigurationDuration> ());
+            streamStallList.add(new ArrayList<StreamConfigurationDuration> ());
+        }
+
+        for (RecommendedStreamConfiguration c : configurations) {
+            int width = c.getWidth();
+            int height = c.getHeight();
+            int internalFormat = c.getFormat();
+            int publicFormat =
+                (isDepth) ? StreamConfigurationMap.depthFormatToPublic(internalFormat) :
+                StreamConfigurationMap.imageFormatToPublic(internalFormat);
+            Size sz = new Size(width, height);
+            int usecaseBitmap = c.getUsecaseBitmap();
+
+            if (!c.isInput()) {
+                StreamConfigurationDuration minDurationConfiguration = null;
+                StreamConfigurationDuration stallDurationConfiguration = null;
+
+                StreamConfiguration streamConfiguration = new StreamConfiguration(internalFormat,
+                        width, height, /*input*/ false);
+
+                long minFrameDuration = fullMap.getOutputMinFrameDuration(publicFormat, sz);
+                if (minFrameDuration > 0) {
+                    minDurationConfiguration = new StreamConfigurationDuration(internalFormat,
+                            width, height, minFrameDuration);
+                }
+
+                long stallDuration = fullMap.getOutputStallDuration(publicFormat, sz);
+                if (stallDuration > 0) {
+                    stallDurationConfiguration = new StreamConfigurationDuration(internalFormat,
+                            width, height, stallDuration);
+                }
+
+                for (int i = 0; i < RecommendedStreamConfigurationMap.MAX_USECASE_COUNT; i++) {
+                    if ((usecaseBitmap & (1 << i)) != 0) {
+                        ArrayList<StreamConfiguration> sc = streamConfigList.get(i);
+                        sc.add(streamConfiguration);
+
+                        if (minFrameDuration > 0) {
+                            ArrayList<StreamConfigurationDuration> scd = streamDurationList.get(i);
+                            scd.add(minDurationConfiguration);
+                        }
+
+                        if (stallDuration > 0) {
+                            ArrayList<StreamConfigurationDuration> scs = streamStallList.get(i);
+                            scs.add(stallDurationConfiguration);
+                        }
+
+                        if ((supportsPrivate != null) && !supportsPrivate[i] &&
+                                (publicFormat == ImageFormat.PRIVATE)) {
+                            supportsPrivate[i] = true;
+                        }
+                    }
+                }
+            } else {
+                if (usecaseBitmap != (1 << RecommendedStreamConfigurationMap.USECASE_ZSL)) {
+                    throw new IllegalArgumentException("Recommended input stream configurations " +
+                            "should only be advertised in the ZSL use case!");
+                }
+
+                ArrayList<StreamConfiguration> sc = streamConfigList.get(
+                        RecommendedStreamConfigurationMap.USECASE_ZSL);
+                sc.add(new StreamConfiguration(internalFormat,
+                        width, height, /*input*/ true));
+            }
+        }
+    }
+
+    private class StreamConfigurationData {
+        StreamConfiguration [] streamConfigurationArray = null;
+        StreamConfigurationDuration [] minDurationArray = null;
+        StreamConfigurationDuration [] stallDurationArray = null;
+    }
+
+    public void initializeStreamConfigurationData(ArrayList<StreamConfiguration> sc,
+            ArrayList<StreamConfigurationDuration> scd, ArrayList<StreamConfigurationDuration> scs,
+            StreamConfigurationData /*out*/scData) {
+        if ((scData == null) || (sc == null)) {
+            return;
+        }
+
+        scData.streamConfigurationArray = new StreamConfiguration[sc.size()];
+        scData.streamConfigurationArray = sc.toArray(scData.streamConfigurationArray);
+
+        if ((scd != null) && !scd.isEmpty()) {
+            scData.minDurationArray = new StreamConfigurationDuration[scd.size()];
+            scData.minDurationArray = scd.toArray(scData.minDurationArray);
+        } else {
+            scData.minDurationArray = new StreamConfigurationDuration[0];
+        }
+
+        if ((scs != null) && !scs.isEmpty()) {
+            scData.stallDurationArray = new StreamConfigurationDuration[scs.size()];
+            scData.stallDurationArray = scs.toArray(scData.stallDurationArray);
+        } else {
+            scData.stallDurationArray = new StreamConfigurationDuration[0];
+        }
+    }
+
+    /**
+     * Retrieve the list of recommended stream configurations.
+     *
+     * @return A list of recommended stream configuration maps for each common use case or null
+     *         in case the recommended stream configurations are invalid or incomplete.
+     * @hide
+     */
+    public ArrayList<RecommendedStreamConfigurationMap> getRecommendedStreamConfigurations() {
+        RecommendedStreamConfiguration[] configurations = getBase(
+                CameraCharacteristics.SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS);
+        RecommendedStreamConfiguration[] depthConfigurations = getBase(
+                CameraCharacteristics.DEPTH_AVAILABLE_RECOMMENDED_DEPTH_STREAM_CONFIGURATIONS);
+        if ((configurations == null) && (depthConfigurations == null)) {
+            return null;
+        }
+
+        StreamConfigurationMap fullMap = getStreamConfigurationMap();
+        ArrayList<RecommendedStreamConfigurationMap> recommendedConfigurations =
+            new ArrayList<RecommendedStreamConfigurationMap> ();
+
+        ArrayList<ArrayList<StreamConfiguration>> streamConfigList =
+            new ArrayList<ArrayList<StreamConfiguration>>();
+        ArrayList<ArrayList<StreamConfigurationDuration>> streamDurationList =
+            new ArrayList<ArrayList<StreamConfigurationDuration>>();
+        ArrayList<ArrayList<StreamConfigurationDuration>> streamStallList =
+            new ArrayList<ArrayList<StreamConfigurationDuration>>();
+        boolean[] supportsPrivate =
+                new boolean[RecommendedStreamConfigurationMap.MAX_USECASE_COUNT];
+        try {
+            if (configurations != null) {
+                parseRecommendedConfigurations(configurations, fullMap, /*isDepth*/ false,
+                        streamConfigList, streamDurationList, streamStallList, supportsPrivate);
+            }
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "Failed parsing the recommended stream configurations!");
+            return null;
+        }
+
+        ArrayList<ArrayList<StreamConfiguration>> depthStreamConfigList =
+            new ArrayList<ArrayList<StreamConfiguration>>();
+        ArrayList<ArrayList<StreamConfigurationDuration>> depthStreamDurationList =
+            new ArrayList<ArrayList<StreamConfigurationDuration>>();
+        ArrayList<ArrayList<StreamConfigurationDuration>> depthStreamStallList =
+            new ArrayList<ArrayList<StreamConfigurationDuration>>();
+        if (depthConfigurations != null) {
+            try {
+                parseRecommendedConfigurations(depthConfigurations, fullMap, /*isDepth*/ true,
+                        depthStreamConfigList, depthStreamDurationList, depthStreamStallList,
+                        /*supportsPrivate*/ null);
+            } catch (IllegalArgumentException e) {
+                Log.e(TAG, "Failed parsing the recommended depth stream configurations!");
+                return null;
+            }
+        }
+
+        ReprocessFormatsMap inputOutputFormatsMap = getBase(
+                CameraCharacteristics.SCALER_AVAILABLE_RECOMMENDED_INPUT_OUTPUT_FORMATS_MAP);
+        HighSpeedVideoConfiguration[] highSpeedVideoConfigurations = getBase(
+                CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
+        boolean listHighResolution = isBurstSupported();
+        recommendedConfigurations.ensureCapacity(
+                RecommendedStreamConfigurationMap.MAX_USECASE_COUNT);
+        for (int i = 0; i < RecommendedStreamConfigurationMap.MAX_USECASE_COUNT; i++) {
+            StreamConfigurationData scData = new StreamConfigurationData();
+            if (configurations != null) {
+                initializeStreamConfigurationData(streamConfigList.get(i),
+                        streamDurationList.get(i), streamStallList.get(i), scData);
+            }
+
+            StreamConfigurationData depthScData = new StreamConfigurationData();
+            if (depthConfigurations != null) {
+                initializeStreamConfigurationData(depthStreamConfigList.get(i),
+                        depthStreamDurationList.get(i), depthStreamStallList.get(i), depthScData);
+            }
+
+            if ((scData.streamConfigurationArray == null) &&
+                    (depthScData.streamConfigurationArray == null)) {
+                recommendedConfigurations.add(null);
+                continue;
+            }
+
+            StreamConfigurationMap map = null;
+            switch (i) {
+                case RecommendedStreamConfigurationMap.USECASE_PREVIEW:
+                case RecommendedStreamConfigurationMap.USECASE_RAW:
+                case RecommendedStreamConfigurationMap.USECASE_VIDEO_SNAPSHOT:
+                    map = new StreamConfigurationMap(scData.streamConfigurationArray,
+                            scData.minDurationArray, scData.stallDurationArray,
+                            /*depthconfiguration*/ null, /*depthminduration*/ null,
+                            /*depthstallduration*/ null, /*highspeedvideoconfigurations*/ null,
+                            /*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]);
+                    break;
+                case RecommendedStreamConfigurationMap.USECASE_RECORD:
+                    map = new StreamConfigurationMap(scData.streamConfigurationArray,
+                            scData.minDurationArray, scData.stallDurationArray,
+                            /*depthconfiguration*/ null, /*depthminduration*/ null,
+                            /*depthstallduration*/ null, highSpeedVideoConfigurations,
+                            /*inputoutputformatsmap*/ null, listHighResolution, supportsPrivate[i]);
+                    break;
+                case RecommendedStreamConfigurationMap.USECASE_ZSL:
+                    map = new StreamConfigurationMap(scData.streamConfigurationArray,
+                            scData.minDurationArray, scData.stallDurationArray,
+                            depthScData.streamConfigurationArray, depthScData.minDurationArray,
+                            depthScData.stallDurationArray, /*highSpeedVideoConfigurations*/ null,
+                            inputOutputFormatsMap, listHighResolution, supportsPrivate[i]);
+                    break;
+                default:
+                    map = new StreamConfigurationMap(scData.streamConfigurationArray,
+                            scData.minDurationArray, scData.stallDurationArray,
+                            depthScData.streamConfigurationArray, depthScData.minDurationArray,
+                            depthScData.stallDurationArray, /*highSpeedVideoConfigurations*/ null,
+                            /*inputOutputFormatsMap*/ null, listHighResolution, supportsPrivate[i]);
+            }
+
+            recommendedConfigurations.add(new RecommendedStreamConfigurationMap(map, /*usecase*/i,
+                        supportsPrivate[i]));
+        }
+
+        return recommendedConfigurations;
+    }
+
+    private boolean isBurstSupported() {
+        boolean ret = false;
+
+        int[] capabilities = getBase(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+        for (int capability : capabilities) {
+            if (capability == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE) {
+                ret = true;
+                break;
+            }
+        }
+
+        return ret;
+    }
+
     private StreamConfigurationMap getStreamConfigurationMap() {
         StreamConfiguration[] configurations = getBase(
                 CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
@@ -928,14 +1178,7 @@
                 CameraCharacteristics.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
         ReprocessFormatsMap inputOutputFormatsMap = getBase(
                 CameraCharacteristics.SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP);
-        int[] capabilities = getBase(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
-        boolean listHighResolution = false;
-        for (int capability : capabilities) {
-            if (capability == CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE) {
-                listHighResolution = true;
-                break;
-            }
-        }
+        boolean listHighResolution = isBurstSupported();
         return new StreamConfigurationMap(
                 configurations, minFrameDurations, stallDurations,
                 depthConfigurations, depthMinFrameDurations, depthStallDurations,
@@ -1399,6 +1642,7 @@
                 new MarshalQueryableRggbChannelVector(),
                 new MarshalQueryableBlackLevelPattern(),
                 new MarshalQueryableHighSpeedVideoConfiguration(),
+                new MarshalQueryableRecommendedStreamConfiguration(),
 
                 // generic parcelable marshaler (MUST BE LAST since it has lowest priority)
                 new MarshalQueryableParcelable(),
diff --git a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableRecommendedStreamConfiguration.java b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableRecommendedStreamConfiguration.java
new file mode 100644
index 0000000..22a76b7
--- /dev/null
+++ b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableRecommendedStreamConfiguration.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.marshal.impl;
+
+import android.hardware.camera2.marshal.Marshaler;
+import android.hardware.camera2.marshal.MarshalQueryable;
+import android.hardware.camera2.params.RecommendedStreamConfiguration;
+import android.hardware.camera2.utils.TypeReference;
+
+import static android.hardware.camera2.impl.CameraMetadataNative.*;
+import static android.hardware.camera2.marshal.MarshalHelpers.*;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Marshaler for {@code android.scaler.availableRecommendedStreamConfigurations} custom class
+ * {@link RecommendedStreamConfiguration}
+ *
+ * <p>Data is stored as {@code (width, height, format, input, usecaseBitmap)} tuples (int32).</p>
+ */
+public class MarshalQueryableRecommendedStreamConfiguration
+        implements MarshalQueryable<RecommendedStreamConfiguration> {
+    private static final int SIZE = SIZEOF_INT32 * 5;
+
+    private class MarshalerRecommendedStreamConfiguration
+            extends Marshaler<RecommendedStreamConfiguration> {
+        protected MarshalerRecommendedStreamConfiguration(
+                TypeReference<RecommendedStreamConfiguration> typeReference, int nativeType) {
+            super(MarshalQueryableRecommendedStreamConfiguration.this, typeReference, nativeType);
+        }
+
+        @Override
+        public void marshal(RecommendedStreamConfiguration value, ByteBuffer buffer) {
+            buffer.putInt(value.getWidth());
+            buffer.putInt(value.getHeight());
+            buffer.putInt(value.getFormat());
+            buffer.putInt(value.isInput() ? 1 : 0);
+            buffer.putInt(value.getUsecaseBitmap());
+        }
+
+        @Override
+        public RecommendedStreamConfiguration unmarshal(ByteBuffer buffer) {
+            int width = buffer.getInt();
+            int height = buffer.getInt();
+            int format = buffer.getInt();
+            boolean input = buffer.getInt() != 0;
+            int usecaseBitmap = buffer.getInt();
+
+            return new RecommendedStreamConfiguration(format, width, height, input, usecaseBitmap);
+        }
+
+        @Override
+        public int getNativeSize() {
+            return SIZE;
+        }
+
+    }
+
+    @Override
+    public Marshaler<RecommendedStreamConfiguration> createMarshaler(
+            TypeReference<RecommendedStreamConfiguration> managedType, int nativeType) {
+        return new MarshalerRecommendedStreamConfiguration(managedType, nativeType);
+    }
+
+    @Override
+    public boolean isTypeMappingSupported(TypeReference<RecommendedStreamConfiguration> managedType,
+            int nativeType) {
+        return nativeType ==
+            TYPE_INT32 && managedType.getType().equals(RecommendedStreamConfiguration.class);
+    }
+}
diff --git a/core/java/android/hardware/camera2/params/BlackLevelPattern.java b/core/java/android/hardware/camera2/params/BlackLevelPattern.java
index 6d6c094..283977f 100644
--- a/core/java/android/hardware/camera2/params/BlackLevelPattern.java
+++ b/core/java/android/hardware/camera2/params/BlackLevelPattern.java
@@ -16,13 +16,17 @@
 
 package android.hardware.camera2.params;
 
-import java.util.Arrays;
-
 import static com.android.internal.util.Preconditions.checkNotNull;
 
+import java.util.Arrays;
+
 /**
  * Immutable class to store a 4-element vector of integers corresponding to a 2x2 pattern
  * of color channel offsets used for the black level offsets of each color channel.
+ *
+ * For a camera device with
+ * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME
+ * MONOCHROME} capability, all 4 elements of the pattern will have the same value.
  */
 public final class BlackLevelPattern {
 
@@ -133,6 +137,12 @@
      * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT}).
      * </p>
      *
+     * <p>A {@link
+     * android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME
+     * MONOCHROME} camera only has one channel. As a result, the returned string will contain 4
+     * identical values.
+     * </p>
+     *
      * @return string representation of {@link BlackLevelPattern}
      *
      * @see android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
diff --git a/core/java/android/hardware/camera2/params/RecommendedStreamConfiguration.java b/core/java/android/hardware/camera2/params/RecommendedStreamConfiguration.java
new file mode 100644
index 0000000..5dd0517
--- /dev/null
+++ b/core/java/android/hardware/camera2/params/RecommendedStreamConfiguration.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.params;
+
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.utils.HashCodeHelpers;
+
+/**
+ * Immutable class to store the recommended stream configurations to set up
+ * {@link android.view.Surface Surfaces} for creating a {@link CameraCaptureSession capture session}
+ * with {@link CameraDevice#createCaptureSession}.
+ *
+ * @see CameraCharacteristics#getRecommendedStreamConfigurationMap
+ *
+ * @hide
+ */
+public final class RecommendedStreamConfiguration extends StreamConfiguration{
+
+    /**
+     * Create a new {@link RecommendedStreamConfiguration}.
+     *
+     * @param format image format
+     * @param width image width, in pixels (positive)
+     * @param height image height, in pixels (positive)
+     * @param input true if this is an input configuration, false for output configurations
+     * @param usecaseBitmap Use case bitmap
+     *
+     * @throws IllegalArgumentException
+     *              if width/height were not positive
+     *              or if the format was not user-defined in ImageFormat/PixelFormat
+     *                  (IMPL_DEFINED is ok)
+     *
+     * @hide
+     */
+    public RecommendedStreamConfiguration(
+            final int format, final int width, final int height, final boolean input, final int
+            usecaseBitmap) {
+        super(format, width, height, input);
+        mUsecaseBitmap = usecaseBitmap;
+    }
+
+    /**
+     * Return usecase bitmap.
+     *
+     * @return usecase bitmap
+     */
+    public int getUsecaseBitmap() {
+        return mUsecaseBitmap;
+    }
+
+    /**
+     * Check if this {@link RecommendedStreamConfiguration} is equal to another
+     * {@link RecommendedStreamConfiguration}.
+     *
+     * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof RecommendedStreamConfiguration) {
+            final RecommendedStreamConfiguration other = (RecommendedStreamConfiguration) obj;
+            return mFormat == other.mFormat &&
+                    mWidth == other.mWidth &&
+                    mHeight == other.mHeight &&
+                    mUsecaseBitmap == other.mUsecaseBitmap &&
+                    mInput == other.mInput;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int hashCode() {
+        return HashCodeHelpers.hashCode(mFormat, mWidth, mHeight, mInput ? 1 : 0, mUsecaseBitmap);
+    }
+
+    private final int mUsecaseBitmap;
+}
diff --git a/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java b/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java
new file mode 100644
index 0000000..59e4a33
--- /dev/null
+++ b/core/java/android/hardware/camera2/params/RecommendedStreamConfigurationMap.java
@@ -0,0 +1,509 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.params;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.ImageFormat;
+import android.graphics.PixelFormat;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureRequest;
+import android.util.ArraySet;
+import android.util.Range;
+import android.util.Size;
+import android.view.Surface;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Immutable class to store the recommended stream configurations to set up
+ * {@link android.view.Surface Surfaces} for creating a
+ * {@link android.hardware.camera2.CameraCaptureSession capture session} with
+ * {@link android.hardware.camera2.CameraDevice#createCaptureSession}.
+ *
+ * <p>The recommended list does not replace or deprecate the exhaustive complete list found in
+ * {@link StreamConfigurationMap}. It is a suggestion about available power and performance
+ * efficient stream configurations for a specific use case. Per definition it is only a subset
+ * of {@link StreamConfigurationMap} and can be considered by developers for optimization
+ * purposes.</p>
+ *
+ * <p>This also duplicates the minimum frame durations and stall durations from the
+ * {@link StreamConfigurationMap} for each format/size combination that can be used to calculate
+ * effective frame rate when submitting multiple captures.
+ * </p>
+ *
+ * <p>An instance of this object is available by invoking
+ * {@link CameraCharacteristics#getRecommendedStreamConfigurationMap} and passing a respective
+ * usecase id. For more information about supported use case constants see
+ * {@link #USECASE_PREVIEW}.</p>
+ *
+ * <pre><code>{@code
+ * CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
+ * RecommendedStreamConfigurationMap configs = characteristics.getRecommendedStreamConfigurationMap(
+ *         RecommendedStreamConfigurationMap.USECASE_PREVIEW);
+ * }</code></pre>
+ *
+ * @see CameraCharacteristics#getRecommendedStreamConfigurationMap
+ * @see CameraDevice#createCaptureSession
+ */
+public final class RecommendedStreamConfigurationMap {
+
+    private static final String TAG = "RecommendedStreamConfigurationMap";
+    private int mUsecase;
+    private boolean mSupportsPrivate;
+    private StreamConfigurationMap mRecommendedMap;
+
+    /** @hide */
+    public static final int MAX_USECASE_COUNT = 32;
+
+    /**
+     * The recommended stream configuration map for use case preview must contain a subset of
+     * efficient, non-stalling configurations that must include both
+     * {@link android.graphics.ImageFormat#PRIVATE} and
+     * {@link android.graphics.ImageFormat#YUV_420_888} output formats. Even if available for the
+     * camera device, high speed or input configurations will be absent.
+     */
+    public static final int USECASE_PREVIEW = 0x0;
+
+    /**
+     * The recommended stream configuration map for recording must contain a subset of efficient
+     * video configurations that include {@link android.graphics.ImageFormat#PRIVATE}
+     * output format for at least all supported {@link android.media.CamcorderProfile profiles}.
+     * High speed configurations if supported will be available as well. Even if available for the
+     * camera device, input configurations will be absent.
+     */
+    public static final int USECASE_RECORD = 0x1;
+
+    /**
+     * The recommended stream configuration map for use case video snapshot must only contain a
+     * subset of efficient liveshot configurations that include
+     * {@link android.graphics.ImageFormat#JPEG} output format. The sizes will match at least
+     * the maximum resolution of usecase record and will not cause any preview glitches. Even
+     * if available for the camera device, high speed or input configurations will be absent.
+     */
+    public static final int USECASE_VIDEO_SNAPSHOT = 0x2;
+
+    /**
+     * The recommended stream configuration map for use case snapshot must contain a subset of
+     * efficient still capture configurations that must include
+     * {@link android.graphics.ImageFormat#JPEG} output format and at least one configuration with
+     * size approximately equal to the sensor pixel array size
+     * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
+     * Even if available for the camera device, high speed or input configurations will be absent.
+     */
+    public static final int USECASE_SNAPSHOT = 0x3;
+
+    /**
+     * In case the device supports
+     * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING} and/or
+     * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING},
+     * the recommended stream configuration map for use case ZSL must contain a subset of efficient
+     * configurations that include the suggested input and output format mappings. Even if
+     * available for the camera device, high speed configurations will be absent.
+     */
+    public static final int USECASE_ZSL = 0x4;
+
+    /**
+     * In case the device supports
+     * {@link android.hardware.camera2.CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW}, the
+     * recommended stream configuration map for use case RAW must contain a subset of efficient
+     * configurations that include the {@link android.graphics.ImageFormat#RAW_SENSOR} and other
+     * RAW output formats. Even if available for the camera device, high speed and input
+     * configurations will be absent.
+     */
+    public static final int USECASE_RAW = 0x5;
+
+    /**
+     * Device specific use cases.
+     * @hide
+     */
+    public static final int USECASE_VENDOR_START = 0x18;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"USECASE_"}, value =
+        {USECASE_PREVIEW,
+        USECASE_RECORD,
+        USECASE_VIDEO_SNAPSHOT,
+        USECASE_SNAPSHOT,
+        USECASE_ZSL,
+        USECASE_RAW })
+     public @interface RecommendedUsecase {};
+
+    /**
+     * Create a new {@link RecommendedStreamConfigurationMap}.
+     *
+     * @param recommendedMap stream configuration map that contains for the specific use case
+     * @param usecase Recommended use case
+     * @param supportsPrivate Flag indicating private format support.
+     *
+     * @hide
+     */
+    public RecommendedStreamConfigurationMap(StreamConfigurationMap recommendedMap, int usecase,
+            boolean supportsPrivate) {
+        mRecommendedMap = recommendedMap;
+        mUsecase = usecase;
+        mSupportsPrivate = supportsPrivate;
+    }
+
+    /**
+     * Get the use case value for the recommended stream configurations.
+     *
+     * @return Use case id.
+     */
+    public int getRecommendedUseCase() {
+        return mUsecase;
+    }
+
+    private Set<Integer> getUnmodifiableIntegerSet(int[] intArray) {
+        if ((intArray != null) && (intArray.length > 0)) {
+            ArraySet<Integer> integerSet = new ArraySet<Integer>();
+            integerSet.ensureCapacity(intArray.length);
+            for (int intEntry : intArray) {
+                integerSet.add(intEntry);
+            }
+
+            return Collections.unmodifiableSet(integerSet);
+        }
+
+        return null;
+    }
+
+    /**
+     * Get the image {@code format} output formats in this stream configuration.
+     *
+     * <p>
+     * For more information refer to {@link StreamConfigurationMap#getOutputFormats}.
+     * </p>
+     *
+     * @return a non-modifiable set of Integer formats
+     */
+    public @NonNull Set<Integer> getOutputFormats() {
+        return getUnmodifiableIntegerSet(mRecommendedMap.getOutputFormats());
+    }
+
+    /**
+     * Get the image {@code format} output formats for a reprocessing input format.
+     *
+     * <p>
+     * For more information refer to {@link StreamConfigurationMap#getValidOutputFormatsForInput}.
+     * </p>
+     *
+     * @return a non-modifiable set of Integer formats
+     */
+    public @Nullable Set<Integer> getValidOutputFormatsForInput(int inputFormat) {
+        return getUnmodifiableIntegerSet(mRecommendedMap.getValidOutputFormatsForInput(
+                    inputFormat));
+    }
+
+    /**
+     * Get the image {@code format} input formats in this stream configuration.
+     *
+     * <p>All image formats returned by this function will be defined in either {@link ImageFormat}
+     * or in {@link PixelFormat} (and there is no possibility of collision).</p>
+     *
+     * @return a non-modifiable set of Integer formats
+     */
+    public @Nullable Set<Integer> getInputFormats() {
+        return getUnmodifiableIntegerSet(mRecommendedMap.getInputFormats());
+    }
+
+    private Set<Size> getUnmodifiableSizeSet(Size[] sizeArray) {
+        if ((sizeArray != null) && (sizeArray.length > 0)) {
+            ArraySet<Size> sizeSet = new ArraySet<Size>();
+            sizeSet.addAll(Arrays.asList(sizeArray));
+            return Collections.unmodifiableSet(sizeSet);
+        }
+
+        return  null;
+    }
+
+    /**
+     * Get the supported input sizes for this input format.
+     *
+     * <p>The format must have come from {@link #getInputFormats}; otherwise
+     * {@code null} is returned.</p>
+     *
+     * @param format a format from {@link #getInputFormats}
+     * @return a non-modifiable set of sizes, or {@code null} if the format was not available.
+     */
+    public @Nullable Set<Size> getInputSizes(int format) {
+        return getUnmodifiableSizeSet(mRecommendedMap.getInputSizes(format));
+    }
+
+    /**
+     * Determine whether or not output surfaces with a particular user-defined format can be passed
+     * {@link CameraDevice#createCaptureSession createCaptureSession}.
+     *
+     * <p>
+     * For further information refer to {@link StreamConfigurationMap#isOutputSupportedFor}.
+     * </p>
+     *
+     *
+     * @param format an image format from either {@link ImageFormat} or {@link PixelFormat}
+     * @return
+     *          {@code true} if using a {@code surface} with this {@code format} will be
+     *          supported with {@link CameraDevice#createCaptureSession}
+     *
+     * @throws IllegalArgumentException
+     *          if the image format was not a defined named constant
+     *          from either {@link ImageFormat} or {@link PixelFormat}
+     */
+    public boolean isOutputSupportedFor(int format) {
+        return mRecommendedMap.isOutputSupportedFor(format);
+    }
+
+    /**
+     * Get a list of sizes compatible with the requested image {@code format}.
+     *
+     * <p>
+     * For more information refer to {@link StreamConfigurationMap#getOutputSizes}.
+     * </p>
+     *
+     *
+     * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+     * @return  a non-modifiable set of supported sizes,
+     *          or {@code null} if the {@code format} is not a supported output
+     */
+    public @Nullable Set<Size> getOutputSizes(int format) {
+        return getUnmodifiableSizeSet(mRecommendedMap.getOutputSizes(format));
+    }
+
+    /**
+     * Get a list of supported high speed video recording sizes.
+     * <p>
+     * For more information refer to {@link StreamConfigurationMap#getHighSpeedVideoSizes}.
+     * </p>
+     *
+     * @return a non-modifiable set of supported high speed video recording sizes
+     */
+    public @Nullable Set<Size> getHighSpeedVideoSizes() {
+        return getUnmodifiableSizeSet(mRecommendedMap.getHighSpeedVideoSizes());
+    }
+
+    private Set<Range<Integer>> getUnmodifiableRangeSet(Range<Integer>[] rangeArray) {
+        if ((rangeArray != null) && (rangeArray.length > 0)) {
+            ArraySet<Range<Integer>> rangeSet = new ArraySet<Range<Integer>>();
+            rangeSet.addAll(Arrays.asList(rangeArray));
+            return Collections.unmodifiableSet(rangeSet);
+        }
+
+        return null;
+    }
+
+    /**
+     * Get the frame per second ranges (fpsMin, fpsMax) for input high speed video size.
+     *
+     * <p>
+     * For further information refer to
+     * {@link StreamConfigurationMap#getHighSpeedVideoFpsRangesFor}.
+     * </p>
+     * @param size one of the sizes returned by {@link #getHighSpeedVideoSizes()}
+     * @return a non-modifiable set of supported high speed video recording FPS ranges The upper
+     *         bound of returned ranges is guaranteed to be greater than or equal to 120.
+     * @throws IllegalArgumentException if input size does not exist in the return value of
+     *             getHighSpeedVideoSizes
+     */
+    public @Nullable Set<Range<Integer>> getHighSpeedVideoFpsRangesFor(Size size) {
+        return getUnmodifiableRangeSet(mRecommendedMap.getHighSpeedVideoFpsRangesFor(size));
+    }
+
+    /**
+     * Get a list of supported high speed video recording FPS ranges.
+     * <p>
+     * For further information refer to {@link StreamConfigurationMap#getHighSpeedVideoFpsRanges}.
+     * </p>
+     * @return a non-modifiable set of supported high speed video recording FPS ranges The upper
+     *         bound of returned ranges is guaranteed to be larger or equal to 120.
+     */
+    public @Nullable Set<Range<Integer>> getHighSpeedVideoFpsRanges() {
+        return getUnmodifiableRangeSet(mRecommendedMap.getHighSpeedVideoFpsRanges());
+    }
+
+    /**
+     * Get the supported video sizes for an input high speed FPS range.
+     *
+     * <p>
+     * For further information refer to {@link StreamConfigurationMap#getHighSpeedVideoSizesFor}.
+     * </p>
+     *
+     * @param fpsRange one of the FPS range returned by {@link #getHighSpeedVideoFpsRanges()}
+     * @return A non-modifiable set of video sizes to create high speed capture sessions for high
+     *         speed streaming use cases.
+     *
+     * @throws IllegalArgumentException if input FPS range does not exist in the return value of
+     *         getHighSpeedVideoFpsRanges
+     */
+    public @Nullable Set<Size> getHighSpeedVideoSizesFor(Range<Integer> fpsRange) {
+        return getUnmodifiableSizeSet(mRecommendedMap.getHighSpeedVideoSizesFor(fpsRange));
+    }
+
+    /**
+     * Get a list of supported high resolution sizes, which cannot operate at full BURST_CAPTURE
+     * rate.
+     *
+     * <p>
+     * For further information refer to {@link StreamConfigurationMap#getHighResolutionOutputSizes}.
+     * </p>
+     *
+     * @return a non-modifiable set of supported slower high-resolution sizes, or {@code null} if
+     *         the BURST_CAPTURE capability is not supported
+     */
+    public @Nullable Set<Size> getHighResolutionOutputSizes(int format) {
+        return getUnmodifiableSizeSet(mRecommendedMap.getHighResolutionOutputSizes(format));
+    }
+
+    /**
+     * Get the minimum
+     * {@link android.hardware.camera2.CaptureRequest#SENSOR_FRAME_DURATION frame duration}
+     * for the format/size combination (in nanoseconds).
+     *
+     * <p>
+     * For further information refer to {@link StreamConfigurationMap#getOutputMinFrameDuration}.
+     * </p>
+     *
+     * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+     * @param size an output-compatible size
+     * @return a minimum frame duration {@code >} 0 in nanoseconds, or
+     *          0 if the minimum frame duration is not available.
+     *
+     * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
+     * @throws NullPointerException if {@code size} was {@code null}
+     *
+     */
+    public long getOutputMinFrameDuration(int format, Size size) {
+        return mRecommendedMap.getOutputMinFrameDuration(format, size);
+    }
+
+    /**
+     * Get the stall duration for the format/size combination (in nanoseconds).
+     *
+     * <p>
+     * For further information refer to {@link StreamConfigurationMap#getOutputStallDuration}.
+     * </p>
+     *
+     * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+     * @param size an output-compatible size
+     * @return a stall duration {@code >=} 0 in nanoseconds
+     *
+     * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
+     * @throws NullPointerException if {@code size} was {@code null}
+     */
+    public long getOutputStallDuration(int format, Size size) {
+        return mRecommendedMap.getOutputStallDuration(format, size);
+    }
+
+    /**
+     * Get a list of sizes compatible with {@code klass} to use as an output.
+     *
+     * <p>For further information refer to {@link StreamConfigurationMap#getOutputSizes(Class)}.
+     * </p>
+     *
+     * @param klass
+     *          a non-{@code null} {@link Class} object reference
+     * @return
+     *          a non-modifiable set of supported sizes for {@link ImageFormat#PRIVATE} format,
+     *          or {@code null} if the {@code klass} is not a supported output.
+     *
+     *
+     * @throws NullPointerException if {@code klass} was {@code null}
+     *
+     */
+    public <T> @Nullable Set<Size> getOutputSizes(Class<T> klass) {
+        if (mSupportsPrivate) {
+            return getUnmodifiableSizeSet(mRecommendedMap.getOutputSizes(klass));
+        }
+
+        return null;
+    }
+
+    /**
+     * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
+     * for the class/size combination (in nanoseconds).
+     *
+     * <p>For more information refer to
+     * {@link StreamConfigurationMap#getOutputMinFrameDuration(Class, Size)}.</p>
+     *
+     * @param klass
+     *          a class which  has a non-empty array returned by {@link #getOutputSizes(Class)}
+     * @param size an output-compatible size
+     * @return a minimum frame duration {@code >} 0 in nanoseconds, or
+     *          0 if the minimum frame duration is not available.
+     *
+     * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
+     * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
+     *
+     */
+    public <T> long getOutputMinFrameDuration(final Class<T> klass, final Size size) {
+        if (mSupportsPrivate) {
+            return mRecommendedMap.getOutputMinFrameDuration(klass, size);
+        }
+
+        return 0;
+    }
+
+    /**
+     * Get the stall duration for the class/size combination (in nanoseconds).
+     *
+     * <p>For more information refer to
+     * {@link StreamConfigurationMap#getOutputStallDuration(Class, Size)}.
+     *
+     * @param klass
+     *          a class which has a non-empty array returned by {@link #getOutputSizes(Class)}.
+     * @param size an output-compatible size
+     * @return a minimum frame duration {@code >=} 0 in nanoseconds, or 0 if the stall duration is
+     *         not available.
+     *
+     * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
+     * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
+     *
+     */
+    public <T> long getOutputStallDuration(final Class<T> klass, final Size size) {
+        if (mSupportsPrivate) {
+            return mRecommendedMap.getOutputStallDuration(klass, size);
+        }
+
+        return 0;
+    }
+
+    /**
+     * Determine whether or not the {@code surface} in its current state is suitable to be included
+     * in a {@link CameraDevice#createCaptureSession capture session} as an output.
+     *
+     * <p>For more information refer to {@link StreamConfigurationMap#isOutputSupportedFor}.
+     * </p>
+     *
+     * @param surface a non-{@code null} {@link Surface} object reference
+     * @return {@code true} if this is supported, {@code false} otherwise
+     *
+     * @throws NullPointerException if {@code surface} was {@code null}
+     * @throws IllegalArgumentException if the Surface endpoint is no longer valid
+     *
+     */
+    public boolean isOutputSupportedFor(Surface surface) {
+        return mRecommendedMap.isOutputSupportedFor(surface);
+    }
+
+}
diff --git a/core/java/android/hardware/camera2/params/StreamConfiguration.java b/core/java/android/hardware/camera2/params/StreamConfiguration.java
index a6fc10f..eb92291 100644
--- a/core/java/android/hardware/camera2/params/StreamConfiguration.java
+++ b/core/java/android/hardware/camera2/params/StreamConfiguration.java
@@ -40,7 +40,7 @@
  *
  * @hide
  */
-public final class StreamConfiguration {
+public class StreamConfiguration {
 
     /**
      * Create a new {@link StreamConfiguration}.
@@ -164,8 +164,8 @@
         return HashCodeHelpers.hashCode(mFormat, mWidth, mHeight, mInput ? 1 : 0);
     }
 
-    private final int mFormat;
-    private final int mWidth;
-    private final int mHeight;
-    private final boolean mInput;
+    protected int mFormat;
+    protected int mWidth;
+    protected int mHeight;
+    protected boolean mInput;
 }
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index 414c463..dd052a8 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -98,6 +98,43 @@
             HighSpeedVideoConfiguration[] highSpeedVideoConfigurations,
             ReprocessFormatsMap inputOutputFormatsMap,
             boolean listHighResolution) {
+        this(configurations, minFrameDurations, stallDurations,
+                    depthConfigurations, depthMinFrameDurations, depthStallDurations,
+                    highSpeedVideoConfigurations, inputOutputFormatsMap, listHighResolution,
+                    /*enforceImplementationDefined*/ true);
+    }
+
+    /**
+     * Create a new {@link StreamConfigurationMap}.
+     *
+     * <p>The array parameters ownership is passed to this object after creation; do not
+     * write to them after this constructor is invoked.</p>
+     *
+     * @param configurations a non-{@code null} array of {@link StreamConfiguration}
+     * @param minFrameDurations a non-{@code null} array of {@link StreamConfigurationDuration}
+     * @param stallDurations a non-{@code null} array of {@link StreamConfigurationDuration}
+     * @param highSpeedVideoConfigurations an array of {@link HighSpeedVideoConfiguration}, null if
+     *        camera device does not support high speed video recording
+     * @param listHighResolution a flag indicating whether the device supports BURST_CAPTURE
+     *        and thus needs a separate list of slow high-resolution output sizes
+     * @param enforceImplementationDefined a flag indicating whether
+     *        IMPLEMENTATION_DEFINED format configuration must be present
+     * @throws NullPointerException if any of the arguments except highSpeedVideoConfigurations
+     *         were {@code null} or any subelements were {@code null}
+     *
+     * @hide
+     */
+    public StreamConfigurationMap(
+            StreamConfiguration[] configurations,
+            StreamConfigurationDuration[] minFrameDurations,
+            StreamConfigurationDuration[] stallDurations,
+            StreamConfiguration[] depthConfigurations,
+            StreamConfigurationDuration[] depthMinFrameDurations,
+            StreamConfigurationDuration[] depthStallDurations,
+            HighSpeedVideoConfiguration[] highSpeedVideoConfigurations,
+            ReprocessFormatsMap inputOutputFormatsMap,
+            boolean listHighResolution,
+            boolean enforceImplementationDefined) {
 
         if (configurations == null) {
             // If no color configurations exist, ensure depth ones do
@@ -169,7 +206,7 @@
                     mDepthOutputFormats.get(config.getFormat()) + 1);
         }
 
-        if (configurations != null &&
+        if (configurations != null && enforceImplementationDefined &&
                 mOutputFormats.indexOfKey(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) < 0) {
             throw new AssertionError(
                     "At least one stream configuration for IMPLEMENTATION_DEFINED must exist");
@@ -208,7 +245,7 @@
      * @see ImageFormat
      * @see PixelFormat
      */
-    public final int[] getOutputFormats() {
+    public int[] getOutputFormats() {
         return getPublicFormats(/*output*/true);
     }
 
@@ -232,7 +269,7 @@
      * @see ImageFormat
      * @see PixelFormat
      */
-    public final int[] getValidOutputFormatsForInput(int inputFormat) {
+    public int[] getValidOutputFormatsForInput(int inputFormat) {
         if (mInputOutputFormatsMap == null) {
             return new int[0];
         }
@@ -250,7 +287,7 @@
      * @see ImageFormat
      * @see PixelFormat
      */
-    public final int[] getInputFormats() {
+    public int[] getInputFormats() {
         return getPublicFormats(/*output*/false);
     }
 
@@ -426,6 +463,34 @@
     }
 
     /**
+     * Determine whether or not the particular stream configuration is suitable to be included
+     * in a {@link CameraDevice#createCaptureSession capture session} as an output.
+     *
+     * @param size stream configuration size
+     * @param format stream configuration format
+     * @return {@code true} if this is supported, {@code false} otherwise
+     *
+     * @see CameraDevice#createCaptureSession
+     * @see #isOutputSupportedFor(Class)
+     * @hide
+     */
+    public boolean isOutputSupportedFor(Size size, int format) {
+        int internalFormat = imageFormatToInternal(format);
+        int dataspace = imageFormatToDataspace(format);
+
+        StreamConfiguration[] configs =
+            dataspace != HAL_DATASPACE_DEPTH ? mConfigurations : mDepthConfigurations;
+        for (StreamConfiguration config : configs) {
+            if ((config.getFormat() == internalFormat) && config.isOutput() &&
+                    config.getSize().equals(size)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * Get a list of sizes compatible with {@code klass} to use as an output.
      *
      * <p>Some of the supported classes may support additional formats beyond
@@ -1062,8 +1127,9 @@
      * @see ImageFormat
      * @see PixelFormat
      * @see #checkArgumentFormat
+     * @hide
      */
-    static int imageFormatToPublic(int format) {
+    public static int imageFormatToPublic(int format) {
         switch (format) {
             case HAL_PIXEL_FORMAT_BLOB:
                 return ImageFormat.JPEG;
@@ -1105,8 +1171,9 @@
      * @see ImageFormat
      * @see PixelFormat
      * @see #checkArgumentFormat
+     * @hide
      */
-    static int depthFormatToPublic(int format) {
+    public static int depthFormatToPublic(int format) {
         switch (format) {
             case HAL_PIXEL_FORMAT_BLOB:
                 return ImageFormat.DEPTH_POINT_CLOUD;
diff --git a/core/java/android/hardware/camera2/params/TonemapCurve.java b/core/java/android/hardware/camera2/params/TonemapCurve.java
index 71e68a5..90e6355 100644
--- a/core/java/android/hardware/camera2/params/TonemapCurve.java
+++ b/core/java/android/hardware/camera2/params/TonemapCurve.java
@@ -34,6 +34,10 @@
  * use as the tonemapping/contrast/gamma curve when {@link CaptureRequest#TONEMAP_MODE} is
  * set to {@link CameraMetadata#TONEMAP_MODE_CONTRAST_CURVE}.</p>
  *
+ * <p>For a camera device with
+ * {@link android.hardware.camera2.CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME
+ * MONOCHROME} capability, all 3 channels will contain the same set of control points.
+ *
  * <p>The total number of points {@code (Pin, Pout)} for each color channel can be no more than
  * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS}.</p>
  *
diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java
new file mode 100644
index 0000000..0a76c2b
--- /dev/null
+++ b/core/java/android/hardware/display/ColorDisplayManager.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.display;
+
+import android.content.Context;
+
+import com.android.internal.R;
+
+/**
+ * Manages the display's color transforms and modes.
+ * @hide
+ */
+public final class ColorDisplayManager {
+
+    /**
+     * Returns {@code true} if Night Display is supported by the device.
+     */
+    public static boolean isNightDisplayAvailable(Context context) {
+        return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
+    }
+}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 01ef58e..82e765d 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -263,6 +263,7 @@
      * @see KeyguardManager#isDeviceLocked()
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#shouldShowWithInsecureKeyguard
     // TODO: Update name and documentation and un-hide the flag. Don't change the value before that.
     public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
 
@@ -295,6 +296,7 @@
      * @see #createVirtualDisplay
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_DESTROY
     public static final int VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 8;
 
     /**
@@ -304,6 +306,7 @@
      * @see #createVirtualDisplay
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors
     public static final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 9;
 
     /** @hide */
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 7840fd0..9db1f92 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -235,7 +235,8 @@
         // If true, enables automatic brightness control.
         public boolean useAutoBrightness;
 
-        // If true, scales the brightness to half of desired.
+        // If true, scales the brightness to a fraction of desired (as defined by
+        // screenLowPowerBrightnessFactor).
         public boolean lowPowerMode;
 
         // The factor to adjust the screen brightness in low power mode in the range
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/core/java/android/hardware/iris/IIrisService.aidl
similarity index 74%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to core/java/android/hardware/iris/IIrisService.aidl
index ede8695..8cf3c13 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/core/java/android/hardware/iris/IIrisService.aidl
@@ -13,9 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package android.hardware.iris;
 
-package com.android.internal.telephony;
-
-interface IRcs {
-    void deleteThread(int threadId);
+/**
+ * Communication channel from client to the iris service. These methods are all require the
+ * MANAGE_BIOMETRIC signature permission.
+ * @hide
+ */
+interface IIrisService {
 }
\ No newline at end of file
diff --git a/core/java/android/hardware/iris/IrisManager.java b/core/java/android/hardware/iris/IrisManager.java
new file mode 100644
index 0000000..281ac47
--- /dev/null
+++ b/core/java/android/hardware/iris/IrisManager.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.hardware.iris;
+
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * A class that coordinates access to the iris authentication hardware.
+ * @hide
+ */
+@SystemService(Context.IRIS_SERVICE)
+public class IrisManager {
+
+    /**
+     * @hide
+     */
+    public IrisManager(Context context, IIrisService service) {
+    }
+}
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 9f11246..a83a33e 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -19,7 +19,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.app.PendingIntent;
-import android.content.Intent;
 import android.os.RemoteException;
 
 import com.android.internal.util.Preconditions;
@@ -49,13 +48,25 @@
      */
     private final ContextHubInfo mAttachedHub;
 
-    private final CloseGuard mCloseGuard = CloseGuard.get();
+    private final CloseGuard mCloseGuard;
 
     private final AtomicBoolean mIsClosed = new AtomicBoolean(false);
 
-    /* package */ ContextHubClient(ContextHubInfo hubInfo) {
+    /*
+     * True if this is a persistent client (i.e. does not have to close the connection when the
+     * resource is freed from the system).
+     */
+    private final boolean mPersistent;
+
+    /* package */ ContextHubClient(ContextHubInfo hubInfo, boolean persistent) {
         mAttachedHub = hubInfo;
-        mCloseGuard.open("close");
+        mPersistent = persistent;
+        if (mPersistent) {
+            mCloseGuard = null;
+        } else {
+            mCloseGuard = CloseGuard.get();
+            mCloseGuard.open("close");
+        }
     }
 
     /**
@@ -88,11 +99,18 @@
      * Closes the connection for this client and the Context Hub Service.
      *
      * When this function is invoked, the messaging associated with this client is invalidated.
-     * All futures messages targeted for this client are dropped at the service.
+     * All futures messages targeted for this client are dropped at the service, and the
+     * ContextHubClient is unregistered from the service.
+     *
+     * If this object has a PendingIntent, i.e. the object was generated via
+     * {@link ContextHubManager.createClient(PendingIntent, ContextHubInfo, long)}, then the
+     * Intent events corresponding to the PendingIntent will no longer be triggered.
      */
     public void close() {
         if (!mIsClosed.getAndSet(true)) {
-            mCloseGuard.close();
+            if (mCloseGuard != null) {
+                mCloseGuard.close();
+            }
             try {
                 mClientProxy.close();
             } catch (RemoteException e) {
@@ -102,71 +120,6 @@
     }
 
     /**
-     * Registers to receive persistent intents for a given nanoapp.
-     *
-     * This method should be used if the caller wants to receive notifications even after the
-     * process exits. The client must have an open connection with the Context Hub Service (i.e. it
-     * cannot have been closed through the {@link #close()} method). Only one PendingIntent can be
-     * registered at a time for a single ContextHubClient. If registered successfully, intents will
-     * be delivered regarding events for the specified nanoapp from the attached Context Hub. Any
-     * unicast messages for this client will also be delivered. The intent will have an extra
-     * {@link ContextHubManager.EXTRA_CONTEXT_HUB_INFO} of type {@link ContextHubInfo}, which
-     * describes the Context Hub the intent event was for. The intent will also have an extra
-     * {@link ContextHubManager.EXTRA_EVENT_TYPE} of type {@link ContextHubManager.Event}, which
-     * will contain the type of the event. See {@link ContextHubManager.Event} for description of
-     * each event type, along with event-specific extra fields. A client can use
-     * {@link ContextHubIntentEvent.fromIntent(Intent)} to parse the Intent generated by the event.
-     *
-     * When the intent is received, this client can be recreated through
-     * {@link ContextHubManager.createClient(PendingIntent, ContextHubInfo,
-     * ContextHubClientCallback, Exectutor)}. When recreated, the client can be treated as the
-     * same endpoint entity from a nanoapp's perspective, and can be continued to be used to send
-     * messages even if the original process has exited.
-     *
-     * Intents will be delivered until it is unregistered through
-     * {@link #unregisterIntent(PendingIntent)}. Note that the registration of this client will
-     * continued to be maintained at the Context Hub Service until
-     * {@link #unregisterIntent(PendingIntent)} is called for registered intents.
-     *
-     * @param pendingIntent the PendingIntent to register for this client
-     * @param nanoAppId     the unique ID of the nanoapp to receive events for
-     * @return true on success, false otherwise
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
-    public boolean registerIntent(@NonNull PendingIntent pendingIntent, long nanoAppId) {
-        Preconditions.checkNotNull(pendingIntent, "PendingIntent cannot be null");
-
-        try {
-            return mClientProxy.registerIntent(pendingIntent, nanoAppId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Unregisters an intent previously registered via {@link #registerIntent(PendingIntent, long)}.
-     * If this intent has not been registered for this client, this method returns false.
-     *
-     * @param pendingIntent the PendingIntent to unregister
-     *
-     * @return true on success, false otherwise
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
-    public boolean unregisterIntent(@NonNull PendingIntent pendingIntent) {
-        Preconditions.checkNotNull(pendingIntent, "PendingIntent cannot be null");
-
-        try {
-            return mClientProxy.unregisterIntent(pendingIntent);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * Sends a message to a nanoapp through the Context Hub Service.
      *
      * This function returns RESULT_SUCCESS if the message has reached the HAL, but
@@ -199,7 +152,9 @@
             if (mCloseGuard != null) {
                 mCloseGuard.warnIfOpen();
             }
-            close();
+            if (!mPersistent) {
+                close();
+            }
         } finally {
             super.finalize();
         }
diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java
index 36123e3..51daa92 100644
--- a/core/java/android/hardware/location/ContextHubInfo.java
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -15,6 +15,7 @@
  */
 package android.hardware.location;
 
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.hardware.contexthub.V1_0.ContextHub;
 import android.os.Parcel;
@@ -267,6 +268,34 @@
         return retVal;
     }
 
+    @Override
+    public boolean equals(@Nullable Object object) {
+        if (object == this) {
+            return true;
+        }
+
+        boolean isEqual = false;
+        if (object instanceof ContextHubInfo) {
+            ContextHubInfo other = (ContextHubInfo) object;
+            isEqual = (other.getId() == mId)
+                    && other.getName().equals(mName)
+                    && other.getVendor().equals(mVendor)
+                    && other.getToolchain().equals(mToolchain)
+                    && (other.getToolchainVersion() == mToolchainVersion)
+                    && (other.getStaticSwVersion() == getStaticSwVersion())
+                    && (other.getChrePlatformId() == mChrePlatformId)
+                    && (other.getPeakMips() == mPeakMips)
+                    && (other.getStoppedPowerDrawMw() == mStoppedPowerDrawMw)
+                    && (other.getSleepPowerDrawMw() == mSleepPowerDrawMw)
+                    && (other.getPeakPowerDrawMw() == mPeakPowerDrawMw)
+                    && (other.getMaxPacketLengthBytes() == mMaxPacketLengthBytes)
+                    && Arrays.equals(other.getSupportedSensors(), mSupportedSensors)
+                    && Arrays.equals(other.getMemoryRegions(), mMemoryRegions);
+        }
+
+        return isEqual;
+    }
+
     private ContextHubInfo(Parcel in) {
         mId = in.readInt();
         mName = in.readString();
diff --git a/core/java/android/hardware/location/ContextHubIntentEvent.java b/core/java/android/hardware/location/ContextHubIntentEvent.java
index 96e7496..539c494 100644
--- a/core/java/android/hardware/location/ContextHubIntentEvent.java
+++ b/core/java/android/hardware/location/ContextHubIntentEvent.java
@@ -16,6 +16,7 @@
 package android.hardware.location;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.content.Intent;
 
@@ -23,8 +24,9 @@
 
 /**
  * A helper class to retrieve information about a Intent event received for a PendingIntent
- * registered through {@link ContextHubClient.registerIntent(PendingIntent, long)}. This object
- * can only be created through the factory method {@link ContextHubIntentEvent.fromIntent(Intent)}.
+ * registered with {@link ContextHubManager.createClient(ContextHubInfo, PendingIntent, long)}.
+ * This object can only be created through the factory method
+ * {@link ContextHubIntentEvent.fromIntent(Intent)}.
  *
  * @hide
  */
@@ -76,7 +78,7 @@
 
     /**
      * Creates a ContextHubIntentEvent object from an Intent received through a PendingIntent
-     * registered through {@link ContextHubClient.registerIntent(PendingIntent, long)}.
+     * registered with {@link ContextHubManager.createClient(ContextHubInfo, PendingIntent, long)}.
      *
      * @param intent the Intent object from an Intent event
      * @return the ContextHubIntentEvent object describing the event
@@ -206,6 +208,37 @@
         return out + "]";
     }
 
+    @Override
+    public boolean equals(@Nullable Object object) {
+        if (object == this) {
+            return true;
+        }
+
+        boolean isEqual = false;
+        if (object instanceof ContextHubIntentEvent) {
+            ContextHubIntentEvent other = (ContextHubIntentEvent) object;
+            if (other.getEventType() == mEventType
+                    && other.getContextHubInfo().equals(mContextHubInfo)) {
+                isEqual = true;
+                try {
+                    if (mEventType != ContextHubManager.EVENT_HUB_RESET) {
+                        isEqual &= (other.getNanoAppId() == mNanoAppId);
+                    }
+                    if (mEventType == ContextHubManager.EVENT_NANOAPP_ABORTED) {
+                        isEqual &= (other.getNanoAppAbortCode() == mNanoAppAbortCode);
+                    }
+                    if (mEventType == ContextHubManager.EVENT_NANOAPP_MESSAGE) {
+                        isEqual &= other.getNanoAppMessage().equals(mNanoAppMessage);
+                    }
+                } catch (UnsupportedOperationException e) {
+                    isEqual = false;
+                }
+            }
+        }
+
+        return isEqual;
+    }
+
     private static void hasExtraOrThrow(Intent intent, String extra) {
         if (!intent.hasExtra(extra)) {
             throw new IllegalArgumentException("Intent did not have extra: " + extra);
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 9acefa5..843db66 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -25,6 +25,7 @@
 import android.annotation.SystemService;
 import android.app.PendingIntent;
 import android.content.Context;
+import android.content.Intent;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.Looper;
@@ -757,7 +758,7 @@
         Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
         Preconditions.checkNotNull(executor, "Executor cannot be null");
 
-        ContextHubClient client = new ContextHubClient(hubInfo);
+        ContextHubClient client = new ContextHubClient(hubInfo, false /* persistent */);
         IContextHubClientCallback clientInterface = createClientCallback(
                 client, callback, executor);
 
@@ -793,43 +794,55 @@
     }
 
     /**
-     * Creates a ContextHubClient based on an Intent received by the Context Hub Service.
+     * Creates a ContextHubClient that will receive notifications based on Intent events.
      *
-     * This method is intended to be used after receiving an Intent received as a result of
-     * {@link ContextHubClient.registerIntent(PendingIntent, long)}, and must have been created
-     * through {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)} or
-     * equivalent at an earlier time.
+     * This method should be used instead of {@link #createClient(ContextHubInfo,
+     * ContextHubClientCallback)} and the equivalent API if the caller wants to preserve the
+     * messaging endpoint of a ContextHubClient, even after a process exits. If the PendingIntent
+     * with the provided nanoapp has already been registered at the service previously, then the
+     * same ContextHubClient will be regenerated without creating a new client connection at the
+     * service. Note that the PendingIntent, nanoapp, and Context Hub must all match in identifying
+     * a previously registered ContextHubClient. If a client is regenerated, it can be treated as
+     * the same endpoint entity from a nanoapp's perspective, and can be continued to be
+     * used to send messages even if the original process has exited.
      *
-     * @param pendingIntent the PendingIntent that has been registered with a client
+     * If registered successfully, intents will be delivered regarding events or messages from the
+     * specified nanoapp from the attached Context Hub. The intent will have an extra
+     * {@link ContextHubManager.EXTRA_CONTEXT_HUB_INFO} of type {@link ContextHubInfo}, which
+     * describes the Context Hub the intent event was for. The intent will also have an extra
+     * {@link ContextHubManager.EXTRA_EVENT_TYPE} of type {@link ContextHubManager.Event}, which
+     * will contain the type of the event. See {@link ContextHubManager.Event} for description of
+     * each event type, along with event-specific extra fields. The client can also use
+     * {@link ContextHubIntentEvent.fromIntent(Intent)} to parse the Intent generated by the event.
+     *
+     * Intent events will be delivered until it is unregistered through
+     * {@link ContextHubClient.close()}. Note that the registration of this
+     * ContextHubClient at the Context Hub Service will continued to be maintained until
+     * {@link ContextHubClient.close()} is called.
+     *
      * @param hubInfo       the hub to attach this client to
-     * @param callback      the notification callback to register
-     * @param executor      the executor to invoke the callback
+     * @param pendingIntent the PendingIntent to register to the client
+     * @param nanoAppId     the ID of the nanoapp that Intent events will be generated for
      * @return the registered client object
      *
-     * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or pendingIntent
-     *                                  was not associated with a client
-     * @throws IllegalStateException    if the client is already registered to a valid callback
-     * @throws NullPointerException     if pendingIntent, hubInfo, callback, or executor is null
+     * @throws IllegalArgumentException if hubInfo does not represent a valid hub
+     * @throws IllegalStateException    if there were too many registered clients at the service
+     * @throws NullPointerException     if pendingIntent or hubInfo is null
      *
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     @NonNull public ContextHubClient createClient(
-            @NonNull PendingIntent pendingIntent, @NonNull ContextHubInfo hubInfo,
-            @NonNull ContextHubClientCallback callback,
-            @NonNull @CallbackExecutor Executor executor) {
-        Preconditions.checkNotNull(pendingIntent, "PendingIntent cannot be null");
-        Preconditions.checkNotNull(callback, "Callback cannot be null");
-        Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
-        Preconditions.checkNotNull(executor, "Executor cannot be null");
+            @NonNull ContextHubInfo hubInfo, @NonNull PendingIntent pendingIntent, long nanoAppId) {
+        Preconditions.checkNotNull(pendingIntent);
+        Preconditions.checkNotNull(hubInfo);
 
-        ContextHubClient client = new ContextHubClient(hubInfo);
-        IContextHubClientCallback clientInterface = createClientCallback(
-                client, callback, executor);
+        ContextHubClient client = new ContextHubClient(hubInfo, true /* persistent */);
 
         IContextHubClient clientProxy;
         try {
-            clientProxy = mService.bindClient(pendingIntent, clientInterface, hubInfo.getId());
+            clientProxy = mService.createPendingIntentClient(
+                    hubInfo.getId(), pendingIntent, nanoAppId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -839,30 +852,6 @@
     }
 
     /**
-     * Equivalent to {@link #createClient(PendingIntent, ContextHubInfo, ContextHubClientCallback,
-     * Executor)} with the executor using the main thread's Looper.
-     *
-     * @param pendingIntent the PendingIntent that has been registered with a client
-     * @param hubInfo       the hub to attach this client to
-     * @param callback      the notification callback to register
-     * @return the registered client object
-     *
-     * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or pendingIntent
-     *                                  was not associated with a client
-     * @throws IllegalStateException    if the client is already registered to a valid callback
-     * @throws NullPointerException     if pendingIntent, hubInfo, or callback is null
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
-    @NonNull public ContextHubClient createClient(
-            @NonNull PendingIntent pendingIntent, @NonNull ContextHubInfo hubInfo,
-            @NonNull ContextHubClientCallback callback) {
-        return createClient(
-                pendingIntent, hubInfo, callback, new HandlerExecutor(Handler.getMain()));
-    }
-
-    /**
      * Unregister a callback for receive messages from the context hub.
      *
      * @see Callback
diff --git a/core/java/android/hardware/location/IContextHubClient.aidl b/core/java/android/hardware/location/IContextHubClient.aidl
index b539414..e33545c 100644
--- a/core/java/android/hardware/location/IContextHubClient.aidl
+++ b/core/java/android/hardware/location/IContextHubClient.aidl
@@ -29,10 +29,4 @@
 
     // Closes the connection with the Context Hub
     void close();
-
-    // Registers a PendingIntent with the client
-    boolean registerIntent(in PendingIntent pendingIntent, long nanoAppId);
-
-    // Unregisters a PendingIntent from the client
-    boolean unregisterIntent(in PendingIntent pendingIntent);
 }
diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl
index 9b0acdf..19ed694 100644
--- a/core/java/android/hardware/location/IContextHubService.aidl
+++ b/core/java/android/hardware/location/IContextHubService.aidl
@@ -61,10 +61,9 @@
     // Creates a client to send and receive messages
     IContextHubClient createClient(in IContextHubClientCallback client, int contextHubId);
 
-    // Binds an existing client to a new callback interface, provided a previously registered
-    // PendingIntent
-    IContextHubClient bindClient(
-            in PendingIntent pendingIntent, in IContextHubClientCallback client, int contextHubId);
+    // Creates a PendingIntent-based client to send and receive messages
+    IContextHubClient createPendingIntentClient(
+            int contextHubId, in PendingIntent pendingIntent, long nanoAppId);
 
     // Returns a list of ContextHub objects of available hubs
     List<ContextHubInfo> getContextHubs();
diff --git a/core/java/android/hardware/location/MemoryRegion.java b/core/java/android/hardware/location/MemoryRegion.java
index 857434e..3d9e859 100644
--- a/core/java/android/hardware/location/MemoryRegion.java
+++ b/core/java/android/hardware/location/MemoryRegion.java
@@ -16,6 +16,7 @@
 
 package android.hardware.location;
 
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -106,6 +107,25 @@
     }
 
     @Override
+    public boolean equals(@Nullable Object object) {
+        if (object == this) {
+            return true;
+        }
+
+        boolean isEqual = false;
+        if (object instanceof MemoryRegion) {
+            MemoryRegion other = (MemoryRegion) object;
+            isEqual = (other.getCapacityBytes() == mSizeBytes)
+                    && (other.getFreeCapacityBytes() == mSizeBytesFree)
+                    && (other.isReadable() == mIsReadable)
+                    && (other.isWritable() == mIsWritable)
+                    && (other.isExecutable() == mIsExecutable);
+        }
+
+        return isEqual;
+    }
+
+    @Override
     public int describeContents() {
         return 0;
     }
diff --git a/core/java/android/hardware/location/NanoAppMessage.java b/core/java/android/hardware/location/NanoAppMessage.java
index 6635258..9f90d59 100644
--- a/core/java/android/hardware/location/NanoAppMessage.java
+++ b/core/java/android/hardware/location/NanoAppMessage.java
@@ -15,10 +15,13 @@
  */
 package android.hardware.location;
 
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Arrays;
+
 /**
  * A class describing messages send to or from nanoapps through the Context Hub Service.
  *
@@ -168,4 +171,22 @@
 
         return ret;
     }
+
+    @Override
+    public boolean equals(@Nullable Object object) {
+        if (object == this) {
+            return true;
+        }
+
+        boolean isEqual = false;
+        if (object instanceof NanoAppMessage) {
+            NanoAppMessage other = (NanoAppMessage) object;
+            isEqual = (other.getNanoAppId() == mNanoAppId)
+                    && (other.getMessageType() == mMessageType)
+                    && (other.isBroadcastMessage() == mIsBroadcasted)
+                    && Arrays.equals(other.getMessageBody(), mMessageBody);
+        }
+
+        return isEqual;
+    }
 }
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 007f4bc..dc4f0b7 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -611,6 +611,13 @@
      * @hide
      */
     public static final int RECOGNITION_STATUS_FAILURE = 2;
+    /**
+     * Recognition event was triggered by a getModelState request, not by the
+     * DSP.
+     *
+     * @hide
+     */
+    public static final int RECOGNITION_STATUS_GET_STATE_RESPONSE = 3;
 
     /**
      *  A RecognitionEvent is provided by the
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
index e970747..402c228 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
@@ -133,12 +133,21 @@
     public native int stopRecognition(int soundModelHandle);
 
     /**
-     * Get the current state of a {@link SoundTrigger.SoundModel}
+     * Get the current state of a {@link SoundTrigger.SoundModel}.
+     * The state will be returned asynchronously as a {@link SoundTrigger#RecognitionEvent}
+     * in the callback registered in the {@link SoundTrigger.startRecognition} method.
      * @param soundModelHandle The sound model handle indicating which model's state to return
-     * @return - {@link SoundTrigger#RecognitionEvent} in case of success
-     *         - null in case of an error or if not supported
+     * @return - {@link SoundTrigger#STATUS_OK} in case of success
+     *         - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error
+     *         - {@link SoundTrigger#STATUS_PERMISSION_DENIED} if the caller does not have
+     *         system permission
+     *         - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
+     *         - {@link SoundTrigger#STATUS_BAD_VALUE} if the sound model handle is invalid
+     *         - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native
+     *         service fails
+     *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
      */
-    public native SoundTrigger.RecognitionEvent getModelState(int soundModelHandle);
+    public native int getModelState(int soundModelHandle);
 
     private class NativeEventHandlerDelegate {
         private final Handler mHandler;
diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java b/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java
new file mode 100644
index 0000000..b4b541d
--- /dev/null
+++ b/core/java/android/inputmethodservice/MultiClientInputMethodClientCallbackAdaptor.java
@@ -0,0 +1,469 @@
+/*
+ * Copyright (C) 2018 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.inputmethodservice;
+
+import android.annotation.Nullable;
+import android.annotation.WorkerThread;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Debug;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.ResultReceiver;
+import android.util.Log;
+import android.view.InputChannel;
+import android.view.InputDevice;
+import android.view.InputEvent;
+import android.view.InputEventReceiver;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CursorAnchorInfo;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.ExtractedText;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.IMultiClientInputMethodSession;
+import com.android.internal.os.SomeArgs;
+import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.internal.view.IInputContext;
+import com.android.internal.view.IInputMethodSession;
+import com.android.internal.view.InputConnectionWrapper;
+
+import java.lang.ref.WeakReference;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Re-dispatches all the incoming per-client events to the specified {@link Looper} thread.
+ *
+ * <p>There are three types of per-client callbacks.</p>
+ *
+ * <ul>
+ *     <li>{@link IInputMethodSession} - from the IME client</li>
+ *     <li>{@link IMultiClientInputMethodSession} - from MultiClientInputMethodManagerService</li>
+ *     <li>{@link InputChannel} - from the IME client</li>
+ * </ul>
+ *
+ * <p>This class serializes all the incoming events among those channels onto
+ * {@link MultiClientInputMethodServiceDelegate.ClientCallback} on the specified {@link Looper}
+ * thread.</p>
+ */
+final class MultiClientInputMethodClientCallbackAdaptor {
+    static final boolean DEBUG = false;
+    static final String TAG = MultiClientInputMethodClientCallbackAdaptor.class.getSimpleName();
+
+    private final Object mSessionLock = new Object();
+    @GuardedBy("mSessionLock")
+    CallbackImpl mCallbackImpl;
+    @GuardedBy("mSessionLock")
+    InputChannel mReadChannel;
+    @GuardedBy("mSessionLock")
+    KeyEvent.DispatcherState mDispatcherState;
+    @GuardedBy("mSessionLock")
+    Handler mHandler;
+    @GuardedBy("mSessionLock")
+    @Nullable
+    InputEventReceiver mInputEventReceiver;
+
+    private final AtomicBoolean mFinished = new AtomicBoolean(false);
+
+    IInputMethodSession.Stub createIInputMethodSession() {
+        synchronized (mSessionLock) {
+            return new InputMethodSessionImpl(
+                    mSessionLock, mCallbackImpl, mHandler, mFinished);
+        }
+    }
+
+    IMultiClientInputMethodSession.Stub createIMultiClientInputMethodSession() {
+        synchronized (mSessionLock) {
+            return new MultiClientInputMethodSessionImpl(
+                    mSessionLock, mCallbackImpl, mHandler, mFinished);
+        }
+    }
+
+    MultiClientInputMethodClientCallbackAdaptor(
+            MultiClientInputMethodServiceDelegate.ClientCallback clientCallback, Looper looper,
+            KeyEvent.DispatcherState dispatcherState, InputChannel readChannel) {
+        synchronized (mSessionLock) {
+            mCallbackImpl = new CallbackImpl(this, clientCallback);
+            mDispatcherState = dispatcherState;
+            mHandler = new Handler(looper, null, true);
+            mReadChannel = readChannel;
+            mInputEventReceiver = new ImeInputEventReceiver(mReadChannel, mHandler.getLooper(),
+                    mFinished, mDispatcherState, mCallbackImpl.mOriginalCallback);
+        }
+    }
+
+    private static final class KeyEventCallbackAdaptor implements KeyEvent.Callback {
+        private final MultiClientInputMethodServiceDelegate.ClientCallback mLocalCallback;
+
+        KeyEventCallbackAdaptor(
+                MultiClientInputMethodServiceDelegate.ClientCallback callback) {
+            mLocalCallback = callback;
+        }
+
+        @Override
+        public boolean onKeyDown(int keyCode, KeyEvent event) {
+            return mLocalCallback.onKeyDown(keyCode, event);
+        }
+
+        @Override
+        public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+            return mLocalCallback.onKeyLongPress(keyCode, event);
+        }
+
+        @Override
+        public boolean onKeyUp(int keyCode, KeyEvent event) {
+            return mLocalCallback.onKeyUp(keyCode, event);
+        }
+
+        @Override
+        public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
+            return mLocalCallback.onKeyMultiple(keyCode, event);
+        }
+    }
+
+    private static final class ImeInputEventReceiver extends InputEventReceiver {
+        private final AtomicBoolean mFinished;
+        private final KeyEvent.DispatcherState mDispatcherState;
+        private final MultiClientInputMethodServiceDelegate.ClientCallback mClientCallback;
+        private final KeyEventCallbackAdaptor mKeyEventCallbackAdaptor;
+
+        ImeInputEventReceiver(InputChannel readChannel, Looper looper, AtomicBoolean finished,
+                KeyEvent.DispatcherState dispatcherState,
+                MultiClientInputMethodServiceDelegate.ClientCallback callback) {
+            super(readChannel, looper);
+            mFinished = finished;
+            mDispatcherState = dispatcherState;
+            mClientCallback = callback;
+            mKeyEventCallbackAdaptor = new KeyEventCallbackAdaptor(callback);
+        }
+
+        @Override
+        public void onInputEvent(InputEvent event) {
+            if (mFinished.get()) {
+                // The session has been finished.
+                finishInputEvent(event, false);
+                return;
+            }
+            boolean handled = false;
+            try {
+                if (event instanceof KeyEvent) {
+                    final KeyEvent keyEvent = (KeyEvent) event;
+                    handled = keyEvent.dispatch(mKeyEventCallbackAdaptor, mDispatcherState,
+                            mKeyEventCallbackAdaptor);
+                } else {
+                    final MotionEvent motionEvent = (MotionEvent) event;
+                    if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_TRACKBALL)) {
+                        handled = mClientCallback.onTrackballEvent(motionEvent);
+                    } else {
+                        handled = mClientCallback.onGenericMotionEvent(motionEvent);
+                    }
+                }
+            } finally {
+                finishInputEvent(event, handled);
+            }
+        }
+    }
+
+    private static final class InputMethodSessionImpl extends IInputMethodSession.Stub {
+        private final Object mSessionLock;
+        @GuardedBy("mSessionLock")
+        private CallbackImpl mCallbackImpl;
+        @GuardedBy("mSessionLock")
+        private Handler mHandler;
+        private final AtomicBoolean mSessionFinished;
+
+        InputMethodSessionImpl(Object lock, CallbackImpl callback, Handler handler,
+                AtomicBoolean sessionFinished) {
+            mSessionLock = lock;
+            mCallbackImpl = callback;
+            mHandler = handler;
+            mSessionFinished = sessionFinished;
+        }
+
+        @Override
+        public void updateExtractedText(int token, ExtractedText text) {
+            reportNotSupported();
+        }
+
+        @Override
+        public void updateSelection(int oldSelStart, int oldSelEnd,
+                int newSelStart, int newSelEnd,
+                int candidatesStart, int candidatesEnd) {
+            synchronized (mSessionLock) {
+                if (mCallbackImpl == null || mHandler == null) {
+                    return;
+                }
+                final SomeArgs args = SomeArgs.obtain();
+                args.argi1 = oldSelStart;
+                args.argi2 = oldSelEnd;
+                args.argi3 = newSelStart;
+                args.argi4 = newSelEnd;
+                args.argi5 = candidatesStart;
+                args.argi6 = candidatesEnd;
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        CallbackImpl::updateSelection, mCallbackImpl, args));
+            }
+        }
+
+        @Override
+        public void viewClicked(boolean focusChanged) {
+            reportNotSupported();
+        }
+
+        @Override
+        public void updateCursor(Rect newCursor) {
+            reportNotSupported();
+        }
+
+        @Override
+        public void displayCompletions(CompletionInfo[] completions) {
+            synchronized (mSessionLock) {
+                if (mCallbackImpl == null || mHandler == null) {
+                    return;
+                }
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        CallbackImpl::displayCompletions, mCallbackImpl, completions));
+            }
+        }
+
+        @Override
+        public void appPrivateCommand(String action, Bundle data) {
+            synchronized (mSessionLock) {
+                if (mCallbackImpl == null || mHandler == null) {
+                    return;
+                }
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        CallbackImpl::appPrivateCommand, mCallbackImpl, action, data));
+            }
+        }
+
+        @Override
+        public void toggleSoftInput(int showFlags, int hideFlags) {
+            synchronized (mSessionLock) {
+                if (mCallbackImpl == null || mHandler == null) {
+                    return;
+                }
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        CallbackImpl::toggleSoftInput, mCallbackImpl, showFlags,
+                        hideFlags));
+            }
+        }
+
+        @Override
+        public void finishSession() {
+            synchronized (mSessionLock) {
+                if (mCallbackImpl == null || mHandler == null) {
+                    return;
+                }
+                mSessionFinished.set(true);
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        CallbackImpl::finishSession, mCallbackImpl));
+                mCallbackImpl = null;
+                mHandler = null;
+            }
+        }
+
+        @Override
+        public void updateCursorAnchorInfo(CursorAnchorInfo info) {
+            synchronized (mSessionLock) {
+                if (mCallbackImpl == null || mHandler == null) {
+                    return;
+                }
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        CallbackImpl::updateCursorAnchorInfo, mCallbackImpl, info));
+            }
+        }
+    }
+
+    private static final class MultiClientInputMethodSessionImpl
+            extends IMultiClientInputMethodSession.Stub {
+        private final Object mSessionLock;
+        @GuardedBy("mSessionLock")
+        private CallbackImpl mCallbackImpl;
+        @GuardedBy("mSessionLock")
+        private Handler mHandler;
+        private final AtomicBoolean mSessionFinished;
+
+        MultiClientInputMethodSessionImpl(Object lock, CallbackImpl callback,
+                Handler handler, AtomicBoolean sessionFinished) {
+            mSessionLock = lock;
+            mCallbackImpl = callback;
+            mHandler = handler;
+            mSessionFinished = sessionFinished;
+        }
+
+        @Override
+        public void startInputOrWindowGainedFocus(@Nullable IInputContext inputContext,
+                int missingMethods, @Nullable EditorInfo editorInfo, int controlFlags,
+                @SoftInputModeFlags int softInputMode, int windowHandle) {
+            synchronized (mSessionLock) {
+                if (mCallbackImpl == null || mHandler == null) {
+                    return;
+                }
+                final SomeArgs args = SomeArgs.obtain();
+                // TODO(Bug 119211536): Remove dependency on AbstractInputMethodService from ICW
+                final WeakReference<AbstractInputMethodService> fakeIMS =
+                        new WeakReference<>(null);
+                args.arg1 = (inputContext == null) ? null
+                        : new InputConnectionWrapper(fakeIMS, inputContext, missingMethods,
+                                mSessionFinished);
+                args.arg2 = editorInfo;
+                args.argi1 = controlFlags;
+                args.argi2 = softInputMode;
+                args.argi3 = windowHandle;
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        CallbackImpl::startInputOrWindowGainedFocus, mCallbackImpl, args));
+            }
+        }
+
+        @Override
+        public void showSoftInput(int flags, ResultReceiver resultReceiver) {
+            synchronized (mSessionLock) {
+                if (mCallbackImpl == null || mHandler == null) {
+                    return;
+                }
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        CallbackImpl::showSoftInput, mCallbackImpl, flags,
+                        resultReceiver));
+            }
+        }
+
+        @Override
+        public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
+            synchronized (mSessionLock) {
+                if (mCallbackImpl == null || mHandler == null) {
+                    return;
+                }
+                mHandler.sendMessage(PooledLambda.obtainMessage(
+                        CallbackImpl::hideSoftInput, mCallbackImpl, flags,
+                        resultReceiver));
+            }
+        }
+    }
+
+    /**
+     * The maim part of adaptor to {@link MultiClientInputMethodServiceDelegate.ClientCallback}.
+     */
+    @WorkerThread
+    private static final class CallbackImpl {
+        private final MultiClientInputMethodClientCallbackAdaptor mCallbackAdaptor;
+        private final MultiClientInputMethodServiceDelegate.ClientCallback mOriginalCallback;
+        private boolean mFinished = false;
+
+        CallbackImpl(MultiClientInputMethodClientCallbackAdaptor callbackAdaptor,
+                MultiClientInputMethodServiceDelegate.ClientCallback callback) {
+            mCallbackAdaptor = callbackAdaptor;
+            mOriginalCallback = callback;
+        }
+
+        void updateSelection(SomeArgs args) {
+            try {
+                if (mFinished) {
+                    return;
+                }
+                mOriginalCallback.onUpdateSelection(args.argi1, args.argi2, args.argi3,
+                        args.argi4, args.argi5, args.argi6);
+            } finally {
+                args.recycle();
+            }
+        }
+
+        void displayCompletions(CompletionInfo[] completions) {
+            if (mFinished) {
+                return;
+            }
+            mOriginalCallback.onDisplayCompletions(completions);
+        }
+
+        void appPrivateCommand(String action, Bundle data) {
+            if (mFinished) {
+                return;
+            }
+            mOriginalCallback.onAppPrivateCommand(action, data);
+        }
+
+        void toggleSoftInput(int showFlags, int hideFlags) {
+            if (mFinished) {
+                return;
+            }
+            mOriginalCallback.onToggleSoftInput(showFlags, hideFlags);
+        }
+
+        void finishSession() {
+            if (mFinished) {
+                return;
+            }
+            mFinished = true;
+            mOriginalCallback.onFinishSession();
+            synchronized (mCallbackAdaptor.mSessionLock) {
+                mCallbackAdaptor.mDispatcherState = null;
+                if (mCallbackAdaptor.mReadChannel != null) {
+                    mCallbackAdaptor.mReadChannel.dispose();
+                    mCallbackAdaptor.mReadChannel = null;
+                }
+                mCallbackAdaptor.mInputEventReceiver = null;
+            }
+        }
+
+        void updateCursorAnchorInfo(CursorAnchorInfo info) {
+            if (mFinished) {
+                return;
+            }
+            mOriginalCallback.onUpdateCursorAnchorInfo(info);
+        }
+
+        void startInputOrWindowGainedFocus(SomeArgs args) {
+            try {
+                if (mFinished) {
+                    return;
+                }
+                final InputConnectionWrapper inputConnection = (InputConnectionWrapper) args.arg1;
+                final EditorInfo editorInfo = (EditorInfo) args.arg2;
+                final int startInputFlags = args.argi1;
+                final int softInputMode = args.argi2;
+                final int windowHandle = args.argi3;
+                mOriginalCallback.onStartInputOrWindowGainedFocus(inputConnection, editorInfo,
+                        startInputFlags, softInputMode, windowHandle);
+            } finally {
+                args.recycle();
+            }
+        }
+
+        void showSoftInput(int flags, ResultReceiver resultReceiver) {
+            if (mFinished) {
+                return;
+            }
+            mOriginalCallback.onShowSoftInput(flags, resultReceiver);
+        }
+
+        void hideSoftInput(int flags, ResultReceiver resultReceiver) {
+            if (mFinished) {
+                return;
+            }
+            mOriginalCallback.onHideSoftInput(flags, resultReceiver);
+        }
+    }
+
+    private static void reportNotSupported() {
+        if (DEBUG) {
+            Log.d(TAG, Debug.getCaller() + " is not supported");
+        }
+    }
+}
diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
new file mode 100644
index 0000000..0604f6a
--- /dev/null
+++ b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2018 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.inputmethodservice;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.ResultReceiver;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import android.view.inputmethod.CompletionInfo;
+import android.view.inputmethod.CursorAnchorInfo;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+
+import com.android.internal.inputmethod.StartInputFlags;
+
+/**
+ * Defines all the public APIs and interfaces that are necessary to implement multi-client IMEs.
+ *
+ * <p>Actual implementation is further delegated to
+ * {@link MultiClientInputMethodServiceDelegateImpl}.</p>
+ *
+ * @hide
+ */
+public final class MultiClientInputMethodServiceDelegate {
+    // @SdkConstant(SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE =
+            "android.inputmethodservice.MultiClientInputMethodService";
+
+    /**
+     * Special value that is guaranteed to be not used for IME client ID.
+     */
+    public static final int INVALID_CLIENT_ID = -1;
+
+    /**
+     * Special value that is guaranteed to be not used for window handle.
+     */
+    public static final int INVALID_WINDOW_HANDLE = -1;
+
+    private final MultiClientInputMethodServiceDelegateImpl mImpl;
+
+    /**
+     * Top-level callbacks for this {@link MultiClientInputMethodServiceDelegate}.
+     */
+    public interface ServiceCallback {
+        /**
+         * Called when this {@link MultiClientInputMethodServiceDelegate} is recognized by the
+         * system and privileged operations like {@link #createInputMethodWindowToken(int)} are
+         * ready to be called.
+         */
+        void initialized();
+
+        /**
+         * Called when a new IME client is recognized by the system.
+         *
+         * <p>Once the IME receives this callback, the IME can start interacting with the IME client
+         * by calling {@link #acceptClient(int, ClientCallback, KeyEvent.DispatcherState, Looper)}.
+         * </p>
+         *
+         * @param clientId ID of the client.
+         * @param uid UID of the IME client.
+         * @param pid PID of the IME client.
+         * @param selfReportedDisplayId display ID reported from the IME client. Since the system
+         *        does not validate this display ID, and at any time the IME client can lose the
+         *        access to this display ID, the IME needs to call
+         *        {@link #isUidAllowedOnDisplay(int, int)} to check whether the IME client still
+         *        has access to this display or not.
+         */
+        void addClient(int clientId, int uid, int pid, int selfReportedDisplayId);
+
+        /**
+         * Called when an IME client is being destroyed.
+         *
+         * @param clientId ID of the client.
+         */
+        void removeClient(int clientId);
+    }
+
+    /**
+     * Per-client callbacks.
+     */
+    public interface ClientCallback {
+        /**
+         * Called when the associated IME client called {@link
+         * android.view.inputmethod.InputMethodManager#sendAppPrivateCommand(View, String, Bundle)}.
+         *
+         * @param action Name of the command to be performed.
+         * @param data Any data to include with the command.
+         * @see android.inputmethodservice.InputMethodService#onAppPrivateCommand(String, Bundle)
+         */
+        void onAppPrivateCommand(String action, Bundle data);
+
+        /**
+         * Called when the associated IME client called {@link
+         * android.view.inputmethod.InputMethodManager#displayCompletions(View, CompletionInfo[])}.
+         *
+         * @param completions Completion information provided from the IME client.
+         * @see android.inputmethodservice.InputMethodService#onDisplayCompletions(CompletionInfo[])
+         */
+        void onDisplayCompletions(CompletionInfo[] completions);
+
+        /**
+         * Called when this callback session is closed. No further callback should not happen on
+         * this callback object.
+         */
+        void onFinishSession();
+
+        /**
+         * Called when the associated IME client called {@link
+         * android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow(IBinder, int)} or
+         * {@link android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow(IBinder, int,
+         * ResultReceiver)}.
+         *
+         * @param flags The flag passed by the client.
+         * @param resultReceiver The {@link ResultReceiver} passed by the client.
+         * @see android.inputmethodservice.InputMethodService#onWindowHidden()
+         */
+        void onHideSoftInput(int flags, ResultReceiver resultReceiver);
+
+        /**
+         * Called when the associated IME client called {@link
+         * android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} or {@link
+         * android.view.inputmethod.InputMethodManager#showSoftInput(View, int, ResultReceiver)}.
+         *
+         * @param flags The flag passed by the client.
+         * @param resultReceiver The {@link ResultReceiver} passed by the client.
+         * @see android.inputmethodservice.InputMethodService#onWindowShown()
+         */
+        void onShowSoftInput(int flags, ResultReceiver resultReceiver);
+
+        /**
+         * A generic callback when {@link InputConnection} is being established.
+         *
+         * @param inputConnection The {@link InputConnection} to be established.
+         * @param editorInfo The {@link EditorInfo} reported from the IME client.
+         * @param startInputFlags Any combinations of {@link StartInputFlags}.
+         * @param softInputMode SoftWindowMode specified to this window.
+         * @param targetWindowHandle A unique Window token.
+         * @see android.inputmethodservice.InputMethodService#onStartInput(EditorInfo, boolean)
+         */
+        void onStartInputOrWindowGainedFocus(
+                @Nullable InputConnection inputConnection,
+                @Nullable EditorInfo editorInfo,
+                @StartInputFlags int startInputFlags,
+                @SoftInputModeFlags int softInputMode,
+                int targetWindowHandle);
+
+        /**
+         * Called when the associated IME client called {@link
+         * android.view.inputmethod.InputMethodManager#toggleSoftInput(int, int)}.
+         *
+         * @param showFlags The flag passed by the client.
+         * @param hideFlags The flag passed by the client.
+         * @see android.inputmethodservice.InputMethodService#onToggleSoftInput(int, int)
+         */
+        void onToggleSoftInput(int showFlags, int hideFlags);
+
+        /**
+         * Called when the associated IME client called {@link
+         * android.view.inputmethod.InputMethodManager#updateCursorAnchorInfo(View,
+         * CursorAnchorInfo)}.
+         *
+         * @param info The {@link CursorAnchorInfo} passed by the client.
+         * @see android.inputmethodservice.InputMethodService#onUpdateCursorAnchorInfo(
+         *      CursorAnchorInfo)
+         */
+        void onUpdateCursorAnchorInfo(CursorAnchorInfo info);
+
+        /**
+         * Called when the associated IME client called {@link
+         * android.view.inputmethod.InputMethodManager#updateSelection(View, int, int, int, int)}.
+         *
+         * @param oldSelStart The previous selection start index.
+         * @param oldSelEnd The previous selection end index.
+         * @param newSelStart The new selection start index.
+         * @param newSelEnd The new selection end index.
+         * @param candidatesStart The new candidate start index.
+         * @param candidatesEnd The new candidate end index.
+         * @see android.inputmethodservice.InputMethodService#onUpdateSelection(int, int, int, int,
+         *      int, int)
+         */
+        void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd,
+                int candidatesStart, int candidatesEnd);
+
+        /**
+         * Called to give a chance for the IME to intercept generic motion events before they are
+         * processed by the application.
+         *
+         * @param event {@link MotionEvent} that is about to be handled by the IME client.
+         * @return {@code true} to tell the IME client that the IME handled this event.
+         * @see android.inputmethodservice.InputMethodService#onGenericMotionEvent(MotionEvent)
+         */
+        boolean onGenericMotionEvent(MotionEvent event);
+
+        /**
+         * Called to give a chance for the IME to intercept key down events before they are
+         * processed by the application.
+         *
+         * @param keyCode The value in {@link KeyEvent#getKeyCode()}.
+         * @param event {@link KeyEvent} for this key down event.
+         * @return {@code true} to tell the IME client that the IME handled this event.
+         * @see android.inputmethodservice.InputMethodService#onKeyDown(int, KeyEvent)
+         */
+        boolean onKeyDown(int keyCode, KeyEvent event);
+
+        /**
+         * Called to give a chance for the IME to intercept key long press events before they are
+         * processed by the application.
+         *
+         * @param keyCode The value in {@link KeyEvent#getKeyCode()}.
+         * @param event {@link KeyEvent} for this key long press event.
+         * @return {@code true} to tell the IME client that the IME handled this event.
+         * @see android.inputmethodservice.InputMethodService#onKeyLongPress(int, KeyEvent)
+         */
+        boolean onKeyLongPress(int keyCode, KeyEvent event);
+
+        /**
+         * Called to give a chance for the IME to intercept key multiple events before they are
+         * processed by the application.
+         *
+         * @param keyCode The value in {@link KeyEvent#getKeyCode()}.
+         * @param event {@link KeyEvent} for this key multiple event.
+         * @return {@code true} to tell the IME client that the IME handled this event.
+         * @see android.inputmethodservice.InputMethodService#onKeyMultiple(int, int, KeyEvent)
+         */
+        boolean onKeyMultiple(int keyCode, KeyEvent event);
+
+        /**
+         * Called to give a chance for the IME to intercept key up events before they are processed
+         * by the application.
+         *
+         * @param keyCode The value in {@link KeyEvent#getKeyCode()}.
+         * @param event {@link KeyEvent} for this key up event.
+         * @return {@code true} to tell the IME client that the IME handled this event.
+         * @see android.inputmethodservice.InputMethodService#onKeyUp(int, KeyEvent)
+         */
+        boolean onKeyUp(int keyCode, KeyEvent event);
+
+        /**
+         * Called to give a chance for the IME to intercept generic motion events before they are
+         * processed by the application.
+         *
+         * @param event {@link MotionEvent} that is about to be handled by the IME client.
+         * @return {@code true} to tell the IME client that the IME handled this event.
+         * @see android.inputmethodservice.InputMethodService#onTrackballEvent(MotionEvent)
+         */
+        boolean onTrackballEvent(MotionEvent event);
+    }
+
+    private MultiClientInputMethodServiceDelegate(Context context,
+            ServiceCallback serviceCallback) {
+        mImpl = new MultiClientInputMethodServiceDelegateImpl(context, serviceCallback);
+    }
+
+    /**
+     * Must be called by the multi-client IME implementer to create
+     * {@link MultiClientInputMethodServiceDelegate}.
+     *
+     * @param context {@link Context} with which the delegate should interact with the system.
+     * @param serviceCallback {@link ServiceCallback} to receive service-level callbacks.
+     * @return A new instance of {@link MultiClientInputMethodServiceDelegate}.
+     */
+    public static MultiClientInputMethodServiceDelegate create(Context context,
+            ServiceCallback serviceCallback) {
+        return new MultiClientInputMethodServiceDelegate(context, serviceCallback);
+    }
+
+    /**
+     * Must be called by the multi-client IME service when {@link android.app.Service#onDestroy()}
+     * is called.
+     */
+    public void onDestroy() {
+        mImpl.onDestroy();
+    }
+
+    /**
+     * Must be called by the multi-client IME service when
+     * {@link android.app.Service#onBind(Intent)} is called.
+     *
+     * @param intent {@link Intent} passed to {@link android.app.Service#onBind(Intent)}.
+     * @return An {@link IBinder} object that needs to be returned from
+     *         {@link android.app.Service#onBind(Intent)}.
+     */
+    public IBinder onBind(Intent intent) {
+        return mImpl.onBind(intent);
+    }
+
+    /**
+     * Must be called by the multi-client IME service when
+     * {@link android.app.Service#onUnbind(Intent)} is called.
+     *
+     * @param intent {@link Intent} passed to {@link android.app.Service#onUnbind(Intent)}.
+     * @return A boolean value that needs to be returned from
+     *         {@link android.app.Service#onUnbind(Intent)}.
+     */
+    public boolean onUnbind(Intent intent) {
+        return mImpl.onUnbind(intent);
+    }
+
+    /**
+     * Must be called by the multi-client IME service to create a special window token for IME
+     * window.
+     *
+     * <p>This method is available only after {@link ServiceCallback#initialized()}.</p>
+     *
+     * @param displayId display ID on which the IME window will be shown.
+     * @return Window token to be specified to the IME window/
+     */
+    public IBinder createInputMethodWindowToken(int displayId) {
+        return mImpl.createInputMethodWindowToken(displayId);
+    }
+
+    /**
+     * Must be called by the multi-client IME service to notify the system when the IME is ready to
+     * accept callback events from the specified IME client.
+     *
+     * @param clientId The IME client ID specified in
+     *                 {@link ServiceCallback#addClient(int, int, int, int)}.
+     * @param clientCallback The {@link ClientCallback} to receive callback events from this IME
+     *                       client.
+     * @param dispatcherState {@link KeyEvent.DispatcherState} to be used when receiving key-related
+     *                        callbacks in {@link ClientCallback}.
+     * @param looper {@link Looper} on which {@link ClientCallback} will be called back.
+     */
+    public void acceptClient(int clientId, ClientCallback clientCallback,
+            KeyEvent.DispatcherState dispatcherState, Looper looper) {
+        mImpl.acceptClient(clientId, clientCallback, dispatcherState, looper);
+    }
+
+    /**
+     * Must be called by the multi-client IME service to notify the system when the IME is ready to
+     * interact with the window in the IME client.
+     *
+     * @param clientId The IME client ID specified in
+     *                 {@link ServiceCallback#addClient(int, int, int, int)}.
+     * @param targetWindowHandle The window handle specified in
+     *                           {@link ClientCallback#onStartInputOrWindowGainedFocus}.
+     * @param imeWindowToken The IME window token returned from
+     *                       {@link #createInputMethodWindowToken(int)}.
+     */
+    public void reportImeWindowTarget(int clientId, int targetWindowHandle,
+            IBinder imeWindowToken) {
+        mImpl.reportImeWindowTarget(clientId, targetWindowHandle, imeWindowToken);
+    }
+
+    /**
+     * Can be called by the multi-client IME service to check if the given {@code uid} is allowed
+     * to access to {@code displayId}.
+     *
+     * @param displayId Display ID to be queried.
+     * @param uid UID to be queried.
+     * @return {@code true} if {@code uid} is allowed to access to {@code displayId}.
+     */
+    public boolean isUidAllowedOnDisplay(int displayId, int uid) {
+        return mImpl.isUidAllowedOnDisplay(displayId, uid);
+    }
+}
diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
new file mode 100644
index 0000000..bbe3a7f
--- /dev/null
+++ b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2018 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.inputmethodservice;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Looper;
+import android.util.Log;
+import android.view.InputChannel;
+import android.view.KeyEvent;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.IMultiClientInputMethod;
+import com.android.internal.inputmethod.IMultiClientInputMethodPrivilegedOperations;
+import com.android.internal.inputmethod.MultiClientInputMethodPrivilegedOperations;
+
+import java.lang.annotation.Retention;
+import java.lang.ref.WeakReference;
+
+final class MultiClientInputMethodServiceDelegateImpl {
+    private static final String TAG = "MultiClientInputMethodServiceDelegateImpl";
+
+    private final Object mLock = new Object();
+
+    @Retention(SOURCE)
+    @IntDef({InitializationPhase.INSTANTIATED,
+            InitializationPhase.ON_BIND_CALLED,
+            InitializationPhase.INITIALIZE_CALLED,
+            InitializationPhase.ON_UNBIND_CALLED,
+            InitializationPhase.ON_DESTROY_CALLED})
+    private @interface InitializationPhase {
+        int INSTANTIATED = 1;
+        int ON_BIND_CALLED = 2;
+        int INITIALIZE_CALLED = 3;
+        int ON_UNBIND_CALLED  = 4;
+        int ON_DESTROY_CALLED = 5;
+    }
+
+    @GuardedBy("mLock")
+    @InitializationPhase
+    private int mInitializationPhase;
+
+    private final MultiClientInputMethodPrivilegedOperations mPrivOps =
+            new MultiClientInputMethodPrivilegedOperations();
+
+    private final MultiClientInputMethodServiceDelegate.ServiceCallback mServiceCallback;
+
+    private final Context mContext;
+
+    MultiClientInputMethodServiceDelegateImpl(Context context,
+            MultiClientInputMethodServiceDelegate.ServiceCallback serviceCallback) {
+        mInitializationPhase = InitializationPhase.INSTANTIATED;
+        mContext = context;
+        mServiceCallback = serviceCallback;
+    }
+
+    void onDestroy() {
+        synchronized (mLock) {
+            switch (mInitializationPhase) {
+                case InitializationPhase.INSTANTIATED:
+                case InitializationPhase.ON_UNBIND_CALLED:
+                    mInitializationPhase = InitializationPhase.ON_DESTROY_CALLED;
+                    break;
+                default:
+                    Log.e(TAG, "unexpected state=" + mInitializationPhase);
+                    break;
+            }
+        }
+    }
+
+    private static final class ServiceImpl extends IMultiClientInputMethod.Stub {
+        private final WeakReference<MultiClientInputMethodServiceDelegateImpl> mImpl;
+
+        ServiceImpl(MultiClientInputMethodServiceDelegateImpl service) {
+            mImpl = new WeakReference<>(service);
+        }
+
+        @Override
+        public void initialize(IMultiClientInputMethodPrivilegedOperations privOps) {
+            final MultiClientInputMethodServiceDelegateImpl service = mImpl.get();
+            if (service == null) {
+                return;
+            }
+            synchronized (service.mLock) {
+                switch (service.mInitializationPhase) {
+                    case InitializationPhase.ON_BIND_CALLED:
+                        service.mPrivOps.set(privOps);
+                        service.mInitializationPhase = InitializationPhase.INITIALIZE_CALLED;
+                        service.mServiceCallback.initialized();
+                        break;
+                    default:
+                        Log.e(TAG, "unexpected state=" + service.mInitializationPhase);
+                        break;
+                }
+            }
+        }
+
+        @Override
+        public void addClient(int clientId, int uid, int pid, int selfReportedDisplayId) {
+            final MultiClientInputMethodServiceDelegateImpl service = mImpl.get();
+            if (service == null) {
+                return;
+            }
+            service.mServiceCallback.addClient(clientId, uid, pid, selfReportedDisplayId);
+        }
+
+        @Override
+        public void removeClient(int clientId) {
+            final MultiClientInputMethodServiceDelegateImpl service = mImpl.get();
+            if (service == null) {
+                return;
+            }
+            service.mServiceCallback.removeClient(clientId);
+        }
+    }
+
+    IBinder onBind(Intent intent) {
+        synchronized (mLock) {
+            switch (mInitializationPhase) {
+                case InitializationPhase.INSTANTIATED:
+                    mInitializationPhase = InitializationPhase.ON_BIND_CALLED;
+                    return new ServiceImpl(this);
+                default:
+                    Log.e(TAG, "unexpected state=" + mInitializationPhase);
+                    break;
+            }
+        }
+        return null;
+    }
+
+    boolean onUnbind(Intent intent) {
+        synchronized (mLock) {
+            switch (mInitializationPhase) {
+                case InitializationPhase.ON_BIND_CALLED:
+                case InitializationPhase.INITIALIZE_CALLED:
+                    mInitializationPhase = InitializationPhase.ON_UNBIND_CALLED;
+                    mPrivOps.dispose();
+                    break;
+                default:
+                    Log.e(TAG, "unexpected state=" + mInitializationPhase);
+                    break;
+            }
+        }
+        return false;
+    }
+
+    IBinder createInputMethodWindowToken(int displayId) {
+        return mPrivOps.createInputMethodWindowToken(displayId);
+    }
+
+    void acceptClient(int clientId,
+            MultiClientInputMethodServiceDelegate.ClientCallback clientCallback,
+            KeyEvent.DispatcherState dispatcherState, Looper looper) {
+        final InputChannel[] channels = InputChannel.openInputChannelPair("MSIMS-session");
+        final InputChannel writeChannel = channels[0];
+        final InputChannel readChannel = channels[1];
+        try {
+            final MultiClientInputMethodClientCallbackAdaptor callbackAdaptor =
+                    new MultiClientInputMethodClientCallbackAdaptor(clientCallback, looper,
+                            dispatcherState, readChannel);
+            mPrivOps.acceptClient(clientId, callbackAdaptor.createIInputMethodSession(),
+                    callbackAdaptor.createIMultiClientInputMethodSession(), writeChannel);
+        } finally {
+            writeChannel.dispose();
+        }
+    }
+
+    void reportImeWindowTarget(int clientId, int targetWindowHandle, IBinder imeWindowToken) {
+        mPrivOps.reportImeWindowTarget(clientId, targetWindowHandle, imeWindowToken);
+    }
+
+    boolean isUidAllowedOnDisplay(int displayId, int uid) {
+        return mPrivOps.isUidAllowedOnDisplay(displayId, uid);
+    }
+}
diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java
index 98f3567..4e551756 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -27,6 +28,8 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.net.Inet6Address;
+import java.net.UnknownHostException;
 import java.security.SecureRandom;
 import java.util.Arrays;
 import java.util.Random;
@@ -393,4 +396,49 @@
         }
         return out;
     }
+
+    /**
+     * Checks if this MAC Address matches the provided range.
+     *
+     * @param baseAddress MacAddress representing the base address to compare with.
+     * @param mask MacAddress representing the mask to use during comparison.
+     * @return true if this MAC Address matches the given range.
+     *
+     * @hide
+     */
+    public boolean matches(@NonNull MacAddress baseAddress, @NonNull MacAddress mask) {
+        Preconditions.checkNotNull(baseAddress);
+        Preconditions.checkNotNull(mask);
+        return (mAddr & mask.mAddr) == (baseAddress.mAddr & mask.mAddr);
+    }
+
+    /**
+     * Create a link-local Inet6Address from the MAC address. The EUI-48 MAC address is converted
+     * to an EUI-64 MAC address per RFC 4291. The resulting EUI-64 is used to construct a link-local
+     * IPv6 address per RFC 4862.
+     *
+     * @return A link-local Inet6Address constructed from the MAC address.
+     * @hide
+     */
+    public @Nullable Inet6Address getLinkLocalIpv6FromEui48Mac() {
+        byte[] macEui48Bytes = toByteArray();
+        byte[] addr = new byte[16];
+
+        addr[0] = (byte) 0xfe;
+        addr[1] = (byte) 0x80;
+        addr[8] = (byte) (macEui48Bytes[0] ^ (byte) 0x02); // flip the link-local bit
+        addr[9] = macEui48Bytes[1];
+        addr[10] = macEui48Bytes[2];
+        addr[11] = (byte) 0xff;
+        addr[12] = (byte) 0xfe;
+        addr[13] = macEui48Bytes[3];
+        addr[14] = macEui48Bytes[4];
+        addr[15] = macEui48Bytes[5];
+
+        try {
+            return Inet6Address.getByAddress(null, addr, 0);
+        } catch (UnknownHostException e) {
+            return null;
+        }
+    }
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9cf7de5..c437dde 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2421,7 +2421,7 @@
 
     public static final IntToString[] HISTORY_EVENT_INT_FORMATTERS = new IntToString[] {
             sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
-            sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
+            sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sIntToString,
             sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
             sUidToString, sUidToString, sUidToString, sIntToString
     };
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 0c4a0b3e..0c1aae8 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -199,6 +199,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public static File getProductDirectory() {
         return DIR_PRODUCT_ROOT;
     }
@@ -468,6 +469,14 @@
     }
 
     /**
+     * Returns location of packages cache directory.
+     * {@hide}
+     */
+    public static File getPackageCacheDirectory() {
+        return new File(getDataSystemDirectory(), "package_cache");
+    }
+
+    /**
      * Return the primary shared/external storage directory. This directory may
      * not currently be accessible if it has been mounted by the user on their
      * computer, has been removed from the device, or some other problem has
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 0b90f54..28ea553 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -1156,11 +1156,16 @@
     public static @Nullable File createDir(File baseDir, String name) {
         final File dir = new File(baseDir, name);
 
+        return createDir(dir) ? dir : null;
+    }
+
+    /** @hide */
+    public static boolean createDir(File dir) {
         if (dir.exists()) {
-            return dir.isDirectory() ? dir : null;
+            return dir.isDirectory();
         }
 
-        return dir.mkdir() ? dir : null;
+        return dir.mkdir();
     }
 
     /**
@@ -1385,3 +1390,4 @@
         }
     }
 }
+
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index ab048c5..8c5c415 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -32,11 +32,11 @@
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.util.HashSet;
-import java.util.Set;
 
 /** @hide */
 public class GraphicsEnvironment {
@@ -55,8 +55,8 @@
     private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
     private static final String PROPERTY_GFX_DRIVER_WHITELIST = "ro.gfx.driver.whitelist.0";
     private static final String ANGLE_PACKAGE_NAME = "com.android.angle";
-    private static final String GLES_MODE_METADATA_KEY = "com.android.angle.GLES_MODE";
     private static final String ANGLE_RULES_FILE = "a4a_rules.json";
+    private static final String ANGLE_TEMP_RULES = "debug.angle.rules";
 
     private ClassLoader mClassLoader;
     private String mLayerPath;
@@ -68,7 +68,7 @@
     public void setup(Context context, Bundle coreSettings) {
         setupGpuLayers(context, coreSettings);
         setupAngle(context, coreSettings);
-        chooseDriver(context);
+        chooseDriver(context, coreSettings);
     }
 
     /**
@@ -207,38 +207,11 @@
                 && (!angleEnabledApp.isEmpty() && !packageName.isEmpty())
                 && angleEnabledApp.equals(packageName)) {
 
-            if (DEBUG) Log.v(TAG, packageName + " opted in for ANGLE via Developer Setting");
+            Log.i(TAG, packageName + " opted in for ANGLE via Developer Setting");
 
             devOptIn = true;
         }
 
-        ApplicationInfo appInfo;
-        try {
-            appInfo = context.getPackageManager().getApplicationInfo(packageName,
-                PackageManager.GET_META_DATA);
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.w(TAG, "Failed to get info about current application: " + packageName);
-            return;
-        }
-
-        String appPref = "dontcare";
-        final BaseBundle metadata = appInfo.metaData;
-        if (metadata != null) {
-            final String glesMode = metadata.getString(GLES_MODE_METADATA_KEY);
-            if (glesMode != null) {
-                if (glesMode.equals("angle")) {
-                    appPref = "angle";
-                    if (DEBUG) Log.v(TAG, packageName + " opted for ANGLE via AndroidManifest");
-                } else if (glesMode.equals("native")) {
-                    appPref = "native";
-                    if (DEBUG) Log.v(TAG, packageName + " opted for NATIVE via AndroidManifest");
-                } else {
-                    Log.w(TAG, "Unrecognized GLES_MODE (\"" + glesMode + "\") for " + packageName
-                               + ". Supported values are \"angle\" or \"native\"");
-                }
-            }
-        }
-
         ApplicationInfo angleInfo;
         try {
             angleInfo = context.getPackageManager().getApplicationInfo(ANGLE_PACKAGE_NAME,
@@ -261,50 +234,88 @@
 
         if (DEBUG) Log.v(TAG, "ANGLE package libs: " + paths);
 
-        // Pass the rules file to loader for ANGLE decisions
-        AssetManager angleAssets = null;
-        try {
-            angleAssets =
-                context.getPackageManager().getResourcesForApplication(angleInfo).getAssets();
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.w(TAG, "Failed to get AssetManager for '" + ANGLE_PACKAGE_NAME + "'");
-            return;
-        }
-
-        AssetFileDescriptor assetsFd = null;
-        try {
-            assetsFd = angleAssets.openFd(ANGLE_RULES_FILE);
-        } catch (IOException e) {
-            Log.w(TAG, "Failed to get AssetFileDescriptor for " + ANGLE_RULES_FILE + " from "
-                       + "'" + ANGLE_PACKAGE_NAME + "'");
-            return;
-        }
-
+        // Look up rules file to pass to ANGLE
         FileDescriptor rulesFd = null;
         long rulesOffset = 0;
         long rulesLength = 0;
-        if (assetsFd != null) {
-            rulesFd = assetsFd.getFileDescriptor();
-            rulesOffset = assetsFd.getStartOffset();
-            rulesLength = assetsFd.getLength();
-        } else {
-            Log.w(TAG, "Failed to get file descriptor for " + ANGLE_RULES_FILE);
-            return;
+
+        // Check for temporary rules if debuggable or root
+        if (isDebuggable(context) || (getCanLoadSystemLibraries() == 1)) {
+            String angleTempRules = SystemProperties.get(ANGLE_TEMP_RULES);
+            if (angleTempRules != null && !angleTempRules.isEmpty()) {
+                Log.i(TAG, "Detected system property " + ANGLE_TEMP_RULES + ": " + angleTempRules);
+                File tempRulesFile = new File(angleTempRules);
+                if (tempRulesFile.exists()) {
+                    Log.i(TAG, angleTempRules + " exists, loading file.");
+                    FileInputStream stream = null;
+                    try {
+                        stream = new FileInputStream(angleTempRules);
+                    } catch (FileNotFoundException e) {
+                        Log.w(TAG, "Unable to create stream for temp ANGLE rules");
+                    }
+
+                    if (stream != null) {
+                        try {
+                            rulesFd = stream.getFD();
+                            rulesOffset = 0;
+                            rulesLength = stream.getChannel().size();
+                            Log.i(TAG, "Loaded temporary ANGLE rules from " + angleTempRules);
+                        } catch (IOException e) {
+                            Log.w(TAG, "Failed to get input stream for " + angleTempRules);
+                        }
+                    }
+                }
+            }
+        }
+
+        // If no temp rules, load the real ones from the APK
+        if (rulesFd == null) {
+
+            // Pass the rules file to loader for ANGLE decisions
+            AssetManager angleAssets = null;
+            try {
+                angleAssets =
+                    context.getPackageManager().getResourcesForApplication(angleInfo).getAssets();
+            } catch (PackageManager.NameNotFoundException e) {
+                Log.w(TAG, "Failed to get AssetManager for '" + ANGLE_PACKAGE_NAME + "'");
+                return;
+            }
+
+            AssetFileDescriptor assetsFd = null;
+            try {
+                assetsFd = angleAssets.openFd(ANGLE_RULES_FILE);
+            } catch (IOException e) {
+                Log.w(TAG, "Failed to get AssetFileDescriptor for " + ANGLE_RULES_FILE + " from "
+                           + "'" + ANGLE_PACKAGE_NAME + "'");
+                return;
+            }
+
+            if (assetsFd != null) {
+                rulesFd = assetsFd.getFileDescriptor();
+                rulesOffset = assetsFd.getStartOffset();
+                rulesLength = assetsFd.getLength();
+            } else {
+                Log.w(TAG, "Failed to get file descriptor for " + ANGLE_RULES_FILE);
+                return;
+            }
         }
 
         // Further opt-in logic is handled in native, so pass relevant info down
-        setAngleInfo(paths, packageName, appPref, devOptIn,
+        // TODO: Move the ANGLE selection logic earlier so we don't need to keep these
+        //       file descriptors open.
+        setAngleInfo(paths, packageName, devOptIn,
                      rulesFd, rulesOffset, rulesLength);
     }
 
     /**
      * Choose whether the current process should use the builtin or an updated driver.
      */
-    private static void chooseDriver(Context context) {
+    private static void chooseDriver(Context context, Bundle coreSettings) {
         String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
         if (driverPackageName == null || driverPackageName.isEmpty()) {
             return;
         }
+
         // To minimize risk of driver updates crippling the device beyond user repair, never use an
         // updated driver for privileged or non-updated system apps. Presumably pre-installed apps
         // were tested thoroughly with the pre-installed driver.
@@ -313,12 +324,16 @@
             if (DEBUG) Log.v(TAG, "ignoring driver package for privileged/non-updated system app");
             return;
         }
-        Set<String> whitelist = loadWhitelist(context, driverPackageName);
 
-        // Empty whitelist implies no updatable graphics driver. Typically, the pre-installed
-        // updatable graphics driver is supposed to be a place holder and contains no graphics
-        // driver and whitelist.
-        if (whitelist == null || whitelist.isEmpty()) {
+        String applicationPackageName = context.getPackageName();
+        String devOptInApplicationName = coreSettings.getString(
+                Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP);
+        boolean devOptIn = applicationPackageName.equals(devOptInApplicationName);
+        boolean whitelisted = onWhitelist(context, driverPackageName, ai.packageName);
+        if (!devOptIn && !whitelisted) {
+            if (DEBUG) {
+                Log.w(TAG, applicationPackageName + " is not on the whitelist.");
+            }
             return;
         }
 
@@ -330,12 +345,6 @@
             Log.w(TAG, "driver package '" + driverPackageName + "' not installed");
             return;
         }
-        if (!whitelist.contains(context.getPackageName())) {
-            if (DEBUG) {
-                Log.w(TAG, context.getPackageName() + " is not on the whitelist.");
-            }
-            return;
-        }
 
         // O drivers are restricted to the sphal linker namespace, so don't try to use
         // packages unless they declare they're compatible with that restriction.
@@ -401,10 +410,18 @@
         return null;
     }
 
-    private static Set<String> loadWhitelist(Context context, String driverPackageName) {
+    private static boolean onWhitelist(Context context, String driverPackageName,
+            String applicationPackageName) {
         String whitelistName = SystemProperties.get(PROPERTY_GFX_DRIVER_WHITELIST);
+
+        // Empty whitelist implies no updatable graphics driver. Typically, the pre-installed
+        // updatable graphics driver is supposed to be a place holder and contains no graphics
+        // driver and whitelist.
         if (whitelistName == null || whitelistName.isEmpty()) {
-            return null;
+            if (DEBUG) {
+                Log.w(TAG, "No whitelist found.");
+            }
+            return false;
         }
         try {
             Context driverContext = context.createPackageContext(driverPackageName,
@@ -412,11 +429,11 @@
             AssetManager assets = driverContext.getAssets();
             InputStream stream = assets.open(whitelistName);
             BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
-            Set<String> whitelist = new HashSet<>();
-            for (String line; (line = reader.readLine()) != null; ) {
-                whitelist.add(line);
+            for (String packageName; (packageName = reader.readLine()) != null; ) {
+                if (packageName.equals(applicationPackageName)) {
+                    return true;
+                }
             }
-            return whitelist;
         } catch (PackageManager.NameNotFoundException e) {
             if (DEBUG) {
                 Log.w(TAG, "driver package '" + driverPackageName + "' not installed");
@@ -426,7 +443,7 @@
                 Log.w(TAG, "Failed to load whitelist driver package, abort.");
             }
         }
-        return null;
+        return false;
     }
 
     private static native int getCanLoadSystemLibraries();
@@ -434,7 +451,7 @@
     private static native void setDebugLayers(String layers);
     private static native void setDebugLayersGLES(String layers);
     private static native void setDriverPath(String path);
-    private static native void setAngleInfo(String path, String appPackage, String appPref,
+    private static native void setAngleInfo(String path, String appPackage,
                                             boolean devOptIn, FileDescriptor rulesFd,
                                             long rulesOffset, long rulesLength);
 }
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 7ceeb52..ca5b233 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -48,6 +48,8 @@
     boolean isPowerSaveMode();
     PowerSaveState getPowerSaveState(int serviceType);
     boolean setPowerSaveMode(boolean mode);
+    boolean setDynamicPowerSavings(boolean dynamicPowerSavingsEnabled, int disableThreshold);
+    int getPowerSaveMode();
     boolean isDeviceIdleMode();
     boolean isLightDeviceIdleMode();
 
diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl
index 124f207..74d434c 100644
--- a/core/java/android/os/IStatsManager.aidl
+++ b/core/java/android/os/IStatsManager.aidl
@@ -62,12 +62,15 @@
      * Inform statsd what the version and package are for each uid. Note that each array should
      * have the same number of elements, and version[i] and package[i] correspond to uid[i].
      */
-    oneway void informAllUidData(in int[] uid, in long[] version, in String[] app);
+    oneway void informAllUidData(in int[] uid, in long[] version, in String[] version_string,
+        in String[] app, in String[] installer);
 
     /**
-     * Inform statsd what the uid and version are for one app that was updated.
+     * Inform statsd what the uid, version, version_string, and installer are for one app that was
+     * updated.
      */
-    oneway void informOnePackage(in String app, in int uid, in long version);
+    oneway void informOnePackage(in String app, in int uid, in long version,
+        in String version_string, in String installer);
 
     /**
      * Inform stats that an app was removed.
diff --git a/core/java/android/os/IThermalEventListener.aidl b/core/java/android/os/IThermalEventListener.aidl
index 9a6de60..fc93b5c 100644
--- a/core/java/android/os/IThermalEventListener.aidl
+++ b/core/java/android/os/IThermalEventListener.aidl
@@ -27,6 +27,5 @@
      * Called when a thermal throttling start/stop event is received.
      * @param temperature the temperature at which the event was generated.
      */
-    void notifyThrottling(
-        in boolean isThrottling, in Temperature temperature);
+    void notifyThrottling(in Temperature temperature);
 }
diff --git a/core/java/android/os/IThermalService.aidl b/core/java/android/os/IThermalService.aidl
index e388eda..287a5ed 100644
--- a/core/java/android/os/IThermalService.aidl
+++ b/core/java/android/os/IThermalService.aidl
@@ -19,6 +19,8 @@
 import android.os.IThermalEventListener;
 import android.os.Temperature;
 
+import java.util.List;
+
 /**
  * {@hide}
  */
@@ -30,22 +32,29 @@
       */
     void registerThermalEventListener(in IThermalEventListener listener);
     /**
+      * Register a listener for thermal events on given temperature type.
+      * @param listener the IThermalEventListener to be notified.
+      * @param type the temperature type IThermalEventListener to be notified.
+      * {@hide}
+      */
+    void registerThermalEventListenerWithType(in IThermalEventListener listener, in int type);
+    /**
       * Unregister a previously-registered listener for thermal events.
       * @param listener the IThermalEventListener to no longer be notified.
       * {@hide}
       */
     void unregisterThermalEventListener(in IThermalEventListener listener);
     /**
-      * Send a thermal throttling start/stop notification to all listeners.
-      * @param temperature the temperature at which the event was generated.
+      * Get current temperature with its throttling status.
+      * @return list of android.os.Temperature
       * {@hide}
       */
-    oneway void notifyThrottling(
-        in boolean isThrottling, in Temperature temperature);
+    List<Temperature> getCurrentTemperatures();
     /**
-      * Return whether system performance is currently thermal throttling.
-      * @return true if thermal throttling is currently in effect
+      * Get current temperature with its throttling status on given temperature type.
+      * @param type the temperature type to query.
+      * @return list of android.os.Temperature
       * {@hide}
       */
-    boolean isThrottling();
+    List<Temperature> getCurrentTemperaturesWithType(in int type);
 }
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 70688fd..44b9e311 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -881,9 +881,9 @@
         @Override
         public void close() throws IOException {
             try {
-                mPfd.close();
-            } finally {
                 super.close();
+            } finally {
+                mPfd.close();
             }
         }
 
@@ -932,9 +932,9 @@
         @Override
         public void close() throws IOException {
             try {
-                mPfd.close();
-            } finally {
                 super.close();
+            } finally {
+                mPfd.close();
             }
         }
     }
@@ -1056,6 +1056,9 @@
     /**
      * Internal class representing a remote status read by
      * {@link ParcelFileDescriptor#readCommStatus(FileDescriptor, byte[])}.
+     *
+     * Warning: this must be kept in sync with ParcelFileDescriptorStatus at
+     * frameworks/native/libs/binder/Parcel.cpp
      */
     private static class Status {
         /** Special value indicating remote side died. */
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index e0b2c78..1c1db68 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.Manifest.permission;
 import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
@@ -23,6 +24,7 @@
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
+import android.service.dreams.Sandman;
 import android.util.Log;
 import android.util.proto.ProtoOutputStream;
 
@@ -477,6 +479,13 @@
     public static final String SHUTDOWN_BATTERY_THERMAL_STATE = "thermal,battery";
 
     /**
+     * The value to pass as the 'reason' argument to android_reboot() when device temperature
+     * is too high.
+     * @hide
+     */
+    public static final String SHUTDOWN_THERMAL_STATE = "thermal";
+
+    /**
      * The value to pass as the 'reason' argument to android_reboot() when device is running
      * critically low on battery.
      * @hide
@@ -993,6 +1002,29 @@
     }
 
     /**
+     * Requests the device to start dreaming.
+     * <p>
+     * If dream can not be started, for example if another {@link PowerManager} transition is in
+     * progress, does nothing. Unlike {@link #nap(long)}, this does not put device to sleep when
+     * dream ends.
+     * </p><p>
+     * Requires the {@link android.Manifest.permission#WRITE_DREAM_STATE} permission.
+     * </p>
+     *
+     * @param time The time when the request to nap was issued, in the
+     * {@link SystemClock#uptimeMillis()} time base.  This timestamp may be used to correctly
+     * order the dream request with other power management functions.  It should be set
+     * to the timestamp of the input event that caused the request to dream.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)
+    public void dream(long time) {
+        Sandman.startDreamByUserRequest(mContext);
+    }
+
+    /**
      * Boosts the brightness of the screen to maximum for a predetermined
      * period of time.  This is used to make the screen more readable in bright
      * daylight for a short duration.
@@ -1178,6 +1210,105 @@
     }
 
     /**
+     * Updates the current state of dynamic power savings and disable threshold. This is
+     * a signal to the system which an app can update to serve as an indicator that
+     * the user will be in a battery critical situation before being able to plug in.
+     * Only apps with the {@link android.Manifest.permission#POWER_SAVER} permission may do this.
+     * This is a device global state, not a per user setting.
+     *
+     * <p>When enabled, the system may enact various measures for reducing power consumption in
+     * order to help ensure that the user will make it to their next charging point. The most
+     * visible of these will be the automatic enabling of battery saver if the user has set
+     * their battery saver mode to "automatic". Note
+     * that this is NOT simply an on/off switch for features, but rather a hint for the
+     * system to consider enacting these power saving features, some of which have additional
+     * logic around when to activate based on this signal.
+     *
+     * <p>The provided threshold is the percentage the system should consider itself safe at given
+     * the current state of the device. The value is an integer representing a battery level.
+     *
+     * <p>The threshold is meant to set an explicit stopping point for dynamic power savings
+     * functionality so that the dynamic power savings itself remains a signal rather than becoming
+     * an on/off switch for a subset of features.
+     * @hide
+     *
+     * @param dynamicPowerSavingsEnabled A signal indicating to the system if it believes the
+     * dynamic power savings behaviors should be activated.
+     * @param disableThreshold When the suggesting app believes it would be safe to disable dynamic
+     * power savings behaviors.
+     * @return True if the update was allowed and succeeded.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(permission.POWER_SAVER)
+    public boolean setDynamicPowerSavings(boolean dynamicPowerSavingsEnabled,
+            int disableThreshold) {
+        try {
+            return mService.setDynamicPowerSavings(dynamicPowerSavingsEnabled, disableThreshold);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Indicates automatic battery saver toggling by the system will be based on percentage.
+     *
+     * @see PowerManager#getPowerSaveMode()
+     *
+     *  @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int POWER_SAVER_MODE_PERCENTAGE = 0;
+
+    /**
+     * Indicates automatic battery saver toggling by the system will be based on the state
+     * of the dynamic power savings signal.
+     *
+     * @see PowerManager#setDynamicPowerSavings(boolean, int)
+     * @see PowerManager#getPowerSaveMode()
+     *
+     *  @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int POWER_SAVER_MODE_DYNAMIC = 1;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+        POWER_SAVER_MODE_PERCENTAGE,
+        POWER_SAVER_MODE_DYNAMIC
+
+    })
+    public @interface AutoPowerSaverMode{}
+
+
+    /**
+     * Returns the current battery saver control mode. Values it may return are defined in
+     * AutoPowerSaverMode. Note that this is a global device state, not a per user setting.
+     *
+     * @return The current value power saver mode for the system.
+     *
+     * @see AutoPowerSaverMode
+     * @see PowerManager#getPowerSaveMode()
+     * @hide
+     */
+    @AutoPowerSaverMode
+    @SystemApi
+    @TestApi
+    @RequiresPermission(android.Manifest.permission.POWER_SAVER)
+    public int getPowerSaveMode() {
+        try {
+            return mService.getPowerSaveMode();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Get data about the battery saver mode for a specific service
      * @param serviceType unique key for the service, one of {@link ServiceType}
      * @return Battery saver state data.
diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java
index 72e1ab9..866bd9a 100644
--- a/core/java/android/os/StatsLogEventWrapper.java
+++ b/core/java/android/os/StatsLogEventWrapper.java
@@ -104,14 +104,6 @@
     }
 
     /**
-     * Write a double value.
-     */
-    public void writeDouble(double val) {
-        mTypes.add(EVENT_TYPE_DOUBLE);
-        mValues.add(val);
-    }
-
-    /**
      * Write a storage value.
      */
     public void writeStorage(byte[] val) {
diff --git a/core/java/android/os/Temperature.java b/core/java/android/os/Temperature.java
index 8767731..37ed52c 100644
--- a/core/java/android/os/Temperature.java
+++ b/core/java/android/os/Temperature.java
@@ -16,6 +16,13 @@
 
 package android.os;
 
+import android.annotation.IntDef;
+import android.hardware.thermal.V2_0.TemperatureType;
+import android.hardware.thermal.V2_0.ThrottlingSeverity;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Temperature values used by IThermalService.
  */
@@ -24,24 +31,89 @@
  * @hide
  */
 public class Temperature implements Parcelable {
-    /* Temperature value */
+    /** Temperature value */
     private float mValue;
-    /* A temperature type from HardwarePropertiesManager */
+    /** A temperature type from ThermalHAL */
     private int mType;
+    /** Name of this temperature */
+    private String mName;
+    /** The level of the sensor is currently in throttling */
+    private int mStatus;
 
-    public Temperature() {
-        this(HardwarePropertiesManager.UNDEFINED_TEMPERATURE,
-            Integer.MIN_VALUE);
+    /** @hide */
+    @IntDef(prefix = { "THROTTLING_" }, value = {
+            THROTTLING_NONE,
+            THROTTLING_LIGHT,
+            THROTTLING_MODERATE,
+            THROTTLING_SEVERE,
+            THROTTLING_CRITICAL,
+            THROTTLING_WARNING,
+            THROTTLING_SHUTDOWN,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ThrottlingStatus {}
+
+    /** Keep in sync with hardware/interfaces/thermal/2.0/types.hal */
+    public static final int THROTTLING_NONE = ThrottlingSeverity.NONE;
+    public static final int THROTTLING_LIGHT = ThrottlingSeverity.LIGHT;
+    public static final int THROTTLING_MODERATE = ThrottlingSeverity.MODERATE;
+    public static final int THROTTLING_SEVERE = ThrottlingSeverity.SEVERE;
+    public static final int THROTTLING_CRITICAL = ThrottlingSeverity.CRITICAL;
+    public static final int THROTTLING_WARNING = ThrottlingSeverity.WARNING;
+    public static final int THROTTLING_SHUTDOWN = ThrottlingSeverity.SHUTDOWN;
+
+    /** @hide */
+    @IntDef(prefix = { "TYPE_" }, value = {
+            TYPE_UNKNOWN,
+            TYPE_CPU,
+            TYPE_GPU,
+            TYPE_BATTERY,
+            TYPE_SKIN,
+            TYPE_USB_PORT,
+            TYPE_POWER_AMPLIFIER,
+            TYPE_BCL_VOLTAGE,
+            TYPE_BCL_CURRENT,
+            TYPE_BCL_PERCENTAGE,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Type {}
+
+    /* Keep in sync with hardware/interfaces/thermal/2.0/types.hal */
+    public static final int TYPE_UNKNOWN = TemperatureType.UNKNOWN;
+    public static final int TYPE_CPU = TemperatureType.CPU;
+    public static final int TYPE_GPU = TemperatureType.GPU;
+    public static final int TYPE_BATTERY = TemperatureType.BATTERY;
+    public static final int TYPE_SKIN = TemperatureType.SKIN;
+    public static final int TYPE_USB_PORT = TemperatureType.USB_PORT;
+    public static final int TYPE_POWER_AMPLIFIER = TemperatureType.POWER_AMPLIFIER;
+    public static final int TYPE_BCL_VOLTAGE = TemperatureType.BCL_VOLTAGE;
+    public static final int TYPE_BCL_CURRENT = TemperatureType.BCL_CURRENT;
+    public static final int TYPE_BCL_PERCENTAGE = TemperatureType.BCL_PERCENTAGE;
+
+    /**
+     * Verify a valid temperature type.
+     *
+     * @return true if a temperature type is valid otherwise false.
+     */
+    public static boolean isValidType(int type) {
+        return type >= TYPE_UNKNOWN && type <= TYPE_BCL_PERCENTAGE;
     }
 
-    public Temperature(float value, int type) {
+    public Temperature() {
+        this(Float.NaN, TYPE_UNKNOWN, "", THROTTLING_NONE);
+    }
+
+    public Temperature(float value, @Type int type, String name, int status) {
         mValue = value;
-        mType = type;
+        mType = isValidType(type) ? type : TYPE_UNKNOWN;
+        mName = name;
+        mStatus = status;
     }
 
     /**
      * Return the temperature value.
-     * @return a temperature value in floating point.
+     *
+     * @return a temperature value in floating point could be NaN.
      */
     public float getValue() {
         return mValue;
@@ -49,18 +121,30 @@
 
     /**
      * Return the temperature type.
-     * @return a temperature type:
-     *         HardwarePropertiesManager.DEVICE_TEMPERATURE_CPU, etc.
+     *
+     * @return a temperature type: TYPE_*
      */
-    public int getType() {
+    public @Type int getType() {
         return mType;
     }
 
-    /*
-     * Parcel read/write code must be kept in sync with
-     * frameworks/native/services/thermalservice/aidl/android/os/
-     * Temperature.cpp
+    /**
+     * Return the temperature name.
+     *
+     * @return a temperature name as String.
      */
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * Return the temperature throttling status.
+     *
+     * @return a temperature throttling status: THROTTLING_*
+     */
+    public @ThrottlingStatus int getStatus() {
+        return mStatus;
+    }
 
     private Temperature(Parcel p) {
         readFromParcel(p);
@@ -68,31 +152,36 @@
 
     /**
      * Fill in Temperature members from a Parcel.
+     *
      * @param p the parceled Temperature object.
      */
     public void readFromParcel(Parcel p) {
         mValue = p.readFloat();
         mType = p.readInt();
+        mName = p.readString();
+        mStatus = p.readInt();
     }
 
     @Override
     public void writeToParcel(Parcel p, int flags) {
         p.writeFloat(mValue);
         p.writeInt(mType);
+        p.writeString(mName);
+        p.writeInt(mStatus);
     }
 
     public static final Parcelable.Creator<Temperature> CREATOR =
             new Parcelable.Creator<Temperature>() {
-        @Override
-        public Temperature createFromParcel(Parcel p) {
-            return new Temperature(p);
-        }
+                @Override
+                public Temperature createFromParcel(Parcel p) {
+                    return new Temperature(p);
+                }
 
-        @Override
-        public Temperature[] newArray(int size) {
-            return new Temperature[size];
-        }
-    };
+                @Override
+                public Temperature[] newArray(int size) {
+                    return new Temperature[size];
+                }
+            };
 
     @Override
     public int describeContents() {
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 33b2676..bf988ae 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -188,6 +188,6 @@
     void allocateBytes(String volumeUuid, long bytes, int flags, String callingPackage) = 78;
     void runIdleMaintenance() = 79;
     void abortIdleMaintenance() = 80;
-    String translateAppToSystem(String path, String packageName, int userId) = 81;
-    String translateSystemToApp(String path, String packageName, int userId) = 82;
+    String translateAppToSystem(String path, int pid, int uid) = 81;
+    String translateSystemToApp(String path, int pid, int uid) = 82;
 }
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index c91cda6..423ce77 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -225,6 +225,8 @@
     public static final int DEBUG_SDCARDFS_FORCE_OFF = 1 << 4;
     /** {@hide} */
     public static final int DEBUG_VIRTUAL_DISK = 1 << 5;
+    /** {@hide} */
+    public static final int DEBUG_ISOLATED_STORAGE = 1 << 6;
 
     /** {@hide} */
     public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE;
@@ -266,6 +268,9 @@
     public static final int ENCRYPTION_STATE_ERROR_CORRUPT =
             IVold.ENCRYPTION_STATE_ERROR_CORRUPT;
 
+    /** @hide Prefix used in sandboxIds for apps with sharedUserIds */
+    public static final String SHARED_SANDBOX_PREFIX = "shared-";
+
     private static volatile IStorageManager sStorageManager = null;
 
     private final Context mContext;
@@ -799,7 +804,7 @@
         try {
             for (VolumeInfo vol : mStorageManager.getVolumes(0)) {
                 if (vol.path != null && FileUtils.contains(vol.path, pathString)
-                        && vol.type != VolumeInfo.TYPE_PUBLIC) {
+                        && vol.type != VolumeInfo.TYPE_PUBLIC && vol.type != VolumeInfo.TYPE_STUB) {
                     // TODO: verify that emulated adopted devices have UUID of
                     // underlying volume
                     try {
@@ -1546,13 +1551,13 @@
      *
      * @hide
      */
-    public File translateAppToSystem(File file, String packageName) {
+    public File translateAppToSystem(File file, int pid, int uid) {
         // We can only translate absolute paths
         if (!file.isAbsolute()) return file;
 
         try {
             return new File(mStorageManager.translateAppToSystem(file.getAbsolutePath(),
-                    packageName, mContext.getUserId()));
+                    pid, uid));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1564,13 +1569,13 @@
      *
      * @hide
      */
-    public File translateSystemToApp(File file, String packageName) {
+    public File translateSystemToApp(File file, int pid, int uid) {
         // We can only translate absolute paths
         if (!file.isAbsolute()) return file;
 
         try {
             return new File(mStorageManager.translateSystemToApp(file.getAbsolutePath(),
-                    packageName, mContext.getUserId()));
+                    pid, uid));
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 5bef7ee..8a03e9e 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -331,7 +331,12 @@
      * @return intent to request access, or {@code null} if the requested directory is invalid for
      *         that volume.
      * @see DocumentsContract
+     * @deprecated Callers should migrate to using {@link Intent#ACTION_OPEN_DOCUMENT_TREE} instead.
+     *             Launching this {@link Intent} on devices running
+     *             {@link android.os.Build.VERSION_CODES#Q} or higher, will immediately finish
+     *             with a result code of {@link android.app.Activity#RESULT_CANCELED}.
      */
+    @Deprecated
     public @Nullable Intent createAccessIntent(String directoryName) {
         if ((isPrimary() && directoryName == null) ||
                 (directoryName != null && !Environment.isStandardDirectory(directoryName))) {
@@ -425,32 +430,4 @@
         parcel.writeString(mFsUuid);
         parcel.writeString(mState);
     }
-
-    /** {@hide} */
-    public static final class ScopedAccessProviderContract {
-
-        private ScopedAccessProviderContract() {
-            throw new UnsupportedOperationException("contains constants only");
-        }
-
-        public static final String AUTHORITY = "com.android.documentsui.scopedAccess";
-
-        public static final String TABLE_PACKAGES = "packages";
-        public static final String TABLE_PERMISSIONS = "permissions";
-
-        public static final String COL_PACKAGE = "package_name";
-        public static final String COL_VOLUME_UUID = "volume_uuid";
-        public static final String COL_DIRECTORY = "directory";
-        public static final String COL_GRANTED = "granted";
-
-        public static final String[] TABLE_PACKAGES_COLUMNS = new String[] { COL_PACKAGE };
-        public static final String[] TABLE_PERMISSIONS_COLUMNS =
-                new String[] { COL_PACKAGE, COL_VOLUME_UUID, COL_DIRECTORY, COL_GRANTED };
-
-        public static final int TABLE_PACKAGES_COL_PACKAGE = 0;
-        public static final int TABLE_PERMISSIONS_COL_PACKAGE = 0;
-        public static final int TABLE_PERMISSIONS_COL_VOLUME_UUID = 1;
-        public static final int TABLE_PERMISSIONS_COL_DIRECTORY = 2;
-        public static final int TABLE_PERMISSIONS_COL_GRANTED = 3;
-    }
 }
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index e55afb6..8c3aa17 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -84,6 +84,7 @@
     public static final int TYPE_EMULATED = IVold.VOLUME_TYPE_EMULATED;
     public static final int TYPE_ASEC = IVold.VOLUME_TYPE_ASEC;
     public static final int TYPE_OBB = IVold.VOLUME_TYPE_OBB;
+    public static final int TYPE_STUB = IVold.VOLUME_TYPE_STUB;
 
     public static final int STATE_UNMOUNTED = IVold.VOLUME_STATE_UNMOUNTED;
     public static final int STATE_CHECKING = IVold.VOLUME_STATE_CHECKING;
@@ -295,7 +296,7 @@
     }
 
     public boolean isVisibleForUser(int userId) {
-        if (type == TYPE_PUBLIC && mountUserId == userId) {
+        if ((type == TYPE_PUBLIC || type == TYPE_STUB) && mountUserId == userId) {
             return isVisible();
         } else if (type == TYPE_EMULATED) {
             return isVisible();
@@ -327,7 +328,7 @@
     public File getPathForUser(int userId) {
         if (path == null) {
             return null;
-        } else if (type == TYPE_PUBLIC) {
+        } else if (type == TYPE_PUBLIC || type == TYPE_STUB) {
             return new File(path);
         } else if (type == TYPE_EMULATED) {
             return new File(path, Integer.toString(userId));
@@ -344,7 +345,7 @@
     public File getInternalPathForUser(int userId) {
         if (path == null) {
             return null;
-        } else if (type == TYPE_PUBLIC) {
+        } else if (type == TYPE_PUBLIC || type == TYPE_STUB) {
             // TODO: plumb through cleaner path from vold
             return new File(path.replace("/storage/", "/mnt/media_rw/"));
         } else {
@@ -390,7 +391,7 @@
                 removable = true;
             }
 
-        } else if (type == TYPE_PUBLIC) {
+        } else if (type == TYPE_PUBLIC || type == TYPE_STUB) {
             emulated = false;
             removable = true;
 
@@ -447,7 +448,8 @@
 
     public @Nullable Intent buildBrowseIntentForUser(int userId) {
         final Uri uri;
-        if (type == VolumeInfo.TYPE_PUBLIC && mountUserId == userId) {
+        if ((type == VolumeInfo.TYPE_PUBLIC || type == VolumeInfo.TYPE_STUB)
+                && mountUserId == userId) {
             uri = DocumentsContract.buildRootUri(DOCUMENT_AUTHORITY, fsUuid);
         } else if (type == VolumeInfo.TYPE_EMULATED && isPrimary()) {
             uri = DocumentsContract.buildRootUri(DOCUMENT_AUTHORITY,
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index fc30eed..2ea7066 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -67,15 +67,14 @@
      * such an old app asks for a location permission (i.e. the
      * {@link SplitPermissionInfo#getSplitPermission()}), then the
      * {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside
-     * {@{@link SplitPermissionInfo#getNewPermissions}) is added.
+     * {@link SplitPermissionInfo#getNewPermissions}) is added.
      *
      * <p>Note: Regular apps do not have to worry about this. The platform and permission controller
      * automatically add the new permissions where needed.
      *
      * @return All permissions that are split.
      */
-    public @NonNull
-    List<SplitPermissionInfo> getSplitPermissions() {
+    public @NonNull List<SplitPermissionInfo> getSplitPermissions() {
         return SPLIT_PERMISSIONS;
     }
 
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index c0fa1de..3d93afd 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -509,6 +509,100 @@
         private static final int MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS = 1000 * 10;
 
         /**
+         * Value for {@link CallLog.Calls#BLOCK_REASON}, set as the default value when a call was
+         * not blocked by a CallScreeningService or any other system call blocking method.
+         */
+        public static final int BLOCK_REASON_NOT_BLOCKED = 0;
+
+        /**
+         * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+         * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked by a
+         * CallScreeningService. The {@link CallLog.Calls#CALL_SCREENING_COMPONENT_NAME} and
+         * {@link CallLog.Calls#CALL_SCREENING_APP_NAME} columns will indicate which call screening
+         * service was responsible for blocking the call.
+         */
+        public static final int BLOCK_REASON_CALL_SCREENING_SERVICE = 1;
+
+        /**
+         * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+         * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
+         * configured a contact to be sent directly to voicemail.
+         */
+        public static final int BLOCK_REASON_DIRECT_TO_VOICEMAIL = 2;
+
+        /**
+         * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+         * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because it is
+         * in the BlockedNumbers provider.
+         */
+        public static final int BLOCK_REASON_BLOCKED_NUMBER = 3;
+
+        /**
+         * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+         * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
+         * has chosen to block all calls from unknown numbers.
+         */
+        public static final int BLOCK_REASON_UNKNOWN_NUMBER = 4;
+
+        /**
+         * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+         * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
+         * has chosen to block all calls from restricted numbers.
+         */
+        public static final int BLOCK_REASON_RESTRICTED_NUMBER = 5;
+
+        /**
+         * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+         * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
+         * has chosen to block all calls from pay phones.
+         */
+        public static final int BLOCK_REASON_PAY_PHONE = 6;
+
+        /**
+         * Value for {@link CallLog.Calls#BLOCK_REASON}, set when {@link CallLog.Calls#TYPE} is
+         * {@link CallLog.Calls#BLOCKED_TYPE} to indicate that a call was blocked because the user
+         * has chosen to block all calls from numbers not in their contacts.
+         */
+        public static final int BLOCK_REASON_NOT_IN_CONTACTS = 7;
+
+        /**
+         * The ComponentName of the CallScreeningService which blocked this call. Will be
+         * populated when the {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE}.
+         * <P>Type: TEXT</P>
+         */
+        public static final String CALL_SCREENING_COMPONENT_NAME = "call_screening_component_name";
+
+        /**
+         * The name of the app which blocked a call. Will be populated when the
+         * {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE}. Provided as a
+         * convenience so that the call log can still indicate which app blocked a call, even if
+         * that app is no longer installed.
+         * <P>Type: TEXT</P>
+         */
+        public static final String CALL_SCREENING_APP_NAME = "call_screening_app_name";
+
+        /**
+         * Where the {@link CallLog.Calls#TYPE} is {@link CallLog.Calls#BLOCKED_TYPE},
+         * indicates the reason why a call is blocked.
+         * <P>Type: INTEGER</P>
+         *
+         * <p>
+         * Allowed values:
+         * <ul>
+         * <li>{@link CallLog.Calls#BLOCK_REASON_NOT_BLOCKED}</li>
+         * <li>{@link CallLog.Calls#BLOCK_REASON_CALL_SCREENING_SERVICE}</li>
+         * <li>{@link CallLog.Calls#BLOCK_REASON_DIRECT_TO_VOICEMAIL}</li>
+         * <li>{@link CallLog.Calls#BLOCK_REASON_BLOCKED_NUMBER}</li>
+         * <li>{@link CallLog.Calls#BLOCK_REASON_UNKNOWN_NUMBER}</li>
+         * <li>{@link CallLog.Calls#BLOCK_REASON_RESTRICTED_NUMBER}</li>
+         * <li>{@link CallLog.Calls#BLOCK_REASON_PAY_PHONE}</li>
+         * <li>{@link CallLog.Calls#BLOCK_REASON_NOT_IN_CONTACTS}</li>
+         * </ul>
+         * </p>
+         */
+        public static final String BLOCK_REASON = "block_reason";
+
+        /**
          * Adds a call to the call log.
          *
          * @param ci the CallerInfo object to get the target contact from.  Can be null
@@ -530,12 +624,14 @@
          * {@hide}
          */
         public static Uri addCall(CallerInfo ci, Context context, String number,
-                int presentation, int callType, int features, PhoneAccountHandle accountHandle,
+                int presentation, int callType, int features,
+                PhoneAccountHandle accountHandle,
                 long start, int duration, Long dataUsage) {
-            return addCall(ci, context, number, /* postDialDigits =*/ "", /* viaNumber =*/ "",
-                    presentation, callType, features, accountHandle, start, duration,
-                    dataUsage, /* addForAllUsers =*/ false, /* userToBeInsertedTo =*/ null,
-                    /* is_read =*/ false);
+            return addCall(ci, context, number, "" /* postDialDigits */, "" /* viaNumber */,
+                presentation, callType, features, accountHandle, start, duration,
+                dataUsage, false /* addForAllUsers */, null /* userToBeInsertedTo */,
+                false /* isRead */, Calls.BLOCK_REASON_NOT_BLOCKED /* callBlockReason */,
+                null /* callScreeningAppName */, null /* callScreeningComponentName */);
         }
 
 
@@ -572,8 +668,10 @@
                 int features, PhoneAccountHandle accountHandle, long start, int duration,
                 Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo) {
             return addCall(ci, context, number, postDialDigits, viaNumber, presentation, callType,
-                    features, accountHandle, start, duration, dataUsage, addForAllUsers,
-                    userToBeInsertedTo, /* is_read =*/ false);
+                features, accountHandle, start, duration, dataUsage, addForAllUsers,
+                userToBeInsertedTo, false /* isRead */ , Calls.BLOCK_REASON_NOT_BLOCKED
+                /* callBlockReason */, null /* callScreeningAppName */,
+                null /* callScreeningComponentName */);
         }
 
         /**
@@ -602,8 +700,11 @@
          * @param userToBeInsertedTo {@link UserHandle} of user that the call is going to be
          *                           inserted to. null if it is inserted to the current user. The
          *                           value is ignored if @{link addForAllUsers} is true.
-         * @param is_read Flag to show if the missed call log has been read by the user or not.
+         * @param isRead Flag to show if the missed call log has been read by the user or not.
          *                Used for call log restore of missed calls.
+         * @param callBlockReason The reason why the call is blocked.
+         * @param callScreeningAppName The call screening application name which block the call.
+         * @param callScreeningComponentName The call screening component name which block the call.
          *
          * @result The URI of the call log entry belonging to the user that made or received this
          *        call.  This could be of the shadow provider.  Do not return it to non-system apps,
@@ -615,7 +716,8 @@
                 String postDialDigits, String viaNumber, int presentation, int callType,
                 int features, PhoneAccountHandle accountHandle, long start, int duration,
                 Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo,
-                boolean is_read) {
+                boolean isRead, int callBlockReason, String callScreeningAppName,
+                String callScreeningComponentName) {
             if (VERBOSE_LOG) {
                 Log.v(LOG_TAG, String.format("Add call: number=%s, user=%s, for all=%s",
                         number, userToBeInsertedTo, addForAllUsers));
@@ -690,9 +792,13 @@
             values.put(ADD_FOR_ALL_USERS, addForAllUsers ? 1 : 0);
 
             if (callType == MISSED_TYPE) {
-                values.put(IS_READ, Integer.valueOf(is_read ? 1 : 0));
+                values.put(IS_READ, Integer.valueOf(isRead ? 1 : 0));
             }
 
+            values.put(BLOCK_REASON, callBlockReason);
+            values.put(CALL_SCREENING_APP_NAME, callScreeningAppName);
+            values.put(CALL_SCREENING_COMPONENT_NAME, callScreeningComponentName);
+
             if ((ci != null) && (ci.contactIdOrZero > 0)) {
                 // Update usage information for the number associated with the contact ID.
                 // We need to use both the number and the ID for obtaining a data ID since other
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 67e52aa..16d454d 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -16,12 +16,11 @@
 
 package android.provider;
 
-import static android.system.OsConstants.SEEK_SET;
-
 import static com.android.internal.util.Preconditions.checkArgument;
 import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
 import static com.android.internal.util.Preconditions.checkCollectionNotEmpty;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.content.ContentProviderClient;
@@ -29,13 +28,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.MimeTypeFilter;
 import android.content.pm.ResolveInfo;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.graphics.ImageDecoder;
-import android.graphics.Matrix;
 import android.graphics.Point;
 import android.media.ExifInterface;
 import android.net.Uri;
@@ -50,20 +48,13 @@
 import android.os.ParcelableException;
 import android.os.RemoteException;
 import android.os.storage.StorageVolume;
-import android.system.ErrnoException;
-import android.system.Os;
 import android.util.DataUnit;
 import android.util.Log;
-import android.util.Size;
 
-import libcore.io.IoUtils;
-
-import java.io.BufferedInputStream;
 import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
@@ -113,6 +104,54 @@
     public static final String EXTRA_TARGET_URI = "android.content.extra.TARGET_URI";
 
     /**
+     * Key for {@link DocumentsProvider} to query display name is matched.
+     * The match of display name is partial matching and case-insensitive.
+     * Ex: The value is "o", the display name of the results will contain
+     * both "foo" and "Open".
+     *
+     * @see DocumentsProvider#querySearchDocuments(String, String[],
+     *      Bundle)
+     * {@hide}
+     */
+    public static final String QUERY_ARG_DISPLAY_NAME = "android:query-arg-display-name";
+
+    /**
+     * Key for {@link DocumentsProvider} to query mime types is matched.
+     * The value is a string array, it can support different mime types.
+     * Each items will be treated as "OR" condition. Ex: {"image/*" ,
+     * "video/*"}. The mime types of the results will contain both image
+     * type and video type.
+     *
+     * @see DocumentsProvider#querySearchDocuments(String, String[],
+     *      Bundle)
+     * {@hide}
+     */
+    public static final String QUERY_ARG_MIME_TYPES = "android:query-arg-mime-types";
+
+    /**
+     * Key for {@link DocumentsProvider} to query the file size in bytes is
+     * larger than the value.
+     *
+     * @see DocumentsProvider#querySearchDocuments(String, String[],
+     *      Bundle)
+     * {@hide}
+     */
+    public static final String QUERY_ARG_FILE_SIZE_OVER = "android:query-arg-file-size-over";
+
+    /**
+     * Key for {@link DocumentsProvider} to query the last modified time
+     * is newer than the value. The unit is in milliseconds since
+     * January 1, 1970 00:00:00.0 UTC.
+     *
+     * @see DocumentsProvider#querySearchDocuments(String, String[],
+     *      Bundle)
+     * @see Document#COLUMN_LAST_MODIFIED
+     * {@hide}
+     */
+    public static final String QUERY_ARG_LAST_MODIFIED_AFTER =
+            "android:query-arg-last-modified-after";
+
+    /**
      * Sets the desired initial location visible to user when file chooser is shown.
      *
      * <p>Applicable to {@link Intent} with actions:
@@ -929,6 +968,89 @@
     }
 
     /**
+     * Check if the values match the query arguments.
+     *
+     * @param queryArgs the query arguments
+     * @param displayName the display time to check against
+     * @param mimeType the mime type to check against
+     * @param lastModified the last modified time to check against
+     * @param size the size to check against
+     * @hide
+     */
+    public static boolean matchSearchQueryArguments(Bundle queryArgs, String displayName,
+            String mimeType, long lastModified, long size) {
+        if (queryArgs == null) {
+            return true;
+        }
+
+        final String argDisplayName = queryArgs.getString(QUERY_ARG_DISPLAY_NAME, "");
+        if (!argDisplayName.isEmpty()) {
+            // TODO (118795812) : Enhance the search string handled in DocumentsProvider
+            if (!displayName.toLowerCase().contains(argDisplayName.toLowerCase())) {
+                return false;
+            }
+        }
+
+        final long argFileSize = queryArgs.getLong(QUERY_ARG_FILE_SIZE_OVER, -1 /* defaultValue */);
+        if (argFileSize != -1 && size < argFileSize) {
+            return false;
+        }
+
+        final long argLastModified = queryArgs.getLong(QUERY_ARG_LAST_MODIFIED_AFTER,
+                -1 /* defaultValue */);
+        if (argLastModified != -1 && lastModified < argLastModified) {
+            return false;
+        }
+
+        final String[] argMimeTypes = queryArgs.getStringArray(QUERY_ARG_MIME_TYPES);
+        if (argMimeTypes != null && argMimeTypes.length > 0) {
+            mimeType = Intent.normalizeMimeType(mimeType);
+            for (String type : argMimeTypes) {
+                if (MimeTypeFilter.matches(mimeType, Intent.normalizeMimeType(type))) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Get the handled query arguments from the query bundle. The handled arguments are
+     * {@link DocumentsContract#QUERY_ARG_DISPLAY_NAME},
+     * {@link DocumentsContract#QUERY_ARG_MIME_TYPES},
+     * {@link DocumentsContract#QUERY_ARG_FILE_SIZE_OVER} and
+     * {@link DocumentsContract#QUERY_ARG_LAST_MODIFIED_AFTER}.
+     *
+     * @param queryArgs the query arguments to be parsed.
+     * @return the handled query arguments
+     * @hide
+     */
+    public static String[] getHandledQueryArguments(Bundle queryArgs) {
+        if (queryArgs == null) {
+            return new String[0];
+        }
+
+        final ArrayList<String> args = new ArrayList<>();
+        if (queryArgs.keySet().contains(QUERY_ARG_DISPLAY_NAME)) {
+            args.add(QUERY_ARG_DISPLAY_NAME);
+        }
+
+        if (queryArgs.keySet().contains(QUERY_ARG_FILE_SIZE_OVER)) {
+            args.add(QUERY_ARG_FILE_SIZE_OVER);
+        }
+
+        if (queryArgs.keySet().contains(QUERY_ARG_LAST_MODIFIED_AFTER)) {
+            args.add(QUERY_ARG_LAST_MODIFIED_AFTER);
+        }
+
+        if (queryArgs.keySet().contains(QUERY_ARG_MIME_TYPES)) {
+            args.add(QUERY_ARG_MIME_TYPES);
+        }
+        return args.toArray(new String[0]);
+    }
+
+    /**
      * Test if the given URI represents a {@link Document} backed by a
      * {@link DocumentsProvider}.
      *
@@ -1052,6 +1174,15 @@
         return searchDocumentsUri.getQueryParameter(PARAM_QUERY);
     }
 
+    /**
+     * Extract the search query from a Bundle
+     * {@link #QUERY_ARG_DISPLAY_NAME}.
+     * {@hide}
+     */
+    public static String getSearchDocumentsQuery(@NonNull Bundle bundle) {
+        return bundle.getString(QUERY_ARG_DISPLAY_NAME, "" /* defaultValue */);
+    }
+
     /** {@hide} */
     @UnsupportedAppUsage
     public static Uri setManageMode(Uri uri) {
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 68f8acd..58f8213 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -32,7 +32,6 @@
 import static android.provider.DocumentsContract.buildTreeDocumentUri;
 import static android.provider.DocumentsContract.getDocumentId;
 import static android.provider.DocumentsContract.getRootId;
-import static android.provider.DocumentsContract.getSearchDocumentsQuery;
 import static android.provider.DocumentsContract.getTreeDocumentId;
 import static android.provider.DocumentsContract.isTreeUri;
 
@@ -47,6 +46,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.MimeTypeFilter;
 import android.content.UriMatcher;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
@@ -651,6 +651,55 @@
     }
 
     /**
+     * Return documents that match the given query under the requested
+     * root. The returned documents should be sorted by relevance in descending
+     * order. How documents are matched against the query string is an
+     * implementation detail left to each provider, but it's suggested that at
+     * least {@link Document#COLUMN_DISPLAY_NAME} be matched in a
+     * case-insensitive fashion.
+     * <p>
+     * If your provider is cloud-based, and you have some data cached or pinned
+     * locally, you may return the local data immediately, setting
+     * {@link DocumentsContract#EXTRA_LOADING} on the Cursor to indicate that
+     * you are still fetching additional data. Then, when the network data is
+     * available, you can send a change notification to trigger a requery and
+     * return the complete contents.
+     * <p>
+     * To support change notifications, you must
+     * {@link Cursor#setNotificationUri(ContentResolver, Uri)} with a relevant
+     * Uri, such as {@link DocumentsContract#buildSearchDocumentsUri(String,
+     * String, String)}. Then you can call {@link ContentResolver#notifyChange(Uri,
+     * android.database.ContentObserver, boolean)} with that Uri to send change
+     * notifications.
+     *
+     * @param rootId the root to search under.
+     * @param projection list of {@link Document} columns to put into the
+     *            cursor. If {@code null} all supported columns should be
+     *            included.
+     * @param queryArgs the query arguments.
+     *            {@link DocumentsContract#QUERY_ARG_DISPLAY_NAME},
+     *            {@link DocumentsContract#QUERY_ARG_MIME_TYPES},
+     *            {@link DocumentsContract#QUERY_ARG_FILE_SIZE_OVER},
+     *            {@link DocumentsContract#QUERY_ARG_LAST_MODIFIED_AFTER}.
+     * @return cursor containing search result. Include
+     *         {@link ContentResolver#EXTRA_HONORED_ARGS} in {@link Cursor}
+     *         extras {@link Bundle} when any QUERY_ARG_* value was honored
+     *         during the preparation of the results.
+     *
+     * @see ContentResolver#EXTRA_HONORED_ARGS
+     * @see DocumentsContract#EXTRA_LOADING
+     * @see DocumentsContract#EXTRA_INFO
+     * @see DocumentsContract#EXTRA_ERROR
+     * {@hide}
+     */
+    @SuppressWarnings("unused")
+    public Cursor querySearchDocuments(String rootId, String[] projection, Bundle queryArgs)
+            throws FileNotFoundException {
+        return querySearchDocuments(rootId, DocumentsContract.getSearchDocumentsQuery(queryArgs),
+                projection);
+    }
+
+    /**
      * Ejects the root. Throws {@link IllegalStateException} if ejection failed.
      *
      * @param rootId the root to be ejected.
@@ -795,7 +844,7 @@
      *      {@link #queryDocument(String, String[])},
      *      {@link #queryRecentDocuments(String, String[])},
      *      {@link #queryRoots(String[])}, and
-     *      {@link #querySearchDocuments(String, String, String[])}.
+     *      {@link #querySearchDocuments(String, String[], Bundle)}.
      */
     @Override
     public Cursor query(Uri uri, String[] projection, String selection,
@@ -812,7 +861,7 @@
      * @see #queryRecentDocuments(String, String[], Bundle, CancellationSignal)
      * @see #queryDocument(String, String[])
      * @see #queryChildDocuments(String, String[], String)
-     * @see #querySearchDocuments(String, String, String[])
+     * @see #querySearchDocuments(String, String[], Bundle)
      */
     @Override
     public final Cursor query(
@@ -825,8 +874,7 @@
                     return queryRecentDocuments(
                             getRootId(uri), projection, queryArgs, cancellationSignal);
                 case MATCH_SEARCH:
-                    return querySearchDocuments(
-                            getRootId(uri), getSearchDocumentsQuery(uri), projection);
+                    return querySearchDocuments(getRootId(uri), projection, queryArgs);
                 case MATCH_DOCUMENT:
                 case MATCH_DOCUMENT_TREE:
                     enforceTree(uri);
@@ -1301,7 +1349,7 @@
                 final long flags =
                     cursor.getLong(cursor.getColumnIndexOrThrow(Document.COLUMN_FLAGS));
                 if ((flags & Document.FLAG_VIRTUAL_DOCUMENT) == 0 && mimeType != null &&
-                        mimeTypeMatches(mimeTypeFilter, mimeType)) {
+                        MimeTypeFilter.matches(mimeType, mimeTypeFilter)) {
                     return new String[] { mimeType };
                 }
             }
@@ -1354,21 +1402,4 @@
         // For any other yet unhandled case, let the provider subclass handle it.
         return openTypedDocument(documentId, mimeTypeFilter, opts, signal);
     }
-
-    /**
-     * @hide
-     */
-    public static boolean mimeTypeMatches(String filter, String test) {
-        if (test == null) {
-            return false;
-        } else if (filter == null || "*/*".equals(filter)) {
-            return true;
-        } else if (filter.equals(test)) {
-            return true;
-        } else if (filter.endsWith("/*")) {
-            return filter.regionMatches(0, test, 0, filter.indexOf('/'));
-        } else {
-            return false;
-        }
-    }
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 689f975..b266648 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1600,8 +1600,11 @@
      * Applications typically use this action to ask the user to revert the "Do not ask again"
      * status of directory access requests made by
      * {@link android.os.storage.StorageVolume#createAccessIntent(String)}.
+     * @deprecated use {@link #ACTION_APPLICATION_DETAILS_SETTINGS} to manage storage permissions
+     *             for a specific application
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    @Deprecated
     public static final String ACTION_STORAGE_VOLUME_ACCESS_SETTINGS =
             "android.settings.STORAGE_VOLUME_ACCESS_SETTINGS";
 
@@ -1822,53 +1825,6 @@
     })
     public @interface ResetMode{}
 
-
-    /**
-     * Indicates that the user has not started setup personalization.
-     * One of the possible states for {@link Secure#USER_SETUP_PERSONALIZATION_STATE}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int USER_SETUP_PERSONALIZATION_NOT_STARTED = 0;
-
-    /**
-     * Indicates that the user has not yet completed setup personalization.
-     * One of the possible states for {@link Secure#USER_SETUP_PERSONALIZATION_STATE}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int USER_SETUP_PERSONALIZATION_STARTED = 1;
-
-    /**
-     * Indicates that the user has snoozed personalization and will complete it later.
-     * One of the possible states for {@link Secure#USER_SETUP_PERSONALIZATION_STATE}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2;
-
-    /**
-     * Indicates that the user has completed setup personalization.
-     * One of the possible states for {@link Secure#USER_SETUP_PERSONALIZATION_STATE}.
-     *
-     * @hide
-     */
-    @SystemApi
-    public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            USER_SETUP_PERSONALIZATION_NOT_STARTED,
-            USER_SETUP_PERSONALIZATION_STARTED,
-            USER_SETUP_PERSONALIZATION_PAUSED,
-            USER_SETUP_PERSONALIZATION_COMPLETE
-    })
-    public @interface UserSetupPersonalization {}
-
     /**
      * Activity Extra: Number of certificates
      * <p>
@@ -4892,6 +4848,7 @@
             MOVED_TO_GLOBAL.add(Settings.Global.WIFI_NETWORK_SHOW_RSSI);
             MOVED_TO_GLOBAL.add(Settings.Global.WIFI_WATCHDOG_ON);
             MOVED_TO_GLOBAL.add(Settings.Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED);
+            MOVED_TO_GLOBAL.add(Settings.Global.WIFI_P2P_PENDING_FACTORY_RESET);
             MOVED_TO_GLOBAL.add(Settings.Global.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON);
             MOVED_TO_GLOBAL.add(Settings.Global.PACKAGE_VERIFIER_ENABLE);
             MOVED_TO_GLOBAL.add(Settings.Global.PACKAGE_VERIFIER_TIMEOUT);
@@ -5646,6 +5603,52 @@
         public static final String USER_SETUP_COMPLETE = "user_setup_complete";
 
         /**
+         * Indicates that the user has not started setup personalization.
+         * One of the possible states for {@link #USER_SETUP_PERSONALIZATION_STATE}.
+         *
+         * @hide
+         */
+        @SystemApi
+        public static final int USER_SETUP_PERSONALIZATION_NOT_STARTED = 0;
+
+        /**
+         * Indicates that the user has not yet completed setup personalization.
+         * One of the possible states for {@link #USER_SETUP_PERSONALIZATION_STATE}.
+         *
+         * @hide
+         */
+        @SystemApi
+        public static final int USER_SETUP_PERSONALIZATION_STARTED = 1;
+
+        /**
+         * Indicates that the user has snoozed personalization and will complete it later.
+         * One of the possible states for {@link #USER_SETUP_PERSONALIZATION_STATE}.
+         *
+         * @hide
+         */
+        @SystemApi
+        public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2;
+
+        /**
+         * Indicates that the user has completed setup personalization.
+         * One of the possible states for {@link #USER_SETUP_PERSONALIZATION_STATE}.
+         *
+         * @hide
+         */
+        @SystemApi
+        public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10;
+
+        /** @hide */
+        @Retention(RetentionPolicy.SOURCE)
+        @IntDef({
+                USER_SETUP_PERSONALIZATION_NOT_STARTED,
+                USER_SETUP_PERSONALIZATION_STARTED,
+                USER_SETUP_PERSONALIZATION_PAUSED,
+                USER_SETUP_PERSONALIZATION_COMPLETE
+        })
+        public @interface UserSetupPersonalization {}
+
+        /**
          * Defines the user's current state of device personalization.
          * The possible states are defined in {@link UserSetupPersonalization}.
          *
@@ -6564,23 +6567,22 @@
         public static final String MULTI_PRESS_TIMEOUT = "multi_press_timeout";
 
         /**
-         * Whether the user specifies a minimum ui timeout to override minimum ui timeout of
-         * accessibility service
+         * Setting that specifies recommended timeout in milliseconds for controls
+         * which don't need user's interactions.
          *
-         * Type: int (0 for false, 1 for true)
          * @hide
          */
-        public static final String ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED =
-                "accessibility_minimum_ui_timeout_enabled";
+        public static final String ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS =
+                "accessibility_non_interactive_ui_timeout_ms";
 
         /**
-         * Setting that specifies ui minimum timeout in milliseconds.
+         * Setting that specifies recommended timeout in milliseconds for controls
+         * which need user's interactions.
          *
-         * @see #ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED
          * @hide
          */
-        public static final String ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS =
-                "accessibility_minimum_ui_timeout_ms";
+        public static final String ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS =
+                "accessibility_interactive_ui_timeout_ms";
 
         /**
          * List of the enabled print services.
@@ -8198,6 +8200,12 @@
                 "packages_to_clear_data_before_full_restore";
 
         /**
+         * Setting to determine whether to use the new notification priority handling features.
+         * @hide
+         */
+        public static final String NOTIFICATION_NEW_INTERRUPTION_MODEL = "new_interruption_model";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -8309,8 +8317,9 @@
             ZEN_SETTINGS_SUGGESTION_VIEWED,
             CHARGING_SOUNDS_ENABLED,
             CHARGING_VIBRATION_ENABLED,
-            ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED,
-            ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS,
+            ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS,
+            ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS,
+            NOTIFICATION_NEW_INTERRUPTION_MODEL,
         };
 
         /**
@@ -8466,10 +8475,12 @@
             VALIDATORS.put(ZEN_SETTINGS_SUGGESTION_VIEWED, BOOLEAN_VALIDATOR);
             VALIDATORS.put(CHARGING_SOUNDS_ENABLED, BOOLEAN_VALIDATOR);
             VALIDATORS.put(CHARGING_VIBRATION_ENABLED, BOOLEAN_VALIDATOR);
-            VALIDATORS.put(ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED, BOOLEAN_VALIDATOR);
-            VALIDATORS.put(ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS,
+                    NON_NEGATIVE_INTEGER_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR);
             VALIDATORS.put(USER_SETUP_COMPLETE, BOOLEAN_VALIDATOR);
             VALIDATORS.put(ASSIST_GESTURE_SETUP_COMPLETE, BOOLEAN_VALIDATOR);
+            VALIDATORS.put(NOTIFICATION_NEW_INTERRUPTION_MODEL, BOOLEAN_VALIDATOR);
         }
 
         /**
@@ -9162,6 +9173,13 @@
         public static final String DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT
                 = "enable_freeform_support";
 
+        /**
+         * Whether to enable experimental desktop mode on secondary displays.
+         * @hide
+         */
+        public static final String DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS =
+                "force_desktop_mode_on_external_displays";
+
        /**
         * Whether user has enabled development settings.
         */
@@ -9984,6 +10002,15 @@
                 "wifi_rtt_background_exec_gap_ms";
 
         /**
+         * Indicate whether factory reset request is pending.
+         *
+         * Type: int (0 for false, 1 for true)
+         * @hide
+         */
+        public static final String WIFI_P2P_PENDING_FACTORY_RESET =
+                "wifi_p2p_pending_factory_reset";
+
+        /**
          * Whether soft AP will shut down after a timeout period when no devices are connected.
          *
          * Type: int (0 for false, 1 for true)
@@ -10297,6 +10324,18 @@
         private static final Validator WIFI_PNO_FREQUENCY_CULLING_ENABLED_VALIDATOR =
                 BOOLEAN_VALIDATOR;
 
+        /**
+         * Setting to enable including recency information when determining pno network priorities.
+         * Disabled by default, and setting it to 1 will enable it.
+         * The value is boolean (0 or 1).
+         * @hide
+         */
+        public static final String WIFI_PNO_RECENCY_SORTING_ENABLED =
+                "wifi_pno_recency_sorting_enabled";
+
+        private static final Validator WIFI_PNO_RECENCY_SORTING_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
        /**
         * The maximum number of times we will retry a connection to an access
         * point for which we have failed in acquiring an IP address from DHCP.
@@ -11499,6 +11538,24 @@
         public static final String NETWORK_WATCHLIST_ENABLED = "network_watchlist_enabled";
 
         /**
+         * Whether or not show hidden launcher icon apps feature is enabled.
+         * Type: int (0 for false, 1 for true)
+         * Default: 0
+         * @hide
+         */
+        public static final String SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED =
+                "show_hidden_icon_apps_enabled";
+
+        /**
+         * Whether or not show new app installed notification is enabled.
+         * Type: int (0 for false, 1 for true)
+         * Default: 0
+         * @hide
+         */
+        public static final String SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED =
+                "show_new_app_installed_notification_enabled";
+
+        /**
          * Flag to keep background restricted profiles running after exiting. If disabled,
          * the restricted profile can be put into stopped state as soon as the user leaves it.
          * Type: int (0 for false, 1 for true)
@@ -11713,6 +11770,13 @@
         public static final String ANGLE_ENABLED_APP = "angle_enabled_app";
 
         /**
+         * App that is selected to use updated graphics driver.
+         * @hide
+         */
+        public static final String UPDATED_GFX_DRIVER_DEV_OPT_IN_APP =
+                "updated_gfx_driver_dev_opt_in_app";
+
+        /**
          * Ordered GPU debug layer list for Vulkan
          * i.e. <layer1>:<layer2>:...:<layerN>
          * @hide
@@ -11758,14 +11822,54 @@
 
         /**
          * Battery level [1-100] at which low power mode automatically turns on.
-         * If 0, it will not automatically turn on.
+         * Pre-Q If 0, it will not automatically turn on. Q and newer it will only automatically
+         * turn on if the {@link #AUTOMATIC_POWER_SAVER_MODE} setting is also set to
+         * {@link android.os.PowerManager.AutoPowerSaverMode#POWER_SAVER_MODE_PERCENTAGE}.
+         *
+         * @see #AUTOMATIC_POWER_SAVER_MODE
+         * @see android.os.PowerManager#getPowerSaveMode()
          * @hide
          */
         public static final String LOW_POWER_MODE_TRIGGER_LEVEL = "low_power_trigger_level";
 
+
         private static final Validator LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR =
                 new SettingsValidators.InclusiveIntegerRangeValidator(0, 100);
 
+        /**
+         * Whether battery saver is currently set to trigger based on percentage, dynamic power
+         * savings trigger, or none. See {@link android.os.PowerManager.AutoPowerSaverMode} for
+         * accepted values.
+         *
+         *  @hide
+         */
+        @TestApi
+        public static final String AUTOMATIC_POWER_SAVER_MODE = "automatic_power_saver_mode";
+
+        private static final Validator AUTOMATIC_POWER_SAVER_MODE_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1"});
+
+        /**
+         * The setting that backs the disable threshold for the setPowerSavingsWarning api in
+         * PowerManager
+         *
+         * @see android.os.PowerManager#setDynamicPowerSavings(boolean, int)
+         * @hide
+         */
+        @TestApi
+        public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD =
+                "dynamic_power_savings_disable_threshold";
+        private static final Validator DYNAMIC_POWER_SAVINGS_VALIDATOR =
+                new SettingsValidators.InclusiveIntegerRangeValidator(0, 100);
+
+        /**
+         * The setting which backs the setDynamicPowerSavings api in PowerManager.
+         *
+         * @see android.os.PowerManager#setDynamicPowerSavings(boolean, int)
+         * @hide
+         */
+        @TestApi
+        public static final String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
 
         /**
          * The max value for {@link #LOW_POWER_MODE_TRIGGER_LEVEL}. If this setting is not set
@@ -12490,6 +12594,17 @@
                 "privileged_device_identifier_target_q_behavior_enabled";
 
         /**
+         * If set to 1, the device identifier check will be relaxed to the previous READ_PHONE_STATE
+         * permission check for 3P apps.
+         *
+         * STOPSHIP: Remove this once we ship with the new device identifier check enabled.
+         *
+         * @hide
+         */
+        public static final String PRIVILEGED_DEVICE_IDENTIFIER_3P_CHECK_RELAXED =
+                "privileged_device_identifier_3p_check_relaxed";
+
+        /**
          * If set to 1, SettingsProvider's restoreAnyVersion="true" attribute will be ignored
          * and restoring to lower version of platform API will be skipped.
          *
@@ -12572,27 +12687,14 @@
                 "hidden_api_access_log_sampling_rate";
 
         /**
-         * Hidden API enforcement policy for apps targeting SDK versions prior to the latest
-         * version.
+         * Hidden API enforcement policy for apps.
          *
          * Values correspond to @{@link
          * android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy}
          *
          * @hide
          */
-        public static final String HIDDEN_API_POLICY_PRE_P_APPS =
-                "hidden_api_policy_pre_p_apps";
-
-        /**
-         * Hidden API enforcement policy for apps targeting the current SDK version.
-         *
-         * Values correspond to @{@link
-         * android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy}
-         *
-         * @hide
-         */
-        public static final String HIDDEN_API_POLICY_P_APPS =
-                "hidden_api_policy_p_apps";
+        public static final String HIDDEN_API_POLICY = "hidden_api_policy";
 
         /**
          * Timeout for a single {@link android.media.soundtrigger.SoundTriggerDetectionService}
@@ -12691,6 +12793,9 @@
             VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL, LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
             VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
                     LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
+            VALIDATORS.put(AUTOMATIC_POWER_SAVER_MODE, AUTOMATIC_POWER_SAVER_MODE_VALIDATOR);
+            VALIDATORS.put(DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
+                    DYNAMIC_POWER_SAVINGS_VALIDATOR);
             VALIDATORS.put(BLUETOOTH_ON, BLUETOOTH_ON_VALIDATOR);
             VALIDATORS.put(PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_VALIDATOR);
             VALIDATORS.put(PRIVATE_DNS_SPECIFIER, PRIVATE_DNS_SPECIFIER_VALIDATOR);
@@ -12706,6 +12811,8 @@
             VALIDATORS.put(DEVICE_DEMO_MODE, BOOLEAN_VALIDATOR);
             VALIDATORS.put(WIFI_PNO_FREQUENCY_CULLING_ENABLED,
                     WIFI_PNO_FREQUENCY_CULLING_ENABLED_VALIDATOR);
+            VALIDATORS.put(WIFI_PNO_RECENCY_SORTING_ENABLED,
+                    WIFI_PNO_RECENCY_SORTING_ENABLED_VALIDATOR);
         }
 
         /**
diff --git a/core/java/android/rolecontrollerservice/IRoleControllerService.aidl b/core/java/android/rolecontrollerservice/IRoleControllerService.aidl
index 0000b9f..ac5be06 100644
--- a/core/java/android/rolecontrollerservice/IRoleControllerService.aidl
+++ b/core/java/android/rolecontrollerservice/IRoleControllerService.aidl
@@ -30,4 +30,6 @@
                            in IRoleManagerCallback callback);
 
     void onClearRoleHolders(in String roleName, in IRoleManagerCallback callback);
+
+    void onGrantDefaultRoles(in IRoleManagerCallback callback);
 }
diff --git a/core/java/android/rolecontrollerservice/RoleControllerService.java b/core/java/android/rolecontrollerservice/RoleControllerService.java
index da11bca..44c45bb 100644
--- a/core/java/android/rolecontrollerservice/RoleControllerService.java
+++ b/core/java/android/rolecontrollerservice/RoleControllerService.java
@@ -89,6 +89,13 @@
                 RoleControllerService.this.onClearRoleHolders(roleName,
                         new RoleManagerCallbackDelegate(callback));
             }
+
+            @Override
+            public void onGrantDefaultRoles(IRoleManagerCallback callback) {
+                Preconditions.checkNotNull(callback, "callback cannot be null");
+                RoleControllerService.this.onGrantDefaultRoles(
+                        new RoleManagerCallbackDelegate(callback));
+            }
         };
     }
 
@@ -133,6 +140,16 @@
     public abstract void onClearRoleHolders(@NonNull String roleName,
             @NonNull RoleManagerCallback callback);
 
+    /**
+     * Called by system to grant default permissions and roles.
+     * <p>
+     * This is typically when creating a new user or upgrading either system or
+     * permission controller package
+     *
+     * @param callback the callback for whether this call is successful
+     */
+    public abstract void onGrantDefaultRoles(@NonNull RoleManagerCallback callback);
+
     private static class RoleManagerCallbackDelegate implements RoleManagerCallback {
 
         private IRoleManagerCallback mCallback;
diff --git a/core/java/android/security/keymaster/ExportResult.java b/core/java/android/security/keymaster/ExportResult.java
index c104671..1ab79fb 100644
--- a/core/java/android/security/keymaster/ExportResult.java
+++ b/core/java/android/security/keymaster/ExportResult.java
@@ -28,6 +28,11 @@
     public final int resultCode;
     public final byte[] exportData;
 
+    public ExportResult(int resultCode) {
+        this.resultCode = resultCode;
+        this.exportData = new byte[0];
+    }
+
     @UnsupportedAppUsage
     public static final Parcelable.Creator<ExportResult> CREATOR = new
             Parcelable.Creator<ExportResult>() {
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java
index 555863e..a4fe75d 100644
--- a/core/java/android/security/keymaster/KeyCharacteristics.java
+++ b/core/java/android/security/keymaster/KeyCharacteristics.java
@@ -52,6 +52,14 @@
         readFromParcel(in);
     }
 
+    /**
+     * Makes a shallow copy of other by copying the other's references to the KeymasterArguments
+     */
+    public void shallowCopyFrom(KeyCharacteristics other) {
+        this.swEnforced = other.swEnforced;
+        this.hwEnforced = other.hwEnforced;
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/core/java/android/security/keymaster/KeymasterCertificateChain.java b/core/java/android/security/keymaster/KeymasterCertificateChain.java
index 243b9fe..00a1a1c 100644
--- a/core/java/android/security/keymaster/KeymasterCertificateChain.java
+++ b/core/java/android/security/keymaster/KeymasterCertificateChain.java
@@ -54,6 +54,14 @@
         readFromParcel(in);
     }
 
+    /**
+     * Makes a shallow copy of other by copying the reference to the certificate chain list.
+     * @param other
+     */
+    public void shallowCopyFrom(KeymasterCertificateChain other) {
+        this.mCertificates = other.mCertificates;
+    }
+
     public List<byte[]> getCertificates() {
         return mCertificates;
     }
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index f4dcce1..15ded8d 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -154,7 +154,7 @@
 
     // User authenticators.
     public static final int HW_AUTH_PASSWORD = 1 << 0;
-    public static final int HW_AUTH_FINGERPRINT = 1 << 1;
+    public static final int HW_AUTH_BIOMETRIC = 1 << 1;
 
     // Error codes.
     public static final int KM_ERROR_OK = 0;
diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java
index 2943211..bc4f360 100644
--- a/core/java/android/security/keymaster/OperationResult.java
+++ b/core/java/android/security/keymaster/OperationResult.java
@@ -59,6 +59,10 @@
         this.outParams = outParams;
     }
 
+    public OperationResult(int resultCode) {
+        this(resultCode, null, 0, 0, null, null);
+    }
+
     protected OperationResult(Parcel in) {
         resultCode = in.readInt();
         token = in.readStrongBinder();
diff --git a/core/java/android/service/carrier/ApnService.java b/core/java/android/service/carrier/ApnService.java
new file mode 100644
index 0000000..d53eb37
--- /dev/null
+++ b/core/java/android/service/carrier/ApnService.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2018 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.service.carrier;
+
+import android.annotation.SystemApi;
+import android.annotation.WorkerThread;
+import android.app.Service;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.os.IBinder;
+import android.util.Log;
+
+import com.android.internal.telephony.IApnSourceService;
+
+import java.util.List;
+
+/**
+ * A service that the system can call to restore default APNs.
+ * <p>
+ * To extend this class, specify the full name of your implementation in the resource file
+ * {@code packages/providers/TelephonyProvider/res/values/config.xml} as the
+ * {@code apn_source_service}.
+ * </p>
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class ApnService extends Service {
+
+    private static final String LOG_TAG = "ApnService";
+
+    private final IApnSourceService.Stub mBinder = new IApnSourceService.Stub() {
+        /**
+         * Retreive APNs for the default slot index.
+         */
+        @Override
+        public ContentValues[] getApns(int subId) {
+            try {
+                List<ContentValues> apns = ApnService.this.onRestoreApns(subId);
+                return apns.toArray(new ContentValues[apns.size()]);
+            } catch (Exception e) {
+                Log.e(LOG_TAG, "Error in getApns for subId=" + subId + ": " + e.getMessage(), e);
+                return null;
+            }
+        }
+    };
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    /**
+     * Override this method to restore default user APNs with a carrier service instead of the
+     * built in platform xml APNs list.
+     * <p>
+     * This method is called by the TelephonyProvider when the user requests restoring the default
+     * APNs. It should return a list of ContentValues representing the default APNs for the given
+     * subId.
+     */
+    @WorkerThread
+    public abstract List<ContentValues> onRestoreApns(int subId);
+}
diff --git a/core/java/android/service/intelligence/IIntelligenceService.aidl b/core/java/android/service/intelligence/IIntelligenceService.aidl
new file mode 100644
index 0000000..bacad8b
--- /dev/null
+++ b/core/java/android/service/intelligence/IIntelligenceService.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 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.service.intelligence;
+
+import android.service.intelligence.InteractionSessionId;
+import android.service.intelligence.InteractionContext;
+
+import android.view.intelligence.ContentCaptureEvent;
+
+import java.util.List;
+
+
+/**
+ * Interface from the system to an intelligence service.
+ *
+ * @hide
+ */
+oneway interface IIntelligenceService {
+
+    // Called when session is created (context not null) or destroyed (context null)
+    void onSessionLifecycle(in InteractionContext context, in InteractionSessionId sessionId);
+
+    void onContentCaptureEvents(in InteractionSessionId sessionId,
+                                in List<ContentCaptureEvent> events);
+}
diff --git a/core/java/android/service/intelligence/IntelligenceService.java b/core/java/android/service/intelligence/IntelligenceService.java
index 4b8825d..a2b60f0 100644
--- a/core/java/android/service/intelligence/IntelligenceService.java
+++ b/core/java/android/service/intelligence/IntelligenceService.java
@@ -15,16 +15,24 @@
  */
 package android.service.intelligence;
 
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.CallSuper;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.app.Service;
 import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
 import android.view.intelligence.ContentCaptureEvent;
 
 import java.util.List;
 
 /**
- * A service used to captures the content of the screen.
+ * A service used to capture the content of the screen.
  *
  * <p>The data collected by this service can be analyzed and combined with other sources to provide
  * contextual data in other areas of the system such as Autofill.
@@ -34,6 +42,8 @@
 @SystemApi
 public abstract class IntelligenceService extends Service {
 
+    private static final String TAG = "IntelligenceService";
+
     /**
      * The {@link Intent} that must be declared as handled by the service.
      * To be supported, the service must also require the
@@ -43,6 +53,50 @@
     public static final String SERVICE_INTERFACE =
             "android.service.intelligence.IntelligenceService";
 
+    private Handler mHandler;
+
+    private final IIntelligenceService mInterface = new IIntelligenceService.Stub() {
+
+        @Override
+        public void onSessionLifecycle(InteractionContext context, InteractionSessionId sessionId)
+                throws RemoteException {
+            if (context != null) {
+                mHandler.sendMessage(
+                        obtainMessage(IntelligenceService::onCreateInteractionSession,
+                                IntelligenceService.this, context, sessionId));
+            } else {
+                mHandler.sendMessage(
+                        obtainMessage(IntelligenceService::onDestroyInteractionSession,
+                                IntelligenceService.this, sessionId));
+            }
+        }
+        @Override
+        public void onContentCaptureEvents(InteractionSessionId sessionId,
+                List<ContentCaptureEvent> events) {
+            mHandler.sendMessage(
+                    obtainMessage(IntelligenceService::onContentCaptureEvent,
+                            IntelligenceService.this, sessionId, events));
+
+        }
+    };
+
+    @CallSuper
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mHandler = new Handler(Looper.getMainLooper(), null, true);
+    }
+
+    /** @hide */
+    @Override
+    public final IBinder onBind(Intent intent) {
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
+            return mInterface.asBinder();
+        }
+        Log.w(TAG, "Tried to bind to wrong intent: " + intent);
+        return null;
+    }
+
     /**
      * Creates a new interaction session.
      *
@@ -59,11 +113,12 @@
      * @param sessionId the session's Id
      * @param events the events
      */
+     // TODO(b/111276913): rename to onContentCaptureEvents
     public abstract void onContentCaptureEvent(@NonNull InteractionSessionId sessionId,
             @NonNull List<ContentCaptureEvent> events);
 
     /**
-     * Destroys the content capture session identified by the specified {@code sessionId}.
+     * Destroys the interaction session.
      *
      * @param sessionId the id of the session to destroy
      */
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/core/java/android/service/intelligence/InteractionContext.aidl
similarity index 71%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to core/java/android/service/intelligence/InteractionContext.aidl
index ede8695..4ce6aa4 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/core/java/android/service/intelligence/InteractionContext.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
+/**
+ * Copyright (c) 2018, 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
+ *     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,
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package android.service.intelligence;
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+parcelable InteractionContext;
diff --git a/core/java/android/service/intelligence/InteractionContext.java b/core/java/android/service/intelligence/InteractionContext.java
index 4d83820..c1803ad 100644
--- a/core/java/android/service/intelligence/InteractionContext.java
+++ b/core/java/android/service/intelligence/InteractionContext.java
@@ -23,6 +23,9 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.util.Preconditions;
+
+import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -32,7 +35,7 @@
 public final class InteractionContext implements Parcelable {
 
     /**
-     * Flag used to indicate that the app explicitly disabled contents capture for the activity
+     * Flag used to indicate that the app explicitly disabled content capture for the activity
      * (using
      * {@link android.view.intelligence.IntelligenceManager#disableContentCapture()}),
      * in which case the service will just receive activity-level events.
@@ -54,24 +57,34 @@
     @Retention(RetentionPolicy.SOURCE)
     @interface ContextCreationFlags{}
 
+    // TODO(b/111276913): create new object for taskId + componentName / reuse on other places
+    private final @NonNull ComponentName mComponentName;
+    private final int mTaskId;
+    private final int mDisplayId;
+    private final int mFlags;
+
+
     /** @hide */
-    InteractionContext() {
+    public InteractionContext(@NonNull ComponentName componentName, int taskId, int displayId,
+            int flags) {
+        mComponentName = Preconditions.checkNotNull(componentName);
+        mTaskId = taskId;
+        mDisplayId = displayId;
+        mFlags = flags;
     }
 
     /**
      * Gets the id of the {@link TaskInfo task} associated with this context.
      */
     public int getTaskId() {
-        //TODO(b/111276913): implement
-        return 108;
+        return mTaskId;
     }
 
     /**
      * Gets the activity associated with this context.
      */
     public @NonNull ComponentName getActivityComponent() {
-        //TODO(b/111276913): implement
-        return null;
+        return mComponentName;
     }
 
     /**
@@ -79,8 +92,7 @@
      * {G android.hardware.display.DisplayManager#getDisplay(int) DisplayManager.getDisplay()}.
      */
     public int getDisplayId() {
-        //TODO(b/111276913): implement
-        return 42;
+        return mDisplayId;
     }
 
     /**
@@ -90,8 +102,26 @@
      * {@link #FLAG_DISABLED_BY_APP}.
      */
     public @ContextCreationFlags int getFlags() {
-        //TODO(b/111276913): implement
-        return 42;
+        return mFlags;
+    }
+
+    /**
+     * @hide
+     */
+    // TODO(b/111276913): dump to proto as well
+    public void dump(PrintWriter pw) {
+        pw.print("comp="); pw.print(mComponentName.flattenToShortString());
+        pw.print(", taskId="); pw.print(mTaskId);
+        pw.print(", displayId="); pw.print(mDisplayId);
+        if (mFlags > 0) {
+            pw.print(", flags="); pw.print(mFlags);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "Context[act=" + mComponentName.flattenToShortString() + ", taskId=" + mTaskId
+                + ", displayId=" + mDisplayId + ", flags=" + mFlags + "]";
     }
 
     @Override
@@ -101,6 +131,10 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeParcelable(mComponentName, flags);
+        parcel.writeInt(mTaskId);
+        parcel.writeInt(mDisplayId);
+        parcel.writeInt(mFlags);
     }
 
     public static final Parcelable.Creator<InteractionContext> CREATOR =
@@ -108,8 +142,11 @@
 
         @Override
         public InteractionContext createFromParcel(Parcel parcel) {
-            // TODO(b/111276913): implement
-            return null;
+            final ComponentName componentName = parcel.readParcelable(null);
+            final int taskId = parcel.readInt();
+            final int displayId = parcel.readInt();
+            final int flags = parcel.readInt();
+            return new InteractionContext(componentName, taskId, displayId, flags);
         }
 
         @Override
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/core/java/android/service/intelligence/InteractionSessionId.aidl
similarity index 71%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to core/java/android/service/intelligence/InteractionSessionId.aidl
index ede8695..a5392b6 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/core/java/android/service/intelligence/InteractionSessionId.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
+/**
+ * Copyright (c) 2018, 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
+ *     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,
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package android.service.intelligence;
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+parcelable InteractionSessionId;
diff --git a/core/java/android/service/intelligence/InteractionSessionId.java b/core/java/android/service/intelligence/InteractionSessionId.java
index 4c9d706..667193b 100644
--- a/core/java/android/service/intelligence/InteractionSessionId.java
+++ b/core/java/android/service/intelligence/InteractionSessionId.java
@@ -16,17 +16,85 @@
 
 package android.service.intelligence;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.io.PrintWriter;
+import java.util.UUID;
+
 // TODO(b/111276913): add javadocs / implement equals/hashcode/string
 /** @hide */
 @SystemApi
 public final class InteractionSessionId implements Parcelable {
 
-    /** @hide */
+    private final @NonNull String mValue;
+
+    /**
+     * Creates a new instance.
+     *
+     * @hide
+     */
     public InteractionSessionId() {
+        this(UUID.randomUUID().toString());
+    }
+
+    /**
+     * Creates a new instance.
+     *
+     * @param value The internal value.
+     *
+     * @hide
+     */
+    public InteractionSessionId(@NonNull String value) {
+        mValue = value;
+    }
+
+    /**
+     * @hide
+     */
+    public String getValue() {
+        return mValue;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((mValue == null) ? 0 : mValue.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        final InteractionSessionId other = (InteractionSessionId) obj;
+        if (mValue == null) {
+            if (other.mValue != null) return false;
+        } else if (!mValue.equals(other.mValue)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p><b>NOTE: </b>this method is only useful for debugging purposes and is not guaranteed to
+     * be stable, hence it should not be used to identify the session.
+     */
+    @Override
+    public String toString() {
+        return mValue;
+    }
+
+    /** @hide */
+    // TODO(b/111276913): dump to proto as well
+    public void dump(PrintWriter pw) {
+        pw.print(mValue);
     }
 
     @Override
@@ -36,6 +104,7 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mValue);
     }
 
     public static final Parcelable.Creator<InteractionSessionId> CREATOR =
@@ -43,8 +112,7 @@
 
         @Override
         public InteractionSessionId createFromParcel(Parcel parcel) {
-            // TODO(b/111276913): implement
-            return null;
+            return new InteractionSessionId(parcel.readString());
         }
 
         @Override
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index b8e0387..64eae0c 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1461,6 +1461,8 @@
         private boolean mShowBadge;
         private @UserSentiment int mUserSentiment = USER_SENTIMENT_NEUTRAL;
         private boolean mHidden;
+        private boolean mAudiblyAlerted;
+        private boolean mNoisy;
         private ArrayList<Notification.Action> mSmartActions;
         private ArrayList<CharSequence> mSmartReplies;
 
@@ -1627,6 +1629,20 @@
         }
 
         /**
+         * Returns whether this notification alerted the user via sound or vibration.
+         *
+         * @return true if the notification alerted the user, false otherwise.
+         */
+        public boolean audiblyAlerted() {
+            return mAudiblyAlerted;
+        }
+
+        /** @hide */
+        public boolean isNoisy() {
+            return mNoisy;
+        }
+
+        /**
          * @hide
          */
         @VisibleForTesting
@@ -1635,7 +1651,8 @@
                 CharSequence explanation, String overrideGroupKey,
                 NotificationChannel channel, ArrayList<String> overridePeople,
                 ArrayList<SnoozeCriterion> snoozeCriteria, boolean showBadge,
-                int userSentiment, boolean hidden, ArrayList<Notification.Action> smartActions,
+                int userSentiment, boolean hidden, boolean audiblyAlerted,
+                boolean noisy, ArrayList<Notification.Action> smartActions,
                 ArrayList<CharSequence> smartReplies) {
             mKey = key;
             mRank = rank;
@@ -1652,6 +1669,8 @@
             mShowBadge = showBadge;
             mUserSentiment = userSentiment;
             mHidden = hidden;
+            mAudiblyAlerted = audiblyAlerted;
+            mNoisy = noisy;
             mSmartActions = smartActions;
             mSmartReplies = smartReplies;
         }
@@ -1703,6 +1722,8 @@
         private ArrayMap<String, Boolean> mShowBadge;
         private ArrayMap<String, Integer> mUserSentiment;
         private ArrayMap<String, Boolean> mHidden;
+        private ArrayMap<String, Boolean> mAudiblyAlerted;
+        private ArrayMap<String, Boolean> mNoisy;
         private ArrayMap<String, ArrayList<Notification.Action>> mSmartActions;
         private ArrayMap<String, ArrayList<CharSequence>> mSmartReplies;
 
@@ -1733,7 +1754,8 @@
                     getVisibilityOverride(key), getSuppressedVisualEffects(key),
                     getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key),
                     getChannel(key), getOverridePeople(key), getSnoozeCriteria(key),
-                    getShowBadge(key), getUserSentiment(key), getHidden(key), getSmartActions(key),
+                    getShowBadge(key), getUserSentiment(key), getHidden(key),
+                    getAudiblyAlerted(key), getNoisy(key), getSmartActions(key),
                     getSmartReplies(key));
             return rank >= 0;
         }
@@ -1872,6 +1894,26 @@
             return hidden == null ? false : hidden.booleanValue();
         }
 
+        private boolean getAudiblyAlerted(String key) {
+            synchronized (this) {
+                if (mAudiblyAlerted == null) {
+                    buildAudiblyAlertedLocked();
+                }
+            }
+            Boolean audiblyAlerted = mAudiblyAlerted.get(key);
+            return audiblyAlerted == null ? false : audiblyAlerted.booleanValue();
+        }
+
+        private boolean getNoisy(String key) {
+            synchronized (this) {
+                if (mNoisy == null) {
+                    buildNoisyLocked();
+                }
+            }
+            Boolean noisy = mNoisy.get(key);
+            return noisy == null ? false : noisy.booleanValue();
+        }
+
         private ArrayList<Notification.Action> getSmartActions(String key) {
             synchronized (this) {
                 if (mSmartActions == null) {
@@ -2007,6 +2049,16 @@
         }
 
         // Locked by 'this'
+        private void buildAudiblyAlertedLocked() {
+            mAudiblyAlerted = buildBooleanMapFromBundle(mRankingUpdate.getAudiblyAlerted());
+        }
+
+        // Locked by 'this'
+        private void buildNoisyLocked() {
+            mNoisy = buildBooleanMapFromBundle(mRankingUpdate.getNoisy());
+        }
+
+        // Locked by 'this'
         private void buildSmartActions() {
             Bundle smartActions = mRankingUpdate.getSmartActions();
             mSmartActions = new ArrayMap<>(smartActions.size());
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index c67fad0..f80df93 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -39,13 +39,15 @@
     private final Bundle mHidden;
     private final Bundle mSmartActions;
     private final Bundle mSmartReplies;
+    private final Bundle mAudiblyAlerted;
+    private final Bundle mNoisy;
 
     public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
             Bundle visibilityOverrides, Bundle suppressedVisualEffects,
             int[] importance, Bundle explanation, Bundle overrideGroupKeys,
             Bundle channels, Bundle overridePeople, Bundle snoozeCriteria,
             Bundle showBadge, Bundle userSentiment, Bundle hidden, Bundle smartActions,
-            Bundle smartReplies) {
+            Bundle smartReplies, Bundle audiblyAlerted, Bundle noisy) {
         mKeys = keys;
         mInterceptedKeys = interceptedKeys;
         mVisibilityOverrides = visibilityOverrides;
@@ -61,6 +63,8 @@
         mHidden = hidden;
         mSmartActions = smartActions;
         mSmartReplies = smartReplies;
+        mAudiblyAlerted = audiblyAlerted;
+        mNoisy = noisy;
     }
 
     public NotificationRankingUpdate(Parcel in) {
@@ -80,6 +84,8 @@
         mHidden = in.readBundle();
         mSmartActions = in.readBundle();
         mSmartReplies = in.readBundle();
+        mAudiblyAlerted = in.readBundle();
+        mNoisy = in.readBundle();
     }
 
     @Override
@@ -104,6 +110,8 @@
         out.writeBundle(mHidden);
         out.writeBundle(mSmartActions);
         out.writeBundle(mSmartReplies);
+        out.writeBundle(mAudiblyAlerted);
+        out.writeBundle(mNoisy);
     }
 
     public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -176,4 +184,12 @@
     public Bundle getSmartReplies() {
         return mSmartReplies;
     }
+
+    public Bundle getAudiblyAlerted() {
+        return mAudiblyAlerted;
+    }
+
+    public Bundle getNoisy() {
+        return mNoisy;
+    }
 }
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index e5fd292..2d5f3bf 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1270,7 +1270,13 @@
      */
     public float getLineLeft(int line) {
         final int dir = getParagraphDirection(line);
-        final Alignment align = getParagraphAlignment(line);
+        Alignment align = getParagraphAlignment(line);
+        // Before Q, StaticLayout.Builder.setAlignment didn't check whether the input alignment
+        // is null. And when it is null, the old behavior is the same as ALIGN_CENTER.
+        // To keep consistency, we convert a null alignment to ALIGN_CENTER.
+        if (align == null) {
+            align = Alignment.ALIGN_CENTER;
+        }
 
         // First convert combinations of alignment and direction settings to
         // three basic cases: ALIGN_LEFT, ALIGN_RIGHT and ALIGN_CENTER.
@@ -1319,7 +1325,13 @@
      */
     public float getLineRight(int line) {
         final int dir = getParagraphDirection(line);
-        final Alignment align = getParagraphAlignment(line);
+        Alignment align = getParagraphAlignment(line);
+        // Before Q, StaticLayout.Builder.setAlignment didn't check whether the input alignment
+        // is null. And when it is null, the old behavior is the same as ALIGN_CENTER.
+        // To keep consistency, we convert a null alignment to ALIGN_CENTER.
+        if (align == null) {
+            align = Alignment.ALIGN_CENTER;
+        }
 
         final Alignment resultAlign;
         switch(align) {
@@ -2360,6 +2372,52 @@
         public Directions(int[] dirs) {
             mDirections = dirs;
         }
+
+        /**
+         * Returns number of BiDi runs.
+         *
+         * @hide
+         */
+        public @IntRange(from = 0) int getRunCount() {
+            return mDirections.length / 2;
+        }
+
+        /**
+         * Returns the start offset of the BiDi run.
+         *
+         * @param runIndex the index of the BiDi run
+         * @return the start offset of the BiDi run.
+         * @hide
+         */
+        public @IntRange(from = 0) int getRunStart(@IntRange(from = 0) int runIndex) {
+            return mDirections[runIndex * 2];
+        }
+
+        /**
+         * Returns the length of the BiDi run.
+         *
+         * Note that this method may return too large number due to reducing the number of object
+         * allocations. The too large number means the remaining part is assigned to this run. The
+         * caller must clamp the returned value.
+         *
+         * @param runIndex the index of the BiDi run
+         * @return the length of the BiDi run.
+         * @hide
+         */
+        public @IntRange(from = 0) int getRunLength(@IntRange(from = 0) int runIndex) {
+            return mDirections[runIndex * 2 + 1] & RUN_LENGTH_MASK;
+        }
+
+        /**
+         * Returns true if the BiDi run is RTL.
+         *
+         * @param runIndex the index of the BiDi run
+         * @return true if the BiDi run is RTL.
+         * @hide
+         */
+        public boolean isRunRtl(int runIndex) {
+            return (mDirections[runIndex * 2 + 1] & RUN_RTL_FLAG) != 0;
+        }
     }
 
     /**
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 44dfd11..6eb433a 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
@@ -51,6 +52,8 @@
 public class TextLine {
     private static final boolean DEBUG = false;
 
+    private static final char TAB_CHAR = '\t';
+
     private TextPaint mPaint;
     @UnsupportedAppUsage
     private CharSequence mText;
@@ -198,7 +201,7 @@
             }
         }
 
-        mCharsValid = hasReplacement || hasTabs || directions != Layout.DIRS_ALL_LEFT_TO_RIGHT;
+        mCharsValid = hasReplacement;
 
         if (mCharsValid) {
             if (mChars == null || mChars.length < mLen) {
@@ -232,6 +235,10 @@
         mEllipsisEnd = ellipsisStart != ellipsisEnd ? ellipsisEnd : 0;
     }
 
+    private char charAt(int i) {
+        return mCharsValid ? mChars[i] : mText.charAt(i + mStart);
+    }
+
     /**
      * Justify the line to the given width.
      */
@@ -261,51 +268,23 @@
      * @param bottom the bottom of the line
      */
     void draw(Canvas c, float x, int top, int y, int bottom) {
-        if (!mHasTabs) {
-            if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) {
-                drawRun(c, 0, mLen, false, x, top, y, bottom, false);
-                return;
-            }
-            if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) {
-                drawRun(c, 0, mLen, true, x, top, y, bottom, false);
-                return;
-            }
-        }
-
         float h = 0;
-        int[] runs = mDirections.mDirections;
+        final int runCount = mDirections.getRunCount();
+        for (int runIndex = 0; runIndex < runCount; runIndex++) {
+            final int runStart = mDirections.getRunStart(runIndex);
+            final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen);
+            final boolean runIsRtl = mDirections.isRunRtl(runIndex);
 
-        int lastRunIndex = runs.length - 2;
-        for (int i = 0; i < runs.length; i += 2) {
-            int runStart = runs[i];
-            int runLimit = runStart + (runs[i+1] & Layout.RUN_LENGTH_MASK);
-            if (runLimit > mLen) {
-                runLimit = mLen;
-            }
-            boolean runIsRtl = (runs[i+1] & Layout.RUN_RTL_FLAG) != 0;
-
-            int segstart = runStart;
+            int segStart = runStart;
             for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) {
-                int codept = 0;
-                if (mHasTabs && j < runLimit) {
-                    codept = mChars[j];
-                    if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) {
-                        codept = Character.codePointAt(mChars, j);
-                        if (codept > 0xFFFF) {
-                            ++j;
-                            continue;
-                        }
-                    }
-                }
+                if (j == runLimit || charAt(j) == TAB_CHAR) {
+                    h += drawRun(c, segStart, j, runIsRtl, x + h, top, y, bottom,
+                            runIndex != (runCount - 1) || j != mLen);
 
-                if (j == runLimit || codept == '\t') {
-                    h += drawRun(c, segstart, j, runIsRtl, x+h, top, y, bottom,
-                            i != lastRunIndex || j != mLen);
-
-                    if (codept == '\t') {
+                    if (j != runLimit) {  // charAt(j) == TAB_CHAR
                         h = mDir * nextTab(h * mDir);
                     }
-                    segstart = j + 1;
+                    segStart = j + 1;
                 }
             }
         }
@@ -323,75 +302,81 @@
     }
 
     /**
-     * Returns information about a position on the line.
+     * Returns the signed graphical offset from the leading margin.
      *
-     * @param offset the line-relative character offset, between 0 and the
-     * line length, inclusive
-     * @param trailing true to measure the trailing edge of the character
-     * before offset, false to measure the leading edge of the character
-     * at offset.
-     * @param fmi receives metrics information about the requested
-     * character, can be null.
-     * @return the signed offset from the leading margin to the requested
-     * character edge.
+     * Following examples are all for measuring offset=3. LX(e.g. L0, L1, ...) denotes a
+     * character which has LTR BiDi property. On the other hand, RX(e.g. R0, R1, ...) denotes a
+     * character which has RTL BiDi property. Assuming all character has 1em width.
+     *
+     * Example 1: All LTR chars within LTR context
+     *   Input Text (logical)  :   L0 L1 L2 L3 L4 L5 L6 L7 L8
+     *   Input Text (visual)   :   L0 L1 L2 L3 L4 L5 L6 L7 L8
+     *   Output(trailing=true) :  |--------| (Returns 3em)
+     *   Output(trailing=false):  |--------| (Returns 3em)
+     *
+     * Example 2: All RTL chars within RTL context.
+     *   Input Text (logical)  :   R0 R1 R2 R3 R4 R5 R6 R7 R8
+     *   Input Text (visual)   :   R8 R7 R6 R5 R4 R3 R2 R1 R0
+     *   Output(trailing=true) :                    |--------| (Returns -3em)
+     *   Output(trailing=false):                    |--------| (Returns -3em)
+     *
+     * Example 3: BiDi chars within LTR context.
+     *   Input Text (logical)  :   L0 L1 L2 R3 R4 R5 L6 L7 L8
+     *   Input Text (visual)   :   L0 L1 L2 R5 R4 R3 L6 L7 L8
+     *   Output(trailing=true) :  |-----------------| (Returns 6em)
+     *   Output(trailing=false):  |--------| (Returns 3em)
+     *
+     * Example 4: BiDi chars within RTL context.
+     *   Input Text (logical)  :   L0 L1 L2 R3 R4 R5 L6 L7 L8
+     *   Input Text (visual)   :   L6 L7 L8 R5 R4 R3 L0 L1 L2
+     *   Output(trailing=true) :           |-----------------| (Returns -6em)
+     *   Output(trailing=false):                    |--------| (Returns -3em)
+     *
+     * @param offset the line-relative character offset, between 0 and the line length, inclusive
+     * @param trailing no effect if the offset is not on the BiDi transition offset. If the offset
+     *                 is on the BiDi transition offset and true is passed, the offset is regarded
+     *                 as the edge of the trailing run's edge. If false, the offset is regarded as
+     *                 the edge of the preceding run's edge. See example above.
+     * @param fmi receives metrics information about the requested character, can be null
+     * @return the signed graphical offset from the leading margin to the requested character edge.
+     *         The positive value means the offset is right from the leading edge. The negative
+     *         value means the offset is left from the leading edge.
      */
-    public float measure(int offset, boolean trailing, FontMetricsInt fmi) {
-        int target = trailing ? offset - 1 : offset;
+    public float measure(@IntRange(from = 0) int offset, boolean trailing,
+            @NonNull FontMetricsInt fmi) {
+        if (offset > mLen) {
+            throw new IndexOutOfBoundsException(
+                    "offset(" + offset + ") should be less than line limit(" + mLen + ")");
+        }
+        final int target = trailing ? offset - 1 : offset;
         if (target < 0) {
             return 0;
         }
 
         float h = 0;
+        for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) {
+            final int runStart = mDirections.getRunStart(runIndex);
+            final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen);
+            final boolean runIsRtl = mDirections.isRunRtl(runIndex);
 
-        if (!mHasTabs) {
-            if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) {
-                return measureRun(0, offset, mLen, false, fmi);
-            }
-            if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) {
-                return measureRun(0, offset, mLen, true, fmi);
-            }
-        }
-
-        char[] chars = mChars;
-        int[] runs = mDirections.mDirections;
-        for (int i = 0; i < runs.length; i += 2) {
-            int runStart = runs[i];
-            int runLimit = runStart + (runs[i+1] & Layout.RUN_LENGTH_MASK);
-            if (runLimit > mLen) {
-                runLimit = mLen;
-            }
-            boolean runIsRtl = (runs[i+1] & Layout.RUN_RTL_FLAG) != 0;
-
-            int segstart = runStart;
+            int segStart = runStart;
             for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) {
-                int codept = 0;
-                if (mHasTabs && j < runLimit) {
-                    codept = chars[j];
-                    if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) {
-                        codept = Character.codePointAt(chars, j);
-                        if (codept > 0xFFFF) {
-                            ++j;
-                            continue;
-                        }
-                    }
-                }
+                if (j == runLimit || charAt(j) == TAB_CHAR) {
+                    final boolean targetIsInThisSegment = target >= segStart && target < j;
+                    final boolean sameDirection = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl;
 
-                if (j == runLimit || codept == '\t') {
-                    boolean inSegment = target >= segstart && target < j;
-
-                    boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl;
-                    if (inSegment && advance) {
-                        return h + measureRun(segstart, offset, j, runIsRtl, fmi);
+                    if (targetIsInThisSegment && sameDirection) {
+                        return h + measureRun(segStart, offset, j, runIsRtl, fmi);
                     }
 
-                    float w = measureRun(segstart, j, j, runIsRtl, fmi);
-                    h += advance ? w : -w;
+                    final float segmentWidth = measureRun(segStart, j, j, runIsRtl, fmi);
+                    h += sameDirection ? segmentWidth : -segmentWidth;
 
-                    if (inSegment) {
-                        return h + measureRun(segstart, offset, j, runIsRtl, null);
+                    if (targetIsInThisSegment) {
+                        return h + measureRun(segStart, offset, j, runIsRtl, null);
                     }
 
-                    if (codept == '\t') {
+                    if (j != runLimit) {  // charAt(j) == TAB_CHAR
                         if (offset == j) {
                             return h;
                         }
@@ -401,7 +386,7 @@
                         }
                     }
 
-                    segstart = j + 1;
+                    segStart = j + 1;
                 }
             }
         }
@@ -426,62 +411,29 @@
         }
 
         float h = 0;
+        for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) {
+            final int runStart = mDirections.getRunStart(runIndex);
+            final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen);
+            final boolean runIsRtl = mDirections.isRunRtl(runIndex);
 
-        if (!mHasTabs) {
-            if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) {
-                for (int offset = 0; offset <= mLen; ++offset) {
-                    measurement[offset] = measureRun(0, offset, mLen, false, fmi);
-                }
-                return measurement;
-            }
-            if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) {
-                for (int offset = 0; offset <= mLen; ++offset) {
-                    measurement[offset] = measureRun(0, offset, mLen, true, fmi);
-                }
-                return measurement;
-            }
-        }
-
-        char[] chars = mChars;
-        int[] runs = mDirections.mDirections;
-        for (int i = 0; i < runs.length; i += 2) {
-            int runStart = runs[i];
-            int runLimit = runStart + (runs[i + 1] & Layout.RUN_LENGTH_MASK);
-            if (runLimit > mLen) {
-                runLimit = mLen;
-            }
-            boolean runIsRtl = (runs[i + 1] & Layout.RUN_RTL_FLAG) != 0;
-
-            int segstart = runStart;
+            int segStart = runStart;
             for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; ++j) {
-                int codept = 0;
-                if (mHasTabs && j < runLimit) {
-                    codept = chars[j];
-                    if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) {
-                        codept = Character.codePointAt(chars, j);
-                        if (codept > 0xFFFF) {
-                            ++j;
-                            continue;
-                        }
-                    }
-                }
-
-                if (j == runLimit || codept == '\t') {
-                    float oldh = h;
-                    boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl;
-                    float w = measureRun(segstart, j, j, runIsRtl, fmi);
+                if (j == runLimit || charAt(j) == TAB_CHAR) {
+                    final  float oldh = h;
+                    final boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl;
+                    final float w = measureRun(segStart, j, j, runIsRtl, fmi);
                     h += advance ? w : -w;
 
-                    float baseh = advance ? oldh : h;
+                    final float baseh = advance ? oldh : h;
                     FontMetricsInt crtfmi = advance ? fmi : null;
-                    for (int offset = segstart; offset <= j && offset <= mLen; ++offset) {
-                        if (target[offset] >= segstart && target[offset] < j) {
+                    for (int offset = segStart; offset <= j && offset <= mLen; ++offset) {
+                        if (target[offset] >= segStart && target[offset] < j) {
                             measurement[offset] =
-                                    baseh + measureRun(segstart, offset, j, runIsRtl, crtfmi);
+                                    baseh + measureRun(segStart, offset, j, runIsRtl, crtfmi);
                         }
                     }
 
-                    if (codept == '\t') {
+                    if (j != runLimit) {  // charAt(j) == TAB_CHAR
                         if (target[j] == j) {
                             measurement[j] = h;
                         }
@@ -491,7 +443,7 @@
                         }
                     }
 
-                    segstart = j + 1;
+                    segStart = j + 1;
                 }
             }
         }
@@ -863,7 +815,6 @@
         } else {
             final int delta = mStart;
             if (mComputed == null) {
-                // TODO: Enable measured getRunAdvance for ReplacementSpan and RTL text.
                 return wp.getRunAdvance(mText, delta + start, delta + end,
                         delta + contextStart, delta + contextEnd, runIsRtl, delta + offset);
             } else {
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 2d67d79..bad26ed 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -36,21 +36,22 @@
     public static final String PERSIST_PREFIX = "persist." + FFLAG_OVERRIDE_PREFIX;
     public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
     public static final String EMERGENCY_DIAL_SHORTCUTS = "settings_emergency_dial_shortcuts";
+    public static final String SAFETY_HUB = "settings_safety_hub";
     public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
 
     private static final Map<String, String> DEFAULT_FLAGS;
     static {
         DEFAULT_FLAGS = new HashMap<>();
-        DEFAULT_FLAGS.put("settings_bluetooth_while_driving", "false");
         DEFAULT_FLAGS.put("settings_audio_switcher", "true");
         DEFAULT_FLAGS.put("settings_systemui_theme", "true");
-        DEFAULT_FLAGS.put("settings_dynamic_homepage", "false");
-        DEFAULT_FLAGS.put("settings_mobile_network_v2", "false");
+        DEFAULT_FLAGS.put("settings_dynamic_homepage", "true");
+        DEFAULT_FLAGS.put("settings_mobile_network_v2", "true");
         DEFAULT_FLAGS.put("settings_data_usage_v2", "false");
         DEFAULT_FLAGS.put("settings_seamless_transfer", "false");
         DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
         DEFAULT_FLAGS.put(EMERGENCY_DIAL_SHORTCUTS, "true");
         DEFAULT_FLAGS.put("settings_network_and_internet_v2", "false");
+        DEFAULT_FLAGS.put(SAFETY_HUB, "false");
         DEFAULT_FLAGS.put(SCREENRECORD_LONG_PRESS, "false");
     }
 
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index a872776..96ef8ba 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -21,6 +21,7 @@
 
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
+import android.graphics.FrameInfo;
 import android.hardware.display.DisplayManagerGlobal;
 import android.os.Build;
 import android.os.Handler;
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 719a401..4ead34e 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -218,6 +218,7 @@
      * @see #getFlags
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#shouldShowWithInsecureKeyguard
     public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
 
     /**
@@ -230,6 +231,7 @@
      * @see #supportsSystemDecorations
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors
     public static final int FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 6;
 
     /**
@@ -384,6 +386,7 @@
      *
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY
     public static final int REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY = 0;
     /**
      * Indicates that when display is removed, all its stacks and tasks will be removed, all
@@ -391,6 +394,7 @@
      *
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_DESTROY
     public static final int REMOVE_MODE_DESTROY_CONTENT = 1;
 
     /**
@@ -451,6 +455,19 @@
     }
 
     /**
+     * Gets the display unique id.
+     * <p>
+     * Unique id is different from display id because physical displays have stable unique id across
+     * reboots.
+     *
+     * @see com.android.service.display.DisplayDevice#hasStableUniqueId().
+     * @hide
+     */
+    public String getUniqueId() {
+        return mDisplayInfo.uniqueId;
+    }
+
+    /**
      * Returns true if this display is still valid, false if the display has been removed.
      *
      * If the display is invalid, then the methods of this class will
@@ -881,6 +898,7 @@
      * @see #REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY
      * @see #REMOVE_MODE_DESTROY_CONTENT
      */
+    // TODO (b/114338689): Remove the method and use IWindowManager#getRemoveContentMode
     public int getRemoveMode() {
         return mDisplayInfo.removeMode;
     }
@@ -891,6 +909,7 @@
      * @see #FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
      * @hide
      */
+    // TODO (b/114338689): Remove the method and use IWindowManager#shouldShowSystemDecors
     public boolean supportsSystemDecorations() {
         return (mDisplayInfo.flags & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0;
     }
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 34bcbdd..43de1f8 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -266,6 +266,7 @@
      *
      * @see Display#getRemoveMode()
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#getRemoveContentMode
     public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY;
 
     public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
new file mode 100644
index 0000000..03d9955
--- /dev/null
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.annotation.UnsupportedAppUsage;
+import android.graphics.BaseRecordingCanvas;
+import android.graphics.CanvasProperty;
+import android.graphics.Paint;
+import android.os.Build;
+
+/**
+ * This class exists temporarily to workaround broken apps
+ *
+ * b/119066174
+ *
+ * @hide
+ */
+public abstract class DisplayListCanvas extends BaseRecordingCanvas {
+
+    /** @hide */
+    protected DisplayListCanvas(long nativeCanvas) {
+        super(nativeCanvas);
+    }
+
+    /** @hide */
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    public abstract void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
+            CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
+            CanvasProperty<Float> ry, CanvasProperty<Paint> paint);
+
+    /** @hide */
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    public abstract void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
+            CanvasProperty<Float> radius, CanvasProperty<Paint> paint);
+}
diff --git a/core/java/android/view/FrameMetricsObserver.java b/core/java/android/view/FrameMetricsObserver.java
index 597089b..0f38e84 100644
--- a/core/java/android/view/FrameMetricsObserver.java
+++ b/core/java/android/view/FrameMetricsObserver.java
@@ -40,8 +40,9 @@
     @UnsupportedAppUsage
     private FrameMetrics mFrameMetrics;
 
-    /* package */ Window.OnFrameMetricsAvailableListener mListener;
-    /* package */ VirtualRefBasePtr mNative;
+    /* pacage */ Window.OnFrameMetricsAvailableListener mListener;
+    /** @hide */
+    public VirtualRefBasePtr mNative;
 
     /**
      * Creates a FrameMetricsObserver
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 07a57fb..4b8b7f3 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -58,10 +58,33 @@
     void dispatchGetNewSurface();
 
     /**
-     * Tell the window that it is either gaining or losing focus.  Keep it up
-     * to date on the current state showing navigational focus (touch mode) too.
+     * Tell the window that it is either gaining or losing focus.
+     *
+     * @param hasFocus       {@code true} if window has focus, {@code false} otherwise.
+     * @param inTouchMode    {@code true} if screen is in touch mode, {@code false} otherwise.
+     * @param reportToClient {@code true} when need to report to child view with
+     *                       {@link View#onWindowFocusChanged(boolean)}, {@code false} otherwise.
+     * <p>
+     * Note: In the previous design, there is only one window focus state tracked by
+     * WindowManagerService.
+     * For multi-display, the window focus state is tracked by each display independently.
+     * <p>
+     * It will introduce a problem if the window was already focused on one display and then
+     * switched to another display, since the window focus state on each display is independent,
+     * there is no global window focus state in WindowManagerService, so the window focus state of
+     * the former display remains unchanged.
+     * <p>
+     * When switched back to former display, some flows that rely on the global window focus state
+     * in view root will be missed due to the window focus state remaining unchanged.
+     * (i.e: Showing single IME window when switching between displays.)
+     * <p>
+     * To solve the problem, WindowManagerService tracks the top focused display change and then
+     * callbacks to the client via this method to make sure that the client side will request the
+     * IME on the top focused display, and then set {@param reportToClient} as {@code false} to
+     * ignore reporting to the application, since its focus remains unchanged on its display.
+     *
      */
-    void windowFocusChanged(boolean hasFocus, boolean inTouchMode);
+    void windowFocusChanged(boolean hasFocus, boolean inTouchMode, boolean reportToClient);
     
     void closeSystemDialogs(String reason);
     
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index f8bdfe2..c836c9e 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -111,9 +111,6 @@
     // caller must call setNewConfiguration() sometime later.
     Configuration updateOrientationFromAppTokens(in Configuration currentConfig,
             IBinder freezeThisOneIfNeeded, int displayId);
-    // Notify window manager of the new display override configuration. Returns an array of stack
-    // ids that were affected by the update, ActivityManager should resize these stacks.
-    int[] setNewDisplayOverrideConfiguration(in Configuration overrideConfig, int displayId);
 
     void startFreezingScreen(int exitAnim, int enterAnim);
     void stopFreezingScreen();
@@ -435,4 +432,120 @@
      * @param displayId The id of the display.
      */
     void dontOverrideDisplayInfo(int displayId);
+
+    /**
+     * Gets the windowing mode of the display.
+     *
+     * @param displayId The id of the display.
+     * @return {@link WindowConfiguration.WindowingMode}
+     */
+    int getWindowingMode(int displayId);
+
+    /**
+     * Sets the windowing mode of the display.
+     *
+     * @param displayId The id of the display.
+     * @param mode {@link WindowConfiguration.WindowingMode}
+     */
+    void setWindowingMode(int displayId, int mode);
+
+    /**
+     * Gets current remove content mode of the display.
+     * <p>
+     * What actions should be performed with the display's content when it is removed. Default
+     * behavior for public displays in this case is to move all activities to the primary display
+     * and make it focused. For private display is to destroy all activities.
+     * </p>
+     *
+     * @param displayId The id of the display.
+     * @return The remove content mode of the display.
+     * @see WindowManager#REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY
+     * @see WindowManager#REMOVE_CONTENT_MODE_DESTROY
+     */
+    int getRemoveContentMode(int displayId);
+
+    /**
+     * Sets the remove content mode of the display.
+     * <p>
+     * This mode indicates what actions should be performed with the display's content when it is
+     * removed.
+     * </p>
+     *
+     * @param displayId The id of the display.
+     * @param mode Remove content mode.
+     * @see WindowManager#REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY
+     * @see WindowManager#REMOVE_CONTENT_MODE_DESTROY
+     */
+    void setRemoveContentMode(int displayId, int mode);
+
+    /**
+     * Indicates that the display should show its content when non-secure keyguard is shown.
+     * <p>
+     * This flag identifies secondary displays that will continue showing content if keyguard can be
+     * dismissed without entering credentials.
+     * </p><p>
+     * An example of usage is a virtual display which content is displayed on external hardware
+     * display that is not visible to the system directly.
+     * </p>
+     *
+     * @param displayId The id of the display.
+     * @return {@code true} if the display should show its content when non-secure keyguard is
+     *         shown.
+     * @see KeyguardManager#isDeviceSecure()
+     * @see KeyguardManager#isDeviceLocked()
+     */
+    boolean shouldShowWithInsecureKeyguard(int displayId);
+
+    /**
+     * Sets that the display should show its content when non-secure keyguard is shown.
+     *
+     * @param displayId The id of the display.
+     * @param shouldShow Indicates that the display should show its content when non-secure keyguard
+     *                  is shown.
+     * @see KeyguardManager#isDeviceSecure()
+     * @see KeyguardManager#isDeviceLocked()
+     */
+    void setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow);
+
+    /**
+     * Indicates the display should show system decors.
+     * <p>
+     * System decors include status bar, navigation bar, launcher.
+     * </p>
+     *
+     * @param displayId The id of the display.
+     * @return {@code true} if the display should show system decors.
+     */
+    boolean shouldShowSystemDecors(int displayId);
+
+    /**
+     * Sets that the display should show system decors.
+     * <p>
+     * System decors include status bar, navigation bar, launcher.
+     * </p>
+     *
+     * @param displayId The id of the display.
+     * @param shouldShow Indicates that the display should show system decors.
+     */
+    void setShouldShowSystemDecors(int displayId, boolean shouldShow);
+
+    /**
+     * Indicates that the display should show IME.
+     *
+     * @param displayId The id of the display.
+     * @return {@code true} if the display should show IME.
+     * @see KeyguardManager#isDeviceSecure()
+     * @see KeyguardManager#isDeviceLocked()
+     */
+    boolean shouldShowIme(int displayId);
+
+    /**
+     * Sets that the display should show IME.
+     *
+     * @param displayId The id of the display.
+     * @param shouldShow Indicates that the display should show IME.
+     * @see KeyguardManager#isDeviceSecure()
+     * @see KeyguardManager#isDeviceLocked()
+     */
+    void setShouldShowIme(int displayId, boolean shouldShow);
 }
diff --git a/services/core/java/com/android/server/input/InputApplicationHandle.java b/core/java/android/view/InputApplicationHandle.java
similarity index 97%
rename from services/core/java/com/android/server/input/InputApplicationHandle.java
rename to core/java/android/view/InputApplicationHandle.java
index 3cf7edc..dc1e505 100644
--- a/services/core/java/com/android/server/input/InputApplicationHandle.java
+++ b/core/java/android/view/InputApplicationHandle.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.input;
+package android.view;
 
 /**
  * Functions as a handle for an application that can receive input.
diff --git a/core/java/android/view/InputChannel.java b/core/java/android/view/InputChannel.java
index b2dd6ac..84c8e7a 100644
--- a/core/java/android/view/InputChannel.java
+++ b/core/java/android/view/InputChannel.java
@@ -18,6 +18,7 @@
 
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
+import android.os.IBinder;
 import android.os.Parcelable;
 import android.util.Slog;
 
@@ -50,15 +51,17 @@
     @SuppressWarnings("unused")
     @UnsupportedAppUsage
     private long mPtr; // used by native code
-    
+
     private static native InputChannel[] nativeOpenInputChannelPair(String name);
-    
+
     private native void nativeDispose(boolean finalized);
     private native void nativeTransferTo(InputChannel other);
     private native void nativeReadFromParcel(Parcel parcel);
     private native void nativeWriteToParcel(Parcel parcel);
     private native void nativeDup(InputChannel target);
-    
+    private native IBinder nativeGetToken();
+    private native void nativeSetToken(IBinder token);
+
     private native String nativeGetName();
 
     /**
@@ -159,14 +162,22 @@
         }
         
         nativeWriteToParcel(out);
-        
+
         if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0) {
             dispose();
         }
     }
-    
+
     @Override
     public String toString() {
         return getName();
     }
+
+    public IBinder getToken() {
+        return nativeGetToken();
+    }
+
+    public void setToken(IBinder token) {
+        nativeSetToken(token);
+    }
 }
diff --git a/services/core/java/com/android/server/input/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
similarity index 93%
rename from services/core/java/com/android/server/input/InputWindowHandle.java
rename to core/java/android/view/InputWindowHandle.java
index bb29bf8..621ee89 100644
--- a/services/core/java/com/android/server/input/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.input;
+package android.view;
 
 import android.graphics.Region;
 import android.view.IWindow;
@@ -34,9 +34,6 @@
     // The input application handle.
     public final InputApplicationHandle inputApplicationHandle;
 
-    // The window manager's window state.
-    public final Object windowState;
-
     // The client window.
     public final IWindow clientWindow;
 
@@ -97,9 +94,8 @@
     private native void nativeDispose();
 
     public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
-            Object windowState, IWindow clientWindow, int displayId) {
+            IWindow clientWindow, int displayId) {
         this.inputApplicationHandle = inputApplicationHandle;
-        this.windowState = windowState;
         this.clientWindow = clientWindow;
         this.displayId = displayId;
     }
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 0a3403b..0739516 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -814,13 +814,19 @@
     public static final int KEYCODE_ALL_APPS = 284;
     /** Key code constant: Refresh key. */
     public static final int KEYCODE_REFRESH = 285;
+    /** Key code constant: Thumbs up key. Apps can use this to let user upvote content. */
+    public static final int KEYCODE_THUMBS_UP = 286;
+    /** Key code constant: Thumbs down key. Apps can use this to let user downvote content. */
+    public static final int KEYCODE_THUMBS_DOWN = 287;
+    /** Key code constant: Consumed by system to switch current viewer profile. */
+    public static final int KEYCODE_PROFILE_SWITCH = 288;
 
     /**
      * Integer value of the last KEYCODE. Increases as new keycodes are added to KeyEvent.
      * @hide
      */
     @TestApi
-    public static final int LAST_KEYCODE = KEYCODE_REFRESH;
+    public static final int LAST_KEYCODE = KEYCODE_PROFILE_SWITCH;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
@@ -1972,6 +1978,7 @@
     }
 
     /** @hide */
+    @TestApi
     @Override
     public final void setDisplayId(int displayId) {
         mDisplayId = displayId;
@@ -2036,6 +2043,16 @@
     }
 
     /**
+     * Modifies the flags of the event.
+     *
+     * @param newFlags New flags for the event, replacing the entire value.
+     * @hide
+     */
+    public final void setFlags(int newFlags) {
+        mFlags = newFlags;
+    }
+
+    /**
      * Returns the flags for this key event.
      *
      * @see #FLAG_WOKE_HERE
@@ -2523,10 +2540,11 @@
     }
 
     /**
-     * Retrieve the repeat count of the event.  For both key up and key down
-     * events, this is the number of times the key has repeated with the first
-     * down starting at 0 and counting up from there.  For multiple key
-     * events, this is the number of down/up pairs that have occurred.
+     * Retrieve the repeat count of the event.  For key down events,
+     * this is the number of times the key has repeated with the first
+     * down starting at 0 and counting up from there.  For key up events,
+     * this is always equal to zero. For multiple key events,
+     * this is the number of down/up pairs that have occurred.
      *
      * @return The number of times the key has repeated.
      */
@@ -2535,6 +2553,20 @@
     }
 
     /**
+     * Modifies the down time and the event time of the event.
+     *
+     * @param downTime The new down time (in {@link android.os.SystemClock#uptimeMillis}) of the
+     *                 event.
+     * @param eventTime The new event time (in {@link android.os.SystemClock#uptimeMillis}) of the
+     *                  event.
+     * @hide
+     */
+    public final void setTime(long downTime, long eventTime) {
+        mDownTime = downTime;
+        mEventTime = eventTime;
+    }
+
+    /**
      * Retrieve the time of the most recent key down event,
      * in the {@link android.os.SystemClock#uptimeMillis} time base.  If this
      * is a down event, this will be the same as {@link #getEventTime()}.
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 81da76d..4a5ccdf 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -61,6 +61,7 @@
     private View mCameraIcon;
     private View mMicIcon;
     private View mAppOps;
+    private View mAudiblyAlertedIcon;
     private int mIconColor;
     private int mOriginalNotificationColor;
     private boolean mExpanded;
@@ -121,6 +122,7 @@
         mMicIcon = findViewById(com.android.internal.R.id.mic);
         mOverlayIcon = findViewById(com.android.internal.R.id.overlay);
         mAppOps = findViewById(com.android.internal.R.id.app_ops);
+        mAudiblyAlertedIcon = findViewById(com.android.internal.R.id.alerted_icon);
     }
 
     @Override
@@ -337,6 +339,11 @@
                 ? View.VISIBLE : View.GONE);
     }
 
+    /** Updates icon visibility based on the noisiness of the notification. */
+    public void setAudiblyAlerted(boolean audiblyAlerted) {
+        mAudiblyAlertedIcon.setVisibility(audiblyAlerted ? View.VISIBLE : View.GONE);
+    }
+
     private void updateExpandButton() {
         int drawableId;
         int contentDescriptionId;
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 9d31bd1..78ad0da 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -293,6 +293,12 @@
         setTarget(canvas.mNode);
     }
 
+    /** @hide */
+    @UnsupportedAppUsage
+    public void setTarget(DisplayListCanvas canvas) {
+        setTarget((RecordingCanvas) canvas);
+    }
+
     private void setTarget(RenderNode node) {
         checkMutable();
         if (mTarget != null) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 0d33bbd..a7a5024 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -153,6 +153,9 @@
 
     private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);
 
+    private static native void nativeSetInputWindowInfo(long transactionObj, long nativeObject,
+            InputWindowHandle handle);
+
 
     private final CloseGuard mCloseGuard = CloseGuard.get();
     private final String mName;
@@ -572,6 +575,10 @@
      * Good practice is to first create the surface with the {@link #HIDDEN} flag
      * specified, open a transaction, set the surface layer, layer stack, alpha,
      * and position, call {@link #show} if appropriate, and close the transaction.
+     * <p>
+     * Bounds of the surface is determined by its crop and its buffer size. If the
+     * surface has no buffer or crop, the surface is boundless and only constrained
+     * by the size of its parent bounds.
      *
      * @param session The surface session, must not be null.
      * @param name The surface name, must not be null.
@@ -959,6 +966,14 @@
         }
     }
 
+    /**
+     * Bounds the surface and its children to the bounds specified. Size of the surface will be
+     * ignored and only the crop and buffer size will be used to determine the bounds of the
+     * surface. If no crop is specified and the surface has no buffer, the surface bounds is only
+     * constrained by the size of its parent bounds.
+     *
+     * @param crop Bounds of the crop to apply.
+     */
     public void setWindowCrop(Rect crop) {
         checkNotReleased();
         synchronized (SurfaceControl.class) {
@@ -966,6 +981,19 @@
         }
     }
 
+    /**
+     * Same as {@link SurfaceControl#setWindowCrop(Rect)} but sets the crop rect top left at 0, 0.
+     *
+     * @param width width of crop rect
+     * @param height height of crop rect
+     */
+    public void setWindowCrop(int width, int height) {
+        checkNotReleased();
+        synchronized (SurfaceControl.class) {
+            sGlobalTransaction.setWindowCrop(this, width, height);
+        }
+    }
+
     public void setLayerStack(int layerStack) {
         checkNotReleased();
         synchronized(SurfaceControl.class) {
@@ -1434,6 +1462,12 @@
             return this;
         }
 
+        public Transaction setInputWindowInfo(SurfaceControl sc, InputWindowHandle handle) {
+            sc.checkNotReleased();
+            nativeSetInputWindowInfo(mNativeObject, sc.mNativeObject, handle);
+            return this;
+        }
+
         @UnsupportedAppUsage
         public Transaction setMatrix(SurfaceControl sc,
                 float dsdx, float dtdx, float dtdy, float dsdy) {
@@ -1477,6 +1511,12 @@
             return this;
         }
 
+        public Transaction setWindowCrop(SurfaceControl sc, int width, int height) {
+            sc.checkNotReleased();
+            nativeSetWindowCrop(mNativeObject, sc.mNativeObject, 0, 0, width, height);
+            return this;
+        }
+
         @UnsupportedAppUsage
         public Transaction setLayerStack(SurfaceControl sc, int layerStack) {
             sc.checkNotReleased();
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 67f9399..2b68ec0 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -598,6 +598,7 @@
                         }
                         if (sizeChanged && !creating) {
                             mSurfaceControl.setSize(mSurfaceWidth, mSurfaceHeight);
+                            mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight);
                         }
                     } finally {
                         SurfaceControl.closeTransaction();
@@ -1169,6 +1170,12 @@
         }
 
         @Override
+        public void setWindowCrop(int width, int height) {
+            super.setWindowCrop(width, height);
+            mBackgroundControl.setWindowCrop(width, height);
+        }
+
+        @Override
         public void setLayerStack(int layerStack) {
             super.setLayerStack(layerStack);
             mBackgroundControl.setLayerStack(layerStack);
diff --git a/core/java/android/view/TextureLayer.java b/core/java/android/view/TextureLayer.java
index d89d634..46dd436 100644
--- a/core/java/android/view/TextureLayer.java
+++ b/core/java/android/view/TextureLayer.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.graphics.Bitmap;
+import android.graphics.HardwareRenderer;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.SurfaceTexture;
@@ -32,10 +33,10 @@
  * @hide
  */
 public final class TextureLayer {
-    private ThreadedRenderer mRenderer;
+    private HardwareRenderer mRenderer;
     private VirtualRefBasePtr mFinalizer;
 
-    private TextureLayer(ThreadedRenderer renderer, long deferredUpdater) {
+    private TextureLayer(HardwareRenderer renderer, long deferredUpdater) {
         if (renderer == null || deferredUpdater == 0) {
             throw new IllegalArgumentException("Either hardware renderer: " + renderer
                     + " or deferredUpdater: " + deferredUpdater + " is invalid");
@@ -139,7 +140,8 @@
         mRenderer.pushLayerUpdate(this);
     }
 
-    static TextureLayer adoptTextureLayer(ThreadedRenderer renderer, long layer) {
+    /** @hide */
+    public static TextureLayer adoptTextureLayer(HardwareRenderer renderer, long layer) {
         return new TextureLayer(renderer, layer);
     }
 
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index f0f4c1c..bf1a005 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -16,36 +16,24 @@
 
 package android.view;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.TypedArray;
-import android.graphics.Bitmap;
+import android.graphics.HardwareRenderer;
 import android.graphics.Point;
 import android.graphics.RecordingCanvas;
 import android.graphics.Rect;
 import android.graphics.RenderNode;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.Trace;
-import android.util.Log;
 import android.view.Surface.OutOfResourcesException;
 import android.view.View.AttachInfo;
 import android.view.animation.AnimationUtils;
 
 import com.android.internal.R;
-import com.android.internal.util.VirtualRefBasePtr;
 
-import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 
 /**
  * Threaded renderer that proxies the rendering to a render thread. Most calls
@@ -66,15 +54,7 @@
  *
  * @hide
  */
-public final class ThreadedRenderer {
-    private static final String LOG_TAG = "ThreadedRenderer";
-
-    /**
-     * Name of the file that holds the shaders cache.
-     */
-    private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
-    private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
-
+public final class ThreadedRenderer extends HardwareRenderer {
     /**
      * System property used to enable or disable threaded rendering profiling.
      * The default value of this property is assumed to be false.
@@ -192,6 +172,12 @@
      */
     public static final String DEBUG_FPS_DIVISOR = "debug.hwui.fps_divisor";
 
+    /**
+     * Forces smart-dark to be always on.
+     * @hide
+     */
+    public static final String DEBUG_FORCE_DARK = "debug.hwui.force_dark";
+
     public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
     public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
     public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
@@ -271,21 +257,6 @@
     }
 
     /**
-     * Sets the directory to use as a persistent storage for threaded rendering
-     * resources.
-     *
-     * @param cacheDir A directory the current process can write to
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public static void setupDiskCache(File cacheDir) {
-        ThreadedRenderer.setupShadersDiskCache(
-                new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
-                new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
-    }
-
-    /**
      * Creates a threaded renderer using OpenGL.
      *
      * @param translucent True if the surface is translucent, false otherwise
@@ -300,55 +271,10 @@
         return renderer;
     }
 
-    /**
-     * Invoke this method when the system is running out of memory. This
-     * method will attempt to recover as much memory as possible, based on
-     * the specified hint.
-     *
-     * @param level Hint about the amount of memory that should be trimmed,
-     *              see {@link android.content.ComponentCallbacks}
-     */
-    public static void trimMemory(int level) {
-        nTrimMemory(level);
-    }
-
-    public static void overrideProperty(@NonNull String name, @NonNull String value) {
-        if (name == null || value == null) {
-            throw new IllegalArgumentException("name and value must be non-null");
-        }
-        nOverrideProperty(name, value);
-    }
-
-    // Keep in sync with DrawFrameTask.h SYNC_* flags
-    // Nothing interesting to report
-    private static final int SYNC_OK = 0;
-    // Needs a ViewRoot invalidate
-    private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0;
-    // Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
-    private static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
-    // setStopped is true, drawing is false
-    // TODO: Remove this and SYNC_LOST_SURFACE_REWARD_IF_FOUND?
-    // This flag isn't really used as there's nothing that we care to do
-    // in response, so it really just exists to differentiate from LOST_SURFACE
-    // but possibly both can just be deleted.
-    private static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
-    private static final int SYNC_FRAME_DROPPED = 1 << 3;
-
     private static final String[] VISUALIZERS = {
         PROFILE_PROPERTY_VISUALIZE_BARS,
     };
 
-    private static final int FLAG_DUMP_FRAMESTATS   = 1 << 0;
-    private static final int FLAG_DUMP_RESET        = 1 << 1;
-    private static final int FLAG_DUMP_ALL          = FLAG_DUMP_FRAMESTATS;
-
-    @IntDef(flag = true, prefix = { "FLAG_DUMP_" }, value = {
-            FLAG_DUMP_FRAMESTATS,
-            FLAG_DUMP_RESET
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface DumpFlags {}
-
     // Size of the rendered content.
     private int mWidth, mHeight;
 
@@ -362,51 +288,37 @@
     // Whether the surface has insets. Used to protect opacity.
     private boolean mHasInsets;
 
-    // Light and shadow properties specified by the theme.
+    // Light properties specified by the theme.
     private final float mLightY;
     private final float mLightZ;
     private final float mLightRadius;
-    private final int mAmbientShadowAlpha;
-    private final int mSpotShadowAlpha;
 
-    private long mNativeProxy;
     private boolean mInitialized = false;
-    private RenderNode mRootNode;
     private boolean mRootNodeNeedsUpdate;
 
     private boolean mEnabled;
     private boolean mRequested = true;
-    private boolean mIsOpaque = false;
 
     ThreadedRenderer(Context context, boolean translucent, String name) {
+        super();
+        setName(name);
+        setOpaque(!translucent);
+
         final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
         mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
         mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
         mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
-        mAmbientShadowAlpha =
-                (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
-        mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
+        float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
+        float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
         a.recycle();
-
-        long rootNodePtr = nCreateRootRenderNode();
-        mRootNode = RenderNode.adopt(rootNodePtr);
-        mRootNode.setClipToBounds(false);
-        mIsOpaque = !translucent;
-        mNativeProxy = nCreateProxy(translucent, rootNodePtr);
-        nSetName(mNativeProxy, name);
-
-        ProcessInitializer.sInstance.init(context, mNativeProxy);
-
-        loadSystemProperties();
+        setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
     }
 
-    /**
-     * Destroys the threaded rendering context.
-     */
-    void destroy() {
+    @Override
+    public void destroy() {
         mInitialized = false;
         updateEnabledState(null);
-        nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
+        super.destroy();
     }
 
     /**
@@ -464,7 +376,7 @@
         boolean status = !mInitialized;
         mInitialized = true;
         updateEnabledState(surface);
-        nInitialize(mNativeProxy, surface);
+        setSurface(surface);
         return status;
     }
 
@@ -505,26 +417,18 @@
      */
     void updateSurface(Surface surface) throws OutOfResourcesException {
         updateEnabledState(surface);
-        nUpdateSurface(mNativeProxy, surface);
+        setSurface(surface);
     }
 
-    /**
-     * Halts any current rendering into the surface. Use this if it is unclear whether
-     * or not the surface used by the ThreadedRenderer will be changing. It
-     * Suspends any rendering into the surface, but will not do any destruction.
-     *
-     * Any subsequent draws will override the pause, resuming normal operation.
-     */
-    boolean pauseSurface(Surface surface) {
-        return nPauseSurface(mNativeProxy, surface);
-    }
-
-    /**
-     * Hard stops or resumes rendering into the surface. This flag is used to
-     * determine whether or not it is safe to use the given surface *at all*
-     */
-    void setStopped(boolean stopped) {
-        nSetStopped(mNativeProxy, stopped);
+    @Override
+    public void setSurface(Surface surface) {
+        // TODO: Do we ever pass a non-null but isValid() = false surface?
+        // This is here to be super conservative for ViewRootImpl
+        if (surface != null && surface.isValid()) {
+            super.setSurface(surface);
+        } else {
+            super.setSurface(null);
+        }
     }
 
     /**
@@ -535,7 +439,7 @@
      */
     void destroyHardwareResources(View view) {
         destroyResources(view);
-        nDestroyHardwareResources(mNativeProxy);
+        destroyHardwareResources();
     }
 
     private static void destroyResources(View view) {
@@ -543,14 +447,6 @@
     }
 
     /**
-     * Detaches the layer's surface texture from the GL context and releases
-     * the texture id
-     */
-    void detachSurfaceTexture(long hardwareLayer) {
-        nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
-    }
-
-    /**
      * Sets up the renderer for drawing.
      *
      * @param width The width of the drawing surface.
@@ -581,8 +477,6 @@
         }
 
         mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
-        nSetup(mNativeProxy, mLightRadius,
-                mAmbientShadowAlpha, mSpotShadowAlpha);
 
         setLightCenter(attachInfo);
     }
@@ -598,27 +492,7 @@
         attachInfo.mDisplay.getRealSize(displaySize);
         final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft;
         final float lightY = mLightY - attachInfo.mWindowTop;
-
-        nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
-    }
-
-    /**
-     * Change the ThreadedRenderer's opacity
-     */
-    void setOpaque(boolean opaque) {
-        mIsOpaque = opaque && !mHasInsets;
-        nSetOpaque(mNativeProxy, mIsOpaque);
-    }
-
-    boolean isOpaque() {
-        return mIsOpaque;
-    }
-
-    /**
-     * Enable/disable wide gamut rendering on this renderer.
-     */
-    void setWideGamut(boolean wideGamut) {
-        nSetWideGamut(mNativeProxy, wideGamut);
+        setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
     }
 
     /**
@@ -663,18 +537,12 @@
                     break;
             }
         }
-        nDumpProfileInfo(mNativeProxy, fd, flags);
+        dumpProfileInfo(fd, flags);
     }
 
-    /**
-     * Loads system properties used by the renderer. This method is invoked
-     * whenever system properties are modified. Implementations can use this
-     * to trigger live updates of the renderer based on properties.
-     *
-     * @return True if a property has changed.
-     */
-    boolean loadSystemProperties() {
-        boolean changed = nLoadSystemProperties(mNativeProxy);
+    @Override
+    public boolean loadSystemProperties() {
+        boolean changed = super.loadSystemProperties();
         if (changed) {
             invalidateRoot();
         }
@@ -695,72 +563,27 @@
         updateViewTreeDisplayList(view);
 
         if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
-            RecordingCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
+            RecordingCanvas canvas = mRootNode.startRecording(mSurfaceWidth, mSurfaceHeight);
             try {
                 final int saveCount = canvas.save();
                 canvas.translate(mInsetLeft, mInsetTop);
                 callbacks.onPreDraw(canvas);
 
-                canvas.insertReorderBarrier();
+                canvas.enableZ();
                 canvas.drawRenderNode(view.updateDisplayListIfDirty());
-                canvas.insertInorderBarrier();
+                canvas.disableZ();
 
                 callbacks.onPostDraw(canvas);
                 canvas.restoreToCount(saveCount);
                 mRootNodeNeedsUpdate = false;
             } finally {
-                mRootNode.end(canvas);
+                mRootNode.endRecording();
             }
         }
         Trace.traceEnd(Trace.TRACE_TAG_VIEW);
     }
 
     /**
-     * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
-     * rendernode of the UI thread.
-     * @param node The node to add.
-     * @param placeFront If true, the render node will be placed in front of the content node,
-     *                   otherwise behind the content node.
-     */
-    @UnsupportedAppUsage
-    public void addRenderNode(RenderNode node, boolean placeFront) {
-        nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
-    }
-
-    /**
-     * Only especially added render nodes can be removed.
-     * @param node The node which was added via addRenderNode which should get removed again.
-     */
-    @UnsupportedAppUsage
-    public void removeRenderNode(RenderNode node) {
-        nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
-    }
-
-    /**
-     * Draws a particular render node. If the node is not the content node, only the additional
-     * nodes will get drawn and the content remains untouched.
-     * @param node The node to be drawn.
-     */
-    @UnsupportedAppUsage
-    public void drawRenderNode(RenderNode node) {
-        nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
-    }
-
-    /**
-     * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
-     * will be prevented to overdraw this area. It will be synchronized with the draw call.
-     * This should be updated in the content view's draw call.
-     * @param left The left side of the protected bounds.
-     * @param top The top side of the protected bounds.
-     * @param right The right side of the protected bounds.
-     * @param bottom The bottom side of the protected bounds.
-     */
-    @UnsupportedAppUsage
-    public void setContentDrawBounds(int left, int top, int right, int bottom) {
-        nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
-    }
-
-    /**
      * Interface used to receive callbacks whenever a view is drawn by
      * a threaded renderer instance.
      */
@@ -819,11 +642,10 @@
             attachInfo.mPendingAnimatingRenderNodes = null;
         }
 
-        final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
         if (frameDrawingCallback != null) {
-            nSetFrameCallback(mNativeProxy, frameDrawingCallback);
+            setFrameCallback(frameDrawingCallback);
         }
-        int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
+        int syncResult = syncAndDrawFrame(choreographer.mFrameInfo);
         if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
             setEnabled(false);
             attachInfo.mViewRootImpl.mSurface.release();
@@ -831,207 +653,38 @@
             // if it is still needed or do nothing if we are no longer drawing
             attachInfo.mViewRootImpl.invalidate();
         }
-        if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
+        if ((syncResult & SYNC_REDRAW_REQUESTED) != 0) {
             attachInfo.mViewRootImpl.invalidate();
         }
     }
 
-    void setFrameCompleteCallback(FrameCompleteCallback callback) {
-        nSetFrameCompleteCallback(mNativeProxy, callback);
-    }
-
-    static void invokeFunctor(long functor, boolean waitForCompletion) {
-        nInvokeFunctor(functor, waitForCompletion);
-    }
-
-    /**
-     * Creates a new hardware layer. A hardware layer built by calling this
-     * method will be treated as a texture layer, instead of as a render target.
-     *
-     * @return A hardware layer
-     */
-    TextureLayer createTextureLayer() {
-        long layer = nCreateTextureLayer(mNativeProxy);
-        return TextureLayer.adoptTextureLayer(this, layer);
-    }
-
-
-    void buildLayer(RenderNode node) {
-        if (node.hasDisplayList()) {
-            nBuildLayer(mNativeProxy, node.mNativeRenderNode);
-        }
-    }
-
-
-    boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
-        return nCopyLayerInto(mNativeProxy,
-                layer.getDeferredLayerUpdater(), bitmap);
-    }
-
-    /**
-     * Indicates that the specified hardware layer needs to be updated
-     * as soon as possible.
-     *
-     * @param layer The hardware layer that needs an update
-     */
-    void pushLayerUpdate(TextureLayer layer) {
-        nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
-    }
-
-    /**
-     * Tells the HardwareRenderer that the layer is destroyed. The renderer
-     * should remove the layer from any update queues.
-     */
-    void onLayerDestroyed(TextureLayer layer) {
-        nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
-    }
-
-    /**
-     * Blocks until all previously queued work has completed.
-     */
-    void fence() {
-        nFence(mNativeProxy);
-    }
-
-    /**
-     * Prevents any further drawing until draw() is called. This is a signal
-     * that the contents of the RenderNode tree are no longer safe to play back.
-     * In practice this usually means that there are Functor pointers in the
-     * display list that are no longer valid.
-     */
-    void stopDrawing() {
-        nStopDrawing(mNativeProxy);
-    }
-
-    /**
-     * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
-     */
-    public void notifyFramePending() {
-        nNotifyFramePending(mNativeProxy);
-    }
-
-
-    void registerAnimatingRenderNode(RenderNode animator) {
-        nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
-    }
-
-    void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
-        nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
-                animator.getAnimatorNativePtr());
-    }
-
-    public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
-        if (srcRect == null) {
-            // Empty rect means entire surface
-            return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
-        } else {
-            return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
-                    srcRect.right, srcRect.bottom, bitmap);
-        }
-    }
-
-    /**
-     * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
-     * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
-     * not the RenderNode from a View.
-     **/
-    @UnsupportedAppUsage
-    public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
-        return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
-    }
-
-    /**
-     * Sets whether or not high contrast text rendering is enabled. The setting is global
-     * but only affects content rendered after the change is made.
-     */
-    public static void setHighContrastText(boolean highContrastText) {
-        nSetHighContrastText(highContrastText);
-    }
-
-    /**
-     * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
-     */
-    public static void setIsolatedProcess(boolean isIsolated) {
-        nSetIsolatedProcess(isIsolated);
-    }
-
-    /**
-     * If set extra graphics debugging abilities will be enabled such as dumping skp
-     */
-    public static void setDebuggingEnabled(boolean enable) {
-        nSetDebuggingEnabled(enable);
-    }
-
-    void allocateBuffers(Surface surface) {
-        nAllocateBuffers(mNativeProxy, surface);
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            nDeleteProxy(mNativeProxy);
-            mNativeProxy = 0;
-        } finally {
-            super.finalize();
-        }
-    }
-
     /** The root of everything */
     public @NonNull RenderNode getRootNode() {
         return mRootNode;
     }
 
-    private boolean mForceDark = false;
-
-    /**
-     * Whether or not the force-dark feature should be used for this renderer.
-     */
-    public boolean setForceDark(boolean enable) {
-        if (mForceDark != enable) {
-            mForceDark = enable;
-            nSetForceDark(mNativeProxy, enable);
-            return true;
-        }
-        return false;
-    }
-
     /**
      * Basic synchronous renderer. Currently only used to render the Magnifier, so use with care.
      * TODO: deduplicate against ThreadedRenderer.
      *
      * @hide
      */
-    public static class SimpleRenderer {
-        private final RenderNode mRootNode;
-        private long mNativeProxy;
-        private final float mLightY, mLightZ;
-        private Surface mSurface;
-        private final FrameInfo mFrameInfo = new FrameInfo();
+    public static class SimpleRenderer extends HardwareRenderer {
+        private final float mLightY, mLightZ, mLightRadius;
 
         public SimpleRenderer(final Context context, final String name, final Surface surface) {
+            super();
+            setName(name);
+            setOpaque(false);
+            setSurface(surface);
             final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
             mLightY = a.getDimension(R.styleable.Lighting_lightY, 0);
             mLightZ = a.getDimension(R.styleable.Lighting_lightZ, 0);
-            final float lightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
-            final int ambientShadowAlpha =
-                    (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
-            final int spotShadowAlpha =
-                    (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
+            mLightRadius = a.getDimension(R.styleable.Lighting_lightRadius, 0);
+            final float ambientShadowAlpha = a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0);
+            final float spotShadowAlpha = a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0);
             a.recycle();
-
-            final long rootNodePtr = nCreateRootRenderNode();
-            mRootNode = RenderNode.adopt(rootNodePtr);
-            mRootNode.setClipToBounds(false);
-            mNativeProxy = nCreateProxy(true /* translucent */, rootNodePtr);
-            nSetName(mNativeProxy, name);
-
-            ProcessInitializer.sInstance.init(context, mNativeProxy);
-            nLoadSystemProperties(mNativeProxy);
-
-            nSetup(mNativeProxy, lightRadius, ambientShadowAlpha, spotShadowAlpha);
-
-            mSurface = surface;
-            nUpdateSurface(mNativeProxy, surface);
+            setLightSourceAlpha(ambientShadowAlpha, spotShadowAlpha);
         }
 
         /**
@@ -1045,7 +698,7 @@
             final float lightX = displaySize.x / 2f - windowLeft;
             final float lightY = mLightY - windowTop;
 
-            nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
+            setLightSourceGeometry(lightX, lightY, mLightZ, mLightRadius);
         }
 
         public RenderNode getRootNode() {
@@ -1057,222 +710,10 @@
          */
         public void draw(final FrameDrawingCallback callback) {
             final long vsync = AnimationUtils.currentAnimationTimeMillis() * 1000000L;
-            mFrameInfo.setVsync(vsync, vsync);
-            mFrameInfo.addFlags(1 << 2 /* VSYNC */);
             if (callback != null) {
-                nSetFrameCallback(mNativeProxy, callback);
+                setFrameCallback(callback);
             }
-            nSyncAndDrawFrame(mNativeProxy, mFrameInfo.mFrameInfo, mFrameInfo.mFrameInfo.length);
-        }
-
-        /**
-         * Destroy the renderer.
-         */
-        public void destroy() {
-            mSurface = null;
-            nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
-        }
-
-        @Override
-        protected void finalize() throws Throwable {
-            try {
-                nDeleteProxy(mNativeProxy);
-                mNativeProxy = 0;
-            } finally {
-                super.finalize();
-            }
+            syncAndDrawFrame(vsync);
         }
     }
-
-    /**
-     * Interface used to receive callbacks when a frame is being drawn.
-     */
-    public interface FrameDrawingCallback {
-        /**
-         * Invoked during a frame drawing.
-         *
-         * @param frame The id of the frame being drawn.
-         */
-        void onFrameDraw(long frame);
-    }
-
-    /**
-     * Interface used to be notified when a frame has finished rendering
-     */
-    public interface FrameCompleteCallback {
-        /**
-         * Invoked after a frame draw
-         *
-         * @param frameNr The id of the frame that was drawn.
-         */
-        void onFrameComplete(long frameNr);
-    }
-
-    private static class ProcessInitializer {
-        static ProcessInitializer sInstance = new ProcessInitializer();
-
-        private boolean mInitialized = false;
-
-        private Context mAppContext;
-        private IGraphicsStats mGraphicsStatsService;
-        private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
-            @Override
-            public void onRotateGraphicsStatsBuffer() throws RemoteException {
-                rotateBuffer();
-            }
-        };
-
-        private ProcessInitializer() {}
-
-        synchronized void init(Context context, long renderProxy) {
-            if (mInitialized) return;
-            mInitialized = true;
-            mAppContext = context.getApplicationContext();
-
-            initSched(renderProxy);
-
-            if (mAppContext != null) {
-                initGraphicsStats();
-            }
-        }
-
-        private void initSched(long renderProxy) {
-            try {
-                int tid = nGetRenderThreadTid(renderProxy);
-                ActivityManager.getService().setRenderThread(tid);
-            } catch (Throwable t) {
-                Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
-            }
-        }
-
-        private void initGraphicsStats() {
-            try {
-                IBinder binder = ServiceManager.getService("graphicsstats");
-                if (binder == null) return;
-                mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
-                requestBuffer();
-            } catch (Throwable t) {
-                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
-            }
-        }
-
-        private void rotateBuffer() {
-            nRotateProcessStatsBuffer();
-            requestBuffer();
-        }
-
-        private void requestBuffer() {
-            try {
-                final String pkg = mAppContext.getApplicationInfo().packageName;
-                ParcelFileDescriptor pfd = mGraphicsStatsService
-                        .requestBufferForProcess(pkg, mGraphicsStatsCallback);
-                nSetProcessStatsBuffer(pfd.getFd());
-                pfd.close();
-            } catch (Throwable t) {
-                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
-            }
-        }
-    }
-
-    void addFrameMetricsObserver(FrameMetricsObserver observer) {
-        long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
-        observer.mNative = new VirtualRefBasePtr(nativeObserver);
-    }
-
-    void removeFrameMetricsObserver(FrameMetricsObserver observer) {
-        nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
-        observer.mNative = null;
-    }
-
-    /** b/68769804: For low FPS experiments. */
-    public static void setFPSDivisor(int divisor) {
-        nHackySetRTAnimationsEnabled(divisor <= 1);
-    }
-
-    /**
-     * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
-     * called before any OpenGL context is created.
-     *
-     * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
-     */
-    public static void setContextPriority(int priority) {
-        nSetContextPriority(priority);
-    }
-
-    /** Not actually public - internal use only. This doc to make lint happy */
-    public static native void disableVsync();
-
-    static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
-
-    private static native void nRotateProcessStatsBuffer();
-    private static native void nSetProcessStatsBuffer(int fd);
-    private static native int nGetRenderThreadTid(long nativeProxy);
-
-    private static native long nCreateRootRenderNode();
-    private static native long nCreateProxy(boolean translucent, long rootRenderNode);
-    private static native void nDeleteProxy(long nativeProxy);
-
-    private static native boolean nLoadSystemProperties(long nativeProxy);
-    private static native void nSetName(long nativeProxy, String name);
-
-    private static native void nInitialize(long nativeProxy, Surface window);
-    private static native void nUpdateSurface(long nativeProxy, Surface window);
-    private static native boolean nPauseSurface(long nativeProxy, Surface window);
-    private static native void nSetStopped(long nativeProxy, boolean stopped);
-    private static native void nSetup(long nativeProxy,
-            float lightRadius, int ambientShadowAlpha, int spotShadowAlpha);
-    private static native void nSetLightCenter(long nativeProxy,
-            float lightX, float lightY, float lightZ);
-    private static native void nSetOpaque(long nativeProxy, boolean opaque);
-    private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
-    private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
-    private static native void nDestroy(long nativeProxy, long rootRenderNode);
-    private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
-    private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
-
-    private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
-
-    private static native long nCreateTextureLayer(long nativeProxy);
-    private static native void nBuildLayer(long nativeProxy, long node);
-    private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
-    private static native void nPushLayerUpdate(long nativeProxy, long layer);
-    private static native void nCancelLayerUpdate(long nativeProxy, long layer);
-    private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
-
-    private static native void nDestroyHardwareResources(long nativeProxy);
-    private static native void nTrimMemory(int level);
-    private static native void nOverrideProperty(String name, String value);
-
-    private static native void nFence(long nativeProxy);
-    private static native void nStopDrawing(long nativeProxy);
-    private static native void nNotifyFramePending(long nativeProxy);
-
-    private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
-            @DumpFlags int dumpFlags);
-
-    private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
-             boolean placeFront);
-    private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
-    private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
-    private static native void nSetContentDrawBounds(long nativeProxy, int left,
-             int top, int right, int bottom);
-    private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
-    private static native void nSetFrameCompleteCallback(long nativeProxy,
-            FrameCompleteCallback callback);
-
-    private static native long nAddFrameMetricsObserver(long nativeProxy, FrameMetricsObserver observer);
-    private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
-
-    private static native int nCopySurfaceInto(Surface surface,
-            int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
-
-    private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
-    private static native void nSetHighContrastText(boolean enabled);
-    // For temporary experimentation b/66945974
-    private static native void nHackySetRTAnimationsEnabled(boolean enabled);
-    private static native void nSetDebuggingEnabled(boolean enabled);
-    private static native void nSetIsolatedProcess(boolean enabled);
-    private static native void nSetContextPriority(int priority);
-    private static native void nAllocateBuffers(long nativeProxy, Surface window);
-    private static native void nSetForceDark(long nativeProxy, boolean enabled);
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 43fcce3..5f1336f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -112,6 +112,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
+import android.view.intelligence.IntelligenceManager;
 import android.widget.Checkable;
 import android.widget.FrameLayout;
 import android.widget.ScrollBarDrawable;
@@ -799,6 +800,11 @@
     private static final String AUTOFILL_LOG_TAG = "View.Autofill";
 
     /**
+     * The logging tag used by this class when logging content capture-related messages.
+     */
+    private static final String CONTENT_CAPTURE_LOG_TAG = "View.ContentCapture";
+
+    /**
      * When set to true, apps will draw debugging information about their layouts.
      *
      * @hide
@@ -1337,6 +1343,59 @@
      */
     public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1;
 
+    /** @hide */
+    @IntDef(prefix = { "IMPORTANT_FOR_CONTENT_CAPTURE_" }, value = {
+            IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
+            IMPORTANT_FOR_CONTENT_CAPTURE_YES,
+            IMPORTANT_FOR_CONTENT_CAPTURE_NO,
+            IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
+            IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ContentCaptureImportance {}
+
+    /**
+     * Automatically determine whether a view is important for content capture.
+     *
+     * @see #isImportantForContentCapture()
+     * @see #setImportantForContentCapture(int)
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
+
+    /**
+     * The view is important for content capture, and its children (if any) will be traversed.
+     *
+     * @see #isImportantForContentCapture()
+     * @see #setImportantForContentCapture(int)
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
+
+    /**
+     * The view is not important for content capture, but its children (if any) will be traversed.
+     *
+     * @see #isImportantForContentCapture()
+     * @see #setImportantForContentCapture(int)
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
+
+    /**
+     * The view is important for content capture, but its children (if any) will not be traversed.
+     *
+     * @see #isImportantForContentCapture()
+     * @see #setImportantForContentCapture(int)
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
+
+    /**
+     * The view is not important for content capture, and its children (if any) will not be
+     * traversed.
+     *
+     * @see #isImportantForContentCapture()
+     * @see #setImportantForContentCapture(int)
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
+
+
     /**
      * This view is enabled. Interpretation varies by subclass.
      * Use with ENABLED_MASK when calling setFlags.
@@ -2243,7 +2302,44 @@
     @UnsupportedAppUsage
     protected Object mTag = null;
 
-    // for mPrivateFlags:
+    /*
+     * Masks for mPrivateFlags, as generated by dumpFlags():
+     *
+     * |-------|-------|-------|-------|
+     *                                 1 PFLAG_WANTS_FOCUS
+     *                                1  PFLAG_FOCUSED
+     *                               1   PFLAG_SELECTED
+     *                              1    PFLAG_IS_ROOT_NAMESPACE
+     *                             1     PFLAG_HAS_BOUNDS
+     *                            1      PFLAG_DRAWN
+     *                           1       PFLAG_DRAW_ANIMATION
+     *                          1        PFLAG_SKIP_DRAW
+     *                        1          PFLAG_REQUEST_TRANSPARENT_REGIONS
+     *                       1           PFLAG_DRAWABLE_STATE_DIRTY
+     *                      1            PFLAG_MEASURED_DIMENSION_SET
+     *                     1             PFLAG_FORCE_LAYOUT
+     *                    1              PFLAG_LAYOUT_REQUIRED
+     *                   1               PFLAG_PRESSED
+     *                  1                PFLAG_DRAWING_CACHE_VALID
+     *                 1                 PFLAG_ANIMATION_STARTED
+     *                1                  PFLAG_SAVE_STATE_CALLED
+     *               1                   PFLAG_ALPHA_SET
+     *              1                    PFLAG_SCROLL_CONTAINER
+     *             1                     PFLAG_SCROLL_CONTAINER_ADDED
+     *            1                      PFLAG_DIRTY
+     *            1                      PFLAG_DIRTY_MASK
+     *          1                        PFLAG_OPAQUE_BACKGROUND
+     *         1                         PFLAG_OPAQUE_SCROLLBARS
+     *         11                        PFLAG_OPAQUE_MASK
+     *        1                          PFLAG_PREPRESSED
+     *       1                           PFLAG_CANCEL_NEXT_UP_EVENT
+     *      1                            PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH
+     *     1                             PFLAG_HOVERED
+     *    1                              PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK
+     *   1                               PFLAG_ACTIVATED
+     *  1                                PFLAG_INVALIDATED
+     * |-------|-------|-------|-------|
+     */
     /** {@hide} */
     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
     /** {@hide} */
@@ -2393,7 +2489,9 @@
      */
     static final int PFLAG_INVALIDATED                 = 0x80000000;
 
-    /**
+    /* End of masks for mPrivateFlags */
+
+    /*
      * Masks for mPrivateFlags2, as generated by dumpFlags():
      *
      * |-------|-------|-------|-------|
@@ -2934,7 +3032,7 @@
 
     /* End of masks for mPrivateFlags2 */
 
-    /**
+    /*
      * Masks for mPrivateFlags3, as generated by dumpFlags():
      *
      * |-------|-------|-------|-------|
@@ -3270,6 +3368,72 @@
 
     /* End of masks for mPrivateFlags3 */
 
+    /*
+     * Masks for mPrivateFlags4, as generated by dumpFlags():
+     *
+     * |-------|-------|-------|-------|
+     *                              1111 PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK
+     *                             1     PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT
+     *                            1      PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED
+     *                           1       PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE
+     * |-------|-------|-------|-------|
+     */
+
+    /**
+     * Mask for obtaining the bits which specify how to determine
+     * whether a view is important for autofill.
+     *
+     * <p>NOTE: the important for content capture values were the first flags added and are set in
+     * the rightmost position, so we don't need to shift them
+     */
+    private static final int PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK =
+            IMPORTANT_FOR_CONTENT_CAPTURE_AUTO | IMPORTANT_FOR_CONTENT_CAPTURE_YES
+            | IMPORTANT_FOR_CONTENT_CAPTURE_NO
+            | IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
+            | IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS;
+
+    /*
+     * Variables used to control when the IntelligenceManager.notifyNodeAdded()/removed() methods
+     * should be called.
+     *
+     * The idea is to call notifyNodeAdded() after the view is layout and visible, then call
+     * notifyNodeRemoved() when it's gone (without known when it was removed from the parent).
+     *
+     * TODO(b/111276913): the current algortighm could probably be optimized and some of them
+     * removed
+     */
+    private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT = 0x10;
+    private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED = 0x20;
+    private static final int PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE = 0x40;
+
+    /* End of masks for mPrivateFlags4 */
+
+    private static final int CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED = 1;
+    private static final int CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED = 0;
+
+    @IntDef(flag = true, prefix = { "CONTENT_CAPTURE_NOTIFICATION_TYPE_" }, value = {
+            CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED,
+            CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface ContentCaptureNotificationType {}
+
+    /** @hide */
+    protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
+    /** @hide */
+    protected  static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
+    /** @hide */
+    protected  static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
+            VIEW_STRUCTURE_FOR_ASSIST,
+            VIEW_STRUCTURE_FOR_AUTOFILL,
+            VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ViewStructureType {}
+
     /**
      * Always allow a user to over-scroll this view, provided it is a
      * view that can scroll.
@@ -3861,6 +4025,8 @@
     @UnsupportedAppUsage
     int mPrivateFlags3;
 
+    private int mPrivateFlags4;
+
     /**
      * This view's request for the visibility of the status bar.
      * @hide
@@ -4566,6 +4732,16 @@
     private TouchDelegate mTouchDelegate = null;
 
     /**
+     * While touch exploration is in use, set to true when hovering across boundaries and
+     * inside the touch area of the delegate at receiving {@link MotionEvent#ACTION_HOVER_ENTER}
+     * or {@link MotionEvent#ACTION_HOVER_MOVE}. False when leaving boundaries or receiving a
+     * {@link MotionEvent#ACTION_HOVER_EXIT}.
+     * Note that children of view group are excluded in the touch area.
+     * @see #dispatchTouchExplorationHoverEvent
+     */
+    private boolean mHoveringTouchDelegate = false;
+
+    /**
      * Solid color to use as a background when creating the drawing cache. Enables
      * the cache to use 16 bit bitmaps instead of 32 bit.
      */
@@ -5803,6 +5979,7 @@
         mAttributes = trimmed;
     }
 
+    @Override
     public String toString() {
         StringBuilder out = new StringBuilder(128);
         out.append(getClass().getName());
@@ -5875,6 +6052,9 @@
                 }
             }
         }
+        if (mAutofillId != null) {
+            out.append(" aid="); out.append(mAutofillId);
+        }
         out.append("}");
         return out.toString();
     }
@@ -7888,7 +8068,7 @@
      * fills in all data that can be inferred from the view itself.
      */
     public void onProvideStructure(ViewStructure structure) {
-        onProvideStructureForAssistOrAutofill(structure, false, 0);
+        onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
     }
 
     /**
@@ -7961,11 +8141,45 @@
      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
      */
     public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
-        onProvideStructureForAssistOrAutofill(structure, true, flags);
+        onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
     }
 
-    private void onProvideStructureForAssistOrAutofill(ViewStructure structure,
-            boolean forAutofill, @AutofillFlags int flags) {
+    /**
+     * Populates a {@link ViewStructure} for Content Capture.
+     *
+     * <p>This method is called after a view is that is eligible for Content Capture
+     * (for example, if it {@link #isImportantForAutofill()}, an intelligence service is enabled for
+     * the user, and the activity rendering the view is enabled for Content Capture) is laid out and
+     * is visible.
+     *
+     * <p><b>Note: </b>the following methods of the {@code structure} will be ignored:
+     * <ul>
+     *   <li>{@link ViewStructure#setChildCount(int)}
+     *   <li>{@link ViewStructure#addChildCount(int)}
+     *   <li>{@link ViewStructure#getChildCount()}
+     *   <li>{@link ViewStructure#newChild(int)}
+     *   <li>{@link ViewStructure#asyncNewChild(int)}
+     *   <li>{@link ViewStructure#asyncCommit()}
+     *   <li>{@link ViewStructure#setWebDomain(String)}
+     *   <li>{@link ViewStructure#newHtmlInfoBuilder(String)}
+     *   <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}
+     *   <li>{@link ViewStructure#setDataIsSensitive(boolean)}
+     * </ul>
+     *
+     * @return whether the IntelligenceService should be notified that the view was added (through
+     * the {@link IntelligenceManager#notifyViewAppeared(ViewStructure)} method) to the view
+     * hierarchy. Most views should return {@code true} here, but views that contains virtual
+     * hierarchy might opt to return {@code false} and notify the manager independently, as the
+     * virtual views are rendered.
+     */
+    public boolean onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
+        onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
+        return true;
+    }
+
+    /** @hide */
+    protected void onProvideStructure(@NonNull ViewStructure structure,
+            @ViewStructureType int viewFor, int flags) {
         final int id = mID;
         if (id != NO_ID && !isViewIdGenerated(id)) {
             String pkg, type, entry;
@@ -7981,8 +8195,13 @@
         } else {
             structure.setId(id, null, null, null);
         }
+        if (viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+            //TODO(b/111276913): STOPSHIP - don't set it if not needed
+            structure.setDataIsSensitive(false);
+        }
 
-        if (forAutofill) {
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
             final @AutofillType int autofillType = getAutofillType();
             // Don't need to fill autofill info if view does not support it.
             // For example, only TextViews that are editable support autofill
@@ -7996,7 +8215,8 @@
 
         int ignoredParentLeft = 0;
         int ignoredParentTop = 0;
-        if (forAutofill && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+                && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
             View parentGroup = null;
 
             ViewParent viewParent = getParent();
@@ -8019,7 +8239,8 @@
 
         structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
                 mRight - mLeft, mBottom - mTop);
-        if (!forAutofill) {
+        if (viewFor == VIEW_STRUCTURE_FOR_ASSIST
+                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
             if (!hasIdentityMatrix()) {
                 structure.setTransformation(getMatrix());
             }
@@ -8530,9 +8751,8 @@
             if (parentImportance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
                     || parentImportance == IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS) {
                 if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
-                    Log.v(AUTOFILL_LOG_TAG, "View (autofillId=" +  getAutofillViewId() + ", "
-                            + getClass() + ") is not important for autofill because parent "
-                            + parent + "'s importance is " + parentImportance);
+                    Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
+                            + "because parent " + parent + "'s importance is " + parentImportance);
                 }
                 return false;
             }
@@ -8549,14 +8769,18 @@
         if (importance == IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
                 || importance == IMPORTANT_FOR_AUTOFILL_NO) {
             if (Log.isLoggable(AUTOFILL_LOG_TAG, Log.VERBOSE)) {
-                Log.v(AUTOFILL_LOG_TAG, "View (autofillId=" +  getAutofillViewId() + ", "
-                        + getClass() + ") is not important for autofill because its "
-                        + "importance is " + importance);
+                Log.v(AUTOFILL_LOG_TAG, "View (" +  this + ") is not important for autofill "
+                        + "because its importance is " + importance);
             }
             return false;
         }
 
         // Then use some heuristics to handle AUTO.
+        if (importance != IMPORTANT_FOR_AUTOFILL_AUTO) {
+            Log.w(AUTOFILL_LOG_TAG, "invalid autofill importance (" + importance + " on view "
+                    + this);
+            return false;
+        }
 
         // Always include views that have an explicit resource id.
         final int id = mID;
@@ -8584,6 +8808,197 @@
         return false;
     }
 
+    /**
+     * Gets the mode for determining whether this view is important for content capture.
+     *
+     * <p>See {@link #setImportantForContentCapture(int)} and
+     * {@link #isImportantForContentCapture()} for more info about this mode.
+     *
+     * @return {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO} by default, or value passed to
+     * {@link #setImportantForContentCapture(int)}.
+     *
+     * @attr ref android.R.styleable#View_importantForContentCapture
+     */
+    @ViewDebug.ExportedProperty(mapping = {
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_AUTO, to = "auto"),
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES, to = "yes"),
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO, to = "no"),
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
+                to = "yesExcludeDescendants"),
+            @ViewDebug.IntToString(from = IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
+                to = "noExcludeDescendants")})
+    public @ContentCaptureImportance int getImportantForContentCapture() {
+        // NOTE: the important for content capture values were the first flags added and are set in
+        // the rightmost position, so we don't need to shift them
+        return mPrivateFlags4 & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
+    }
+
+    /**
+     * Sets the mode for determining whether this view is considered important for content capture.
+     *
+     * <p>The platform determines the importance for autofill automatically but you
+     * can use this method to customize the behavior. Typically, a view that provides text should
+     * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
+     *
+     * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
+     * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
+     * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
+     * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
+     *
+     * @attr ref android.R.styleable#View_importantForContentCapture
+     */
+    public void setImportantForContentCapture(@ContentCaptureImportance int mode) {
+        // Reset first
+        mPrivateFlags4 &= ~PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK;
+        // Then set again
+        // NOTE: the important for content capture values were the first flags added and are set in
+        // the rightmost position, so we don't need to shift them
+        mPrivateFlags4 |= (mode & PFLAG4_IMPORTANT_FOR_CONTENT_CAPTURE_MASK);
+    }
+
+    /**
+     * Hints the Android System whether this view is considered important for Content Capture, based
+     * on the value explicitly set by {@link #setImportantForContentCapture(int)} and heuristics
+     * when it's {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO}.
+     *
+     * @return whether the view is considered important for autofill.
+     *
+     * @see #setImportantForContentCapture(int)
+     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO
+     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES
+     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO
+     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
+     * @see #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+     */
+    public final boolean isImportantForContentCapture() {
+        // Check parent mode to ensure we're important
+        ViewParent parent = mParent;
+        while (parent instanceof View) {
+            final int parentImportance = ((View) parent).getImportantForContentCapture();
+            if (parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+                    || parentImportance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS) {
+                if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
+                    Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for "
+                            + "content capture because parent " + parent + "'s importance is "
+                            + parentImportance);
+                }
+                return false;
+            }
+            parent = parent.getParent();
+        }
+
+        final int importance = getImportantForContentCapture();
+
+        // First, check the explicit states.
+        if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS
+                || importance == IMPORTANT_FOR_CONTENT_CAPTURE_YES) {
+            return true;
+        }
+        if (importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS
+                || importance == IMPORTANT_FOR_CONTENT_CAPTURE_NO) {
+            if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
+                Log.v(CONTENT_CAPTURE_LOG_TAG, "View (" +  this + ") is not important for content "
+                        + "capture because its importance is " + importance);
+            }
+            return false;
+        }
+
+        // Then use some heuristics to handle AUTO.
+        if (importance != IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
+            Log.w(CONTENT_CAPTURE_LOG_TAG, "invalid content capture importance (" + importance
+                    + " on view " + this);
+            return false;
+        }
+
+        // View group is important if at least one children also is
+        //TODO(b/111276913): decide if we really need to send the relevant parents or just the
+        // leaves (with absolute coordinates). If it's the latter, then we need to update this
+        // javadoc and ViewGroup's implementation.
+        if (this instanceof ViewGroup) {
+            final ViewGroup group = (ViewGroup) this;
+            for (int i = 0; i < group.getChildCount(); i++) {
+                final View child = group.getChildAt(i);
+                if (child.isImportantForContentCapture()) {
+                    return true;
+                }
+            }
+        }
+
+        // If the app developer explicitly set hints or autofill hintsfor it, it's important.
+        if (getAutofillHints() != null) {
+            return true;
+        }
+
+        // Otherwise, assume it's not important...
+        return false;
+    }
+
+    /**
+     * Helper used to notify the {@link IntelligenceManager} when the view is removed or
+     * added, based on whether it's laid out and visible, and without knowing if the parent removed
+     * it from the view hierarchy.
+     */
+    // TODO(b/111276913): make sure the current algorithm covers all cases. For example, it should
+    // probably be called every time notifyEnterOrExitForAutoFillIfNeeded() is called as well.
+    private void notifyNodeAddedOrRemovedForContentCaptureIfNeeded(
+            @ContentCaptureNotificationType int type) {
+        if (type != CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED
+                && type != CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED) {
+            // Sanity check so it does not screw up the flags
+            Log.wtf(CONTENT_CAPTURE_LOG_TAG, "notifyNodeAddedOrRemovedForContentCaptureIfNeeded(): "
+                    + "invalid type " + type + " for " + this);
+            return;
+        }
+
+        if (!isImportantForContentCapture()) return;
+
+        final IntelligenceManager im = mContext.getSystemService(IntelligenceManager.class);
+        if (im == null || !im.isContentCaptureEnabled()) return;
+
+        // Make sure event is notified just once, and reset the
+        // PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE flag
+        boolean ignoreNotification = false;
+        if (type == CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED) {
+            if ((mPrivateFlags4 & PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE)
+                    == CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED) {
+                ignoreNotification = true;
+            } else {
+                mPrivateFlags4 |= PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE;
+            }
+        } else {
+            if ((mPrivateFlags4 & PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE)
+                    == CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED) {
+                ignoreNotification = true;
+            } else {
+                mPrivateFlags4 &= ~PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE;
+            }
+        }
+        if (ignoreNotification) {
+            if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) {
+                // TODO(b/111276913): remove this log statement if the algorithm is not improved
+                // (right now it's called too many times when the activity is stopped and/or views
+                // disappear
+                Log.v(CONTENT_CAPTURE_LOG_TAG, "notifyNodeAddedOrRemovedForContentCaptureIfNeeded("
+                        + type + "): ignoring repeated notification on " + this);
+            }
+            return;
+        }
+
+        if (type == CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED) {
+            final ViewStructure structure = im.newViewStructure(this);
+            boolean notifyMgr = onProvideContentCaptureStructure(structure, /* flags= */ 0);
+            if (notifyMgr) {
+                im.notifyViewAppeared(structure);
+            }
+            mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED;
+        } else {
+            if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED) == 0) {
+                return; // skip initial notification
+            }
+            im.notifyViewDisappeared(getAutofillId());
+        }
+    }
+
     @Nullable
     private AutofillManager getAutofillManager() {
         return mContext.getSystemService(AutofillManager.class);
@@ -8695,7 +9110,7 @@
      * {@link #onProvideVirtualStructure}.
      */
     public void dispatchProvideStructure(ViewStructure structure) {
-        dispatchProvideStructureForAssistOrAutofill(structure, false, 0);
+        dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
     }
 
     /**
@@ -8737,12 +9152,12 @@
      */
     public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
             @AutofillFlags int flags) {
-        dispatchProvideStructureForAssistOrAutofill(structure, true, flags);
+        dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
     }
 
-    private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
-            boolean forAutofill, @AutofillFlags int flags) {
-        if (forAutofill) {
+    private void dispatchProvideStructure(@NonNull ViewStructure structure,
+            @ViewStructureType int viewFor, @AutofillFlags int flags) {
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
             structure.setAutofillId(getAutofillId());
             onProvideAutofillStructure(structure, flags);
             onProvideAutofillVirtualStructure(structure, flags);
@@ -9852,12 +10267,12 @@
             // We weren't called from within a direct call to fitSystemWindows,
             // call into it as a fallback in case we're in a class that overrides it
             // and has logic to perform.
-            if (fitSystemWindows(insets.getSystemWindowInsets())) {
+            if (fitSystemWindows(insets.getSystemWindowInsetsAsRect())) {
                 return insets.consumeSystemWindowInsets();
             }
         } else {
             // We were called from within a direct call to fitSystemWindows.
-            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
+            if (fitSystemWindowsInt(insets.getSystemWindowInsetsAsRect())) {
                 return insets.consumeSystemWindowInsets();
             }
         }
@@ -9960,7 +10375,7 @@
     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
         WindowInsets innerInsets = computeSystemWindowInsets(new WindowInsets(inoutInsets),
                 outLocalInsets);
-        inoutInsets.set(innerInsets.getSystemWindowInsets());
+        inoutInsets.set(innerInsets.getSystemWindowInsetsAsRect());
         return innerInsets.isSystemWindowInsetsConsumed();
     }
 
@@ -9979,7 +10394,7 @@
                 || mAttachInfo == null
                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
                 && !mAttachInfo.mOverscanRequested)) {
-            outLocalInsets.set(in.getSystemWindowInsets());
+            outLocalInsets.set(in.getSystemWindowInsetsAsRect());
             return in.consumeSystemWindowInsets().inset(outLocalInsets);
         } else {
             // The application wants to take care of fitting system window for
@@ -13094,6 +13509,9 @@
                         : AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_DISAPPEARED);
             }
         }
+        notifyNodeAddedOrRemovedForContentCaptureIfNeeded(isVisible
+                ? CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED
+                : CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED);
     }
 
     /**
@@ -13557,6 +13975,96 @@
     }
 
     /**
+     * Dispatching hover events to {@link TouchDelegate} to improve accessibility.
+     * <p>
+     * This method is dispatching hover events to the delegate target to support explore by touch.
+     * Similar to {@link ViewGroup#dispatchTouchEvent}, this method send proper hover events to
+     * the delegate target according to the pointer and the touch area of the delegate while touch
+     * exploration enabled.
+     * </p>
+     *
+     * @param event The motion event dispatch to the delegate target.
+     * @return True if the event was handled, false otherwise.
+     *
+     * @see #onHoverEvent
+     */
+    private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
+        final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
+        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
+            return false;
+        }
+
+        final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
+        final int action = event.getActionMasked();
+        boolean pointInDelegateRegion = false;
+        boolean handled = false;
+
+        final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
+        for (int i = 0; i < info.getRegionCount(); i++) {
+            Region r = info.getRegionAt(i);
+            if (r.contains((int) event.getX(), (int) event.getY())) {
+                pointInDelegateRegion = true;
+            }
+        }
+
+        // Explore by touch should dispatch events to children under the pointer first if any
+        // before dispatching to TouchDelegate. For non-hoverable views that do not consume
+        // hover events but receive accessibility focus, it should also not delegate to these
+        // views when hovered.
+        if (!oldHoveringTouchDelegate) {
+            if ((action == MotionEvent.ACTION_HOVER_ENTER
+                    || action == MotionEvent.ACTION_HOVER_MOVE)
+                    && !pointInHoveredChild(event)
+                    && pointInDelegateRegion) {
+                mHoveringTouchDelegate = true;
+            }
+        } else {
+            if (action == MotionEvent.ACTION_HOVER_EXIT
+                    || (action == MotionEvent.ACTION_HOVER_MOVE
+                        && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
+                mHoveringTouchDelegate = false;
+            }
+        }
+        switch (action) {
+            case MotionEvent.ACTION_HOVER_MOVE:
+                if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
+                    // Inside bounds, dispatch as is.
+                    handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
+                } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
+                    // Moving inbound, synthesize hover enter.
+                    MotionEvent eventNoHistory = (event.getHistorySize() == 0)
+                            ? event : MotionEvent.obtainNoHistory(event);
+                    eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
+                    handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
+                    eventNoHistory.setAction(action);
+                    handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
+                } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
+                    // Moving outbound, synthesize hover exit.
+                    final boolean hoverExitPending = event.isHoverExitPending();
+                    event.setHoverExitPending(true);
+                    mTouchDelegate.onTouchExplorationHoverEvent(event);
+                    MotionEvent eventNoHistory = (event.getHistorySize() == 0)
+                            ? event : MotionEvent.obtainNoHistory(event);
+                    eventNoHistory.setHoverExitPending(hoverExitPending);
+                    eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
+                    mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
+                }  // else: outside bounds, do nothing.
+                break;
+            case MotionEvent.ACTION_HOVER_ENTER:
+                if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
+                    handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
+                }
+                break;
+            case MotionEvent.ACTION_HOVER_EXIT:
+                if (oldHoveringTouchDelegate) {
+                    mTouchDelegate.onTouchExplorationHoverEvent(event);
+                }
+                break;
+        }
+        return handled;
+    }
+
+    /**
      * Implement this method to handle hover events.
      * <p>
      * This method is called whenever a pointer is hovering into, over, or out of the
@@ -13593,15 +14101,8 @@
      * @see #onHoverChanged
      */
     public boolean onHoverEvent(MotionEvent event) {
-        // Explore by touch should dispatch events to children under pointer first if any before
-        // dispatching to TouchDelegate. For children non-hoverable that will not consume events,
-        // it should also not delegate when they got the pointer hovered.
-        if (mTouchDelegate != null && !pointInHoveredChild(event)) {
-            final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
-            if (manager.isEnabled() && manager.isTouchExplorationEnabled()
-                    && mTouchDelegate.onTouchExplorationHoverEvent(event)) {
-                return true;
-            }
+        if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
+            return true;
         }
 
         // The root view may receive hover (or touch) events that are outside the bounds of
@@ -18630,6 +19131,8 @@
         }
 
         notifyEnterOrExitForAutoFillIfNeeded(false);
+        notifyNodeAddedOrRemovedForContentCaptureIfNeeded(
+                CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED);
     }
 
     /**
@@ -20934,6 +21437,13 @@
             mPrivateFlags3 &= ~PFLAG3_NOTIFY_AUTOFILL_ENTER_ON_LAYOUT;
             notifyEnterOrExitForAutoFillIfNeeded(true);
         }
+
+        if ((mViewFlags & VISIBILITY_MASK) == VISIBLE
+                && (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT) == 0) {
+            notifyNodeAddedOrRemovedForContentCaptureIfNeeded(
+                    CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED);
+            mPrivateFlags4 |= PFLAG4_NOTIFIED_CONTENT_CAPTURE_ON_LAYOUT;
+        }
     }
 
     private boolean hasParentWantsFocus() {
@@ -24122,7 +24632,7 @@
          * @param outShadowSize A {@link android.graphics.Point} containing the width and height
          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
-         * image.
+         * image. Since Android P, the width and height must be positive values.
          *
          * @param outShadowTouchPoint A {@link android.graphics.Point} for the position within the
          * shadow image that should be underneath the touch point during the drag and drop
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index dd1f640..484c6f3 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -46,6 +46,8 @@
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.FrameInfo;
+import android.graphics.HardwareRenderer.FrameDrawingCallback;
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
@@ -84,7 +86,6 @@
 import android.util.TypedValue;
 import android.view.Surface.OutOfResourcesException;
 import android.view.SurfaceControl.Transaction;
-import android.view.ThreadedRenderer.FrameDrawingCallback;
 import android.view.View.AttachInfo;
 import android.view.View.FocusDirection;
 import android.view.View.MeasureSpec;
@@ -1448,6 +1449,9 @@
             }
 
             if (mStopped) {
+                if (mSurfaceHolder != null) {
+                    notifySurfaceDestroyed();
+                }
                 destroySurface();
             }
         }
@@ -2148,7 +2152,7 @@
                     // relayoutWindow may decide to destroy mSurface. As that decision
                     // happens in WindowManager service, we need to be defensive here
                     // and stop using the surface in case it gets destroyed.
-                    if (mAttachInfo.mThreadedRenderer.pauseSurface(mSurface)) {
+                    if (mAttachInfo.mThreadedRenderer.pause()) {
                         // Animations were running so we need to push a frame
                         // to resume them
                         mDirty.set(0, 0, mWidth, mHeight);
@@ -2266,7 +2270,7 @@
                                         & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
                                     // Don't pre-allocate if transparent regions
                                     // are requested as they may not be needed
-                                    mAttachInfo.mThreadedRenderer.allocateBuffers(mSurface);
+                                    mAttachInfo.mThreadedRenderer.allocateBuffers();
                                 }
                             } catch (OutOfResourcesException e) {
                                 handleOutOfResourcesException(e);
@@ -2392,13 +2396,7 @@
                     }
                     mIsCreating = false;
                 } else if (hadSurface) {
-                    mSurfaceHolder.ungetCallbacks();
-                    SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
-                    if (callbacks != null) {
-                        for (SurfaceHolder.Callback c : callbacks) {
-                            c.surfaceDestroyed(mSurfaceHolder);
-                        }
-                    }
+                    notifySurfaceDestroyed();
                     mSurfaceHolder.mSurfaceLock.lock();
                     try {
                         mSurfaceHolder.mSurface = new Surface();
@@ -2666,6 +2664,16 @@
         mIsInTraversal = false;
     }
 
+    private void notifySurfaceDestroyed() {
+        mSurfaceHolder.ungetCallbacks();
+        SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
+        if (callbacks != null) {
+            for (SurfaceHolder.Callback c : callbacks) {
+                c.surfaceDestroyed(mSurfaceHolder);
+            }
+        }
+    }
+
     private void maybeHandleWindowMove(Rect frame) {
 
         // TODO: Well, we are checking whether the frame has changed similarly
@@ -2694,7 +2702,7 @@
         }
     }
 
-    private void handleWindowFocusChanged() {
+    private void handleWindowFocusChanged(boolean reportToClient) {
         final boolean hasWindowFocus;
         final boolean inTouchMode;
         synchronized (this) {
@@ -2729,8 +2737,9 @@
                         } catch (RemoteException ex) {
                         }
                         // Retry in a bit.
-                        mHandler.sendMessageDelayed(mHandler.obtainMessage(
-                                MSG_WINDOW_FOCUS_CHANGED), 500);
+                        final Message msg = mHandler.obtainMessage(MSG_WINDOW_FOCUS_CHANGED);
+                        msg.arg1 = reportToClient ? 1 : 0;
+                        mHandler.sendMessageDelayed(msg, 500);
                         return;
                     }
                 }
@@ -2747,9 +2756,15 @@
             }
             if (mView != null) {
                 mAttachInfo.mKeyDispatchState.reset();
-                mView.dispatchWindowFocusChanged(hasWindowFocus);
-                mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
-
+                // We dispatch onWindowFocusChanged to child view only when window is gaining /
+                // losing focus.
+                // If the focus is updated from top display change but window focus on the display
+                // remains unchanged, will not callback onWindowFocusChanged again since it may
+                // be redundant & can affect the state when it callbacks.
+                if (reportToClient) {
+                    mView.dispatchWindowFocusChanged(hasWindowFocus);
+                    mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
+                }
                 if (mAttachInfo.mTooltipHost != null) {
                     mAttachInfo.mTooltipHost.hideTooltip();
                 }
@@ -4339,7 +4354,7 @@
                     }
                     break;
                 case MSG_WINDOW_FOCUS_CHANGED: {
-                    handleWindowFocusChanged();
+                    handleWindowFocusChanged(msg.arg1 != 0 /* reportToClient */);
                 } break;
                 case MSG_DIE:
                     doDie();
@@ -7262,7 +7277,7 @@
         }
 
         if (stage != null) {
-            handleWindowFocusChanged();
+            handleWindowFocusChanged(true /* reportToClient */);
             stage.deliver(q);
         } else {
             finishInputEvent(q);
@@ -7579,6 +7594,11 @@
     }
 
     public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
+        windowFocusChanged(hasFocus, inTouchMode, true /* reportToClient */);
+    }
+
+    public void windowFocusChanged(boolean hasFocus, boolean inTouchMode,
+            boolean reportToClient) {
         synchronized (this) {
             mWindowFocusChanged = true;
             mUpcomingWindowFocus = hasFocus;
@@ -7586,6 +7606,7 @@
         }
         Message msg = Message.obtain();
         msg.what = MSG_WINDOW_FOCUS_CHANGED;
+        msg.arg1 = reportToClient ? 1 : 0;
         mHandler.sendMessage(msg);
     }
 
@@ -8130,10 +8151,11 @@
         }
 
         @Override
-        public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
+        public void windowFocusChanged(boolean hasFocus, boolean inTouchMode,
+                boolean reportToClient) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
-                viewAncestor.windowFocusChanged(hasFocus, inTouchMode);
+                viewAncestor.windowFocusChanged(hasFocus, inTouchMode, reportToClient);
             }
         }
 
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 38dcdd3..6efb6f3 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -24,7 +24,6 @@
 import android.os.LocaleList;
 import android.util.Pair;
 import android.view.View.AutofillImportance;
-import android.view.ViewStructure.HtmlInfo;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 8628da3..a8debbd 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -17,8 +17,10 @@
 
 package android.view;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
+import android.graphics.Insets;
 import android.graphics.Rect;
 
 import com.android.internal.util.Preconditions;
@@ -43,26 +45,24 @@
  */
 public final class WindowInsets {
 
-    private Rect mSystemWindowInsets;
-    private Rect mWindowDecorInsets;
-    private Rect mStableInsets;
-    private Rect mTempRect;
-    private boolean mIsRound;
-    private DisplayCutout mDisplayCutout;
+    @NonNull private final Insets mSystemWindowInsets;
+    @NonNull private final Insets mWindowDecorInsets;
+    @NonNull private final Insets mStableInsets;
+    @Nullable private Rect mTempRect;
+    private final boolean mIsRound;
+    @Nullable private final DisplayCutout mDisplayCutout;
 
     /**
      * In multi-window we force show the navigation bar. Because we don't want that the surface size
      * changes in this mode, we instead have a flag whether the navigation bar size should always
      * be consumed, so the app is treated like there is no virtual navigation bar at all.
      */
-    private boolean mAlwaysConsumeNavBar;
+    private final boolean mAlwaysConsumeNavBar;
 
-    private boolean mSystemWindowInsetsConsumed = false;
-    private boolean mWindowDecorInsetsConsumed = false;
-    private boolean mStableInsetsConsumed = false;
-    private boolean mDisplayCutoutConsumed = false;
-
-    private static final Rect EMPTY_RECT = new Rect(0, 0, 0, 0);
+    private final boolean mSystemWindowInsetsConsumed;
+    private final boolean mWindowDecorInsetsConsumed;
+    private final boolean mStableInsetsConsumed;
+    private final boolean mDisplayCutoutConsumed;
 
     /**
      * Since new insets may be added in the future that existing apps couldn't
@@ -74,21 +74,33 @@
     public static final WindowInsets CONSUMED;
 
     static {
-        CONSUMED = new WindowInsets(null, null, null, false, false, null);
+        CONSUMED = new WindowInsets((Insets) null, null, null, false, false, null);
     }
 
-    /** @hide */
+    /**
+     * Construct a new WindowInsets from individual insets.
+     *
+     * A {@code null} inset indicates that the respective inset is consumed.
+     *
+     * @hide
+     */
     public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets,
             boolean isRound, boolean alwaysConsumeNavBar, DisplayCutout displayCutout) {
+        this(insetsOrNull(systemWindowInsets), insetsOrNull(windowDecorInsets),
+                insetsOrNull(stableInsets), isRound, alwaysConsumeNavBar, displayCutout);
+    }
+
+    private WindowInsets(Insets systemWindowInsets, Insets windowDecorInsets,
+            Insets stableInsets, boolean isRound, boolean alwaysConsumeNavBar,
+            DisplayCutout displayCutout) {
         mSystemWindowInsetsConsumed = systemWindowInsets == null;
-        mSystemWindowInsets = mSystemWindowInsetsConsumed
-                ? EMPTY_RECT : new Rect(systemWindowInsets);
+        mSystemWindowInsets = mSystemWindowInsetsConsumed ? Insets.NONE : systemWindowInsets;
 
         mWindowDecorInsetsConsumed = windowDecorInsets == null;
-        mWindowDecorInsets = mWindowDecorInsetsConsumed ? EMPTY_RECT : new Rect(windowDecorInsets);
+        mWindowDecorInsets = mWindowDecorInsetsConsumed ? Insets.NONE : windowDecorInsets;
 
         mStableInsetsConsumed = stableInsets == null;
-        mStableInsets = mStableInsetsConsumed ? EMPTY_RECT : new Rect(stableInsets);
+        mStableInsets = mStableInsetsConsumed ? Insets.NONE : stableInsets;
 
         mIsRound = isRound;
         mAlwaysConsumeNavBar = alwaysConsumeNavBar;
@@ -104,16 +116,21 @@
      * @param src Source to copy insets from
      */
     public WindowInsets(WindowInsets src) {
-        mSystemWindowInsets = src.mSystemWindowInsets;
-        mWindowDecorInsets = src.mWindowDecorInsets;
-        mStableInsets = src.mStableInsets;
-        mSystemWindowInsetsConsumed = src.mSystemWindowInsetsConsumed;
-        mWindowDecorInsetsConsumed = src.mWindowDecorInsetsConsumed;
-        mStableInsetsConsumed = src.mStableInsetsConsumed;
-        mIsRound = src.mIsRound;
-        mAlwaysConsumeNavBar = src.mAlwaysConsumeNavBar;
-        mDisplayCutout = src.mDisplayCutout;
-        mDisplayCutoutConsumed = src.mDisplayCutoutConsumed;
+        this(src.mSystemWindowInsetsConsumed ? null : src.mSystemWindowInsets,
+                src.mWindowDecorInsetsConsumed ? null : src.mWindowDecorInsets,
+                src.mStableInsetsConsumed ? null : src.mStableInsets,
+                src.mIsRound, src.mAlwaysConsumeNavBar,
+                displayCutoutCopyConstructorArgument(src));
+    }
+
+    private static DisplayCutout displayCutoutCopyConstructorArgument(WindowInsets w) {
+        if (w.mDisplayCutoutConsumed) {
+            return null;
+        } else if (w.mDisplayCutout == null) {
+            return DisplayCutout.NO_CUTOUT;
+        } else {
+            return w.mDisplayCutout;
+        }
     }
 
     /** @hide */
@@ -126,22 +143,35 @@
      * Used to provide a safe copy of the system window insets to pass through
      * to the existing fitSystemWindows method and other similar internals.
      * @hide
+     *
+     * @deprecated use {@link #getSystemWindowInsets()} instead.
      */
-    @UnsupportedAppUsage
-    public Rect getSystemWindowInsets() {
+    @Deprecated
+    @NonNull
+    public Rect getSystemWindowInsetsAsRect() {
         if (mTempRect == null) {
             mTempRect = new Rect();
         }
-        if (mSystemWindowInsets != null) {
-            mTempRect.set(mSystemWindowInsets);
-        } else {
-            // If there were no system window insets, this is just empty.
-            mTempRect.setEmpty();
-        }
+        mTempRect.set(mSystemWindowInsets.left, mSystemWindowInsets.top,
+                mSystemWindowInsets.right, mSystemWindowInsets.bottom);
         return mTempRect;
     }
 
     /**
+     * Returns the system window insets in pixels.
+     *
+     * <p>The system window inset represents the area of a full-screen window that is
+     * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
+     * </p>
+     *
+     * @return The system window insets
+     */
+    @NonNull
+    public Insets getSystemWindowInsets() {
+        return mSystemWindowInsets;
+    }
+
+    /**
      * Returns the left system window inset in pixels.
      *
      * <p>The system window inset represents the area of a full-screen window that is
@@ -304,11 +334,13 @@
      *
      * @return A modified copy of this WindowInsets
      */
+    @NonNull
     public WindowInsets consumeDisplayCutout() {
-        final WindowInsets result = new WindowInsets(this);
-        result.mDisplayCutout = null;
-        result.mDisplayCutoutConsumed = true;
-        return result;
+        return new WindowInsets(mSystemWindowInsetsConsumed ? null : mSystemWindowInsets,
+                mWindowDecorInsetsConsumed ? null : mWindowDecorInsets,
+                mStableInsetsConsumed ? null : mStableInsets,
+                mIsRound, mAlwaysConsumeNavBar,
+                null /* displayCutout */);
     }
 
 
@@ -349,101 +381,95 @@
      *
      * @return A modified copy of this WindowInsets
      */
+    @NonNull
     public WindowInsets consumeSystemWindowInsets() {
-        final WindowInsets result = new WindowInsets(this);
-        result.mSystemWindowInsets = EMPTY_RECT;
-        result.mSystemWindowInsetsConsumed = true;
-        return result;
+        return new WindowInsets(null /* systemWindowInsets */,
+                mWindowDecorInsetsConsumed ? null : mWindowDecorInsets,
+                mStableInsetsConsumed ? null : mStableInsets,
+                mIsRound, mAlwaysConsumeNavBar,
+                displayCutoutCopyConstructorArgument(this));
     }
 
-    /**
-     * Returns a copy of this WindowInsets with selected system window insets fully consumed.
-     *
-     * @param left true to consume the left system window inset
-     * @param top true to consume the top system window inset
-     * @param right true to consume the right system window inset
-     * @param bottom true to consume the bottom system window inset
-     * @return A modified copy of this WindowInsets
-     * @hide pending API
-     */
-    public WindowInsets consumeSystemWindowInsets(boolean left, boolean top,
-            boolean right, boolean bottom) {
-        if (left || top || right || bottom) {
-            final WindowInsets result = new WindowInsets(this);
-            result.mSystemWindowInsets = new Rect(
-                    left ? 0 : mSystemWindowInsets.left,
-                    top ? 0 : mSystemWindowInsets.top,
-                    right ? 0 : mSystemWindowInsets.right,
-                    bottom ? 0 : mSystemWindowInsets.bottom);
-            return result;
-        }
-        return this;
-    }
-
+    // TODO(b/119190588): replace @code with @link below
     /**
      * Returns a copy of this WindowInsets with selected system window insets replaced
      * with new values.
      *
+     * <p>Note: If the system window insets are already consumed, this method will return them
+     * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to
+     * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of
+     * whether they were consumed, and this method returns invalid non-zero consumed insets.
+     *
      * @param left New left inset in pixels
      * @param top New top inset in pixels
      * @param right New right inset in pixels
      * @param bottom New bottom inset in pixels
      * @return A modified copy of this WindowInsets
+     * @deprecated use {@code Builder#Builder(WindowInsets)} with
+     *             {@link Builder#setSystemWindowInsets(Insets)} instead.
      */
-    public WindowInsets replaceSystemWindowInsets(int left, int top,
-            int right, int bottom) {
-        final WindowInsets result = new WindowInsets(this);
-        result.mSystemWindowInsets = new Rect(left, top, right, bottom);
-        return result;
+    @Deprecated
+    @NonNull
+    public WindowInsets replaceSystemWindowInsets(int left, int top, int right, int bottom) {
+        // Compat edge case: what should this do if the insets have already been consumed?
+        // On platforms prior to Q, the behavior was to override the insets with non-zero values,
+        // but leave them consumed, which is invalid (consumed insets must be zero).
+        // The behavior is now keeping them consumed and discarding the new insets.
+        if (mSystemWindowInsetsConsumed) {
+            return this;
+        }
+        return new Builder(this).setSystemWindowInsets(Insets.of(left, top, right, bottom)).build();
     }
 
+    // TODO(b/119190588): replace @code with @link below
     /**
      * Returns a copy of this WindowInsets with selected system window insets replaced
      * with new values.
      *
+     * <p>Note: If the system window insets are already consumed, this method will return them
+     * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to
+     * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of
+     * whether they were consumed, and this method returns invalid non-zero consumed insets.
+     *
      * @param systemWindowInsets New system window insets. Each field is the inset in pixels
      *                           for that edge
      * @return A modified copy of this WindowInsets
+     * @deprecated use {@code Builder#Builder(WindowInsets)} with
+     *             {@link Builder#setSystemWindowInsets(Insets)} instead.
      */
+    @Deprecated
+    @NonNull
     public WindowInsets replaceSystemWindowInsets(Rect systemWindowInsets) {
-        final WindowInsets result = new WindowInsets(this);
-        result.mSystemWindowInsets = new Rect(systemWindowInsets);
-        return result;
+        return replaceSystemWindowInsets(systemWindowInsets.left, systemWindowInsets.top,
+                systemWindowInsets.right, systemWindowInsets.bottom);
     }
 
     /**
      * @hide
      */
+    @NonNull
     public WindowInsets consumeWindowDecorInsets() {
-        final WindowInsets result = new WindowInsets(this);
-        result.mWindowDecorInsets.set(0, 0, 0, 0);
-        result.mWindowDecorInsetsConsumed = true;
-        return result;
+        return new WindowInsets(mSystemWindowInsetsConsumed ? null : mSystemWindowInsets,
+                null /* windowDecorInsets */,
+                mStableInsetsConsumed ? null : mStableInsets,
+                mIsRound, mAlwaysConsumeNavBar,
+                displayCutoutCopyConstructorArgument(this));
     }
 
     /**
-     * @hide
+     * Returns the stable insets in pixels.
+     *
+     * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+     * partially or fully obscured by the system UI elements.  This value does not change
+     * based on the visibility state of those elements; for example, if the status bar is
+     * normally shown, but temporarily hidden, the stable inset will still provide the inset
+     * associated with the status bar being shown.</p>
+     *
+     * @return The stable insets
      */
-    public WindowInsets consumeWindowDecorInsets(boolean left, boolean top,
-            boolean right, boolean bottom) {
-        if (left || top || right || bottom) {
-            final WindowInsets result = new WindowInsets(this);
-            result.mWindowDecorInsets = new Rect(left ? 0 : mWindowDecorInsets.left,
-                    top ? 0 : mWindowDecorInsets.top,
-                    right ? 0 : mWindowDecorInsets.right,
-                    bottom ? 0 : mWindowDecorInsets.bottom);
-            return result;
-        }
-        return this;
-    }
-
-    /**
-     * @hide
-     */
-    public WindowInsets replaceWindowDecorInsets(int left, int top, int right, int bottom) {
-        final WindowInsets result = new WindowInsets(this);
-        result.mWindowDecorInsets = new Rect(left, top, right, bottom);
-        return result;
+    @NonNull
+    public Insets getStableInsets() {
+        return mStableInsets;
     }
 
     /**
@@ -527,11 +553,13 @@
      *
      * @return A modified copy of this WindowInsets
      */
+    @NonNull
     public WindowInsets consumeStableInsets() {
-        final WindowInsets result = new WindowInsets(this);
-        result.mStableInsets = EMPTY_RECT;
-        result.mStableInsetsConsumed = true;
-        return result;
+        return new WindowInsets(mSystemWindowInsetsConsumed ? null : mSystemWindowInsets,
+                mWindowDecorInsetsConsumed ? null : mWindowDecorInsets,
+                null /* stableInsets */,
+                mIsRound, mAlwaysConsumeNavBar,
+                displayCutoutCopyConstructorArgument(this));
     }
 
     /**
@@ -555,8 +583,11 @@
      * Returns a copy of this instance inset in the given directions.
      *
      * @see #inset(int, int, int, int)
+     * @deprecated use {@link #inset(Insets)}
      * @hide
      */
+    @Deprecated
+    @NonNull
     public WindowInsets inset(Rect r) {
         return inset(r.left, r.top, r.right, r.bottom);
     }
@@ -564,6 +595,17 @@
     /**
      * Returns a copy of this instance inset in the given directions.
      *
+     * @see #inset(int, int, int, int)
+     * @hide
+     */
+    @NonNull
+    public WindowInsets inset(Insets insets) {
+        return inset(insets.left, insets.top, insets.right, insets.bottom);
+    }
+
+    /**
+     * Returns a copy of this instance inset in the given directions.
+     *
      * This is intended for dispatching insets to areas of the window that are smaller than the
      * current area.
      *
@@ -579,35 +621,27 @@
      * @param bottom the amount of insets to remove from the bottom. Must be non-negative.
      *
      * @return the inset insets
-     *
-     * @hide pending API
      */
-    @UnsupportedAppUsage
+    @NonNull
     public WindowInsets inset(int left, int top, int right, int bottom) {
         Preconditions.checkArgumentNonnegative(left);
         Preconditions.checkArgumentNonnegative(top);
         Preconditions.checkArgumentNonnegative(right);
         Preconditions.checkArgumentNonnegative(bottom);
 
-        WindowInsets result = new WindowInsets(this);
-        if (!result.mSystemWindowInsetsConsumed) {
-            result.mSystemWindowInsets =
-                    insetInsets(result.mSystemWindowInsets, left, top, right, bottom);
-        }
-        if (!result.mWindowDecorInsetsConsumed) {
-            result.mWindowDecorInsets =
-                    insetInsets(result.mWindowDecorInsets, left, top, right, bottom);
-        }
-        if (!result.mStableInsetsConsumed) {
-            result.mStableInsets = insetInsets(result.mStableInsets, left, top, right, bottom);
-        }
-        if (mDisplayCutout != null) {
-            result.mDisplayCutout = result.mDisplayCutout.inset(left, top, right, bottom);
-            if (result.mDisplayCutout.isEmpty()) {
-                result.mDisplayCutout = null;
-            }
-        }
-        return result;
+        return new WindowInsets(
+                mSystemWindowInsetsConsumed ? null :
+                        insetInsets(mSystemWindowInsets, left, top, right, bottom),
+                mWindowDecorInsetsConsumed ? null :
+                        insetInsets(mWindowDecorInsets, left, top, right, bottom),
+                mStableInsetsConsumed ? null :
+                        insetInsets(mStableInsets, left, top, right, bottom),
+                mIsRound, mAlwaysConsumeNavBar,
+                mDisplayCutoutConsumed
+                        ? null :
+                        mDisplayCutout == null
+                                ? DisplayCutout.NO_CUTOUT
+                                : mDisplayCutout.inset(left, top, right, bottom));
     }
 
     @Override
@@ -634,7 +668,7 @@
                 mWindowDecorInsetsConsumed, mStableInsetsConsumed, mDisplayCutoutConsumed);
     }
 
-    private static Rect insetInsets(Rect insets, int left, int top, int right, int bottom) {
+    private static Insets insetInsets(Insets insets, int left, int top, int right, int bottom) {
         int newLeft = Math.max(0, insets.left - left);
         int newTop = Math.max(0, insets.top - top);
         int newRight = Math.max(0, insets.right - right);
@@ -642,7 +676,11 @@
         if (newLeft == left && newTop == top && newRight == right && newBottom == bottom) {
             return insets;
         }
-        return new Rect(newLeft, newTop, newRight, newBottom);
+        return Insets.of(newLeft, newTop, newRight, newBottom);
+    }
+
+    private static Insets insetsOrNull(Rect insets) {
+        return insets != null ? Insets.of(insets) : null;
     }
 
     /**
@@ -651,4 +689,122 @@
     boolean isSystemWindowInsetsConsumed() {
         return mSystemWindowInsetsConsumed;
     }
+
+    /**
+     * Builder for WindowInsets.
+     */
+    public static class Builder {
+
+        private Insets mSystemWindowInsets;
+        private Insets mStableInsets;
+        private DisplayCutout mDisplayCutout;
+
+        private Insets mWindowDecorInsets;
+        private boolean mIsRound;
+        private boolean mAlwaysConsumeNavBar;
+
+        /**
+         * Creates a builder where all insets are initially consumed.
+         */
+        public Builder() {
+        }
+
+        /**
+         * Creates a builder where all insets are initialized from {@link WindowInsets}.
+         *
+         * @param insets the instance to initialize from.
+         */
+        public Builder(WindowInsets insets) {
+            mSystemWindowInsets = insets.mSystemWindowInsetsConsumed ? null
+                    : insets.mSystemWindowInsets;
+            mStableInsets = insets.mStableInsetsConsumed ? null : insets.mStableInsets;
+            mDisplayCutout = displayCutoutCopyConstructorArgument(insets);
+            mWindowDecorInsets =  insets.mWindowDecorInsetsConsumed ? null
+                    : insets.mWindowDecorInsets;
+            mIsRound = insets.mIsRound;
+            mAlwaysConsumeNavBar = insets.mAlwaysConsumeNavBar;
+        }
+
+        /**
+         * Sets system window insets in pixels.
+         *
+         * <p>The system window inset represents the area of a full-screen window that is
+         * partially or fully obscured by the status bar, navigation bar, IME or other system
+         * windows.</p>
+         *
+         * @see #getSystemWindowInsets()
+         * @return itself
+         */
+        @NonNull
+        public Builder setSystemWindowInsets(@NonNull Insets systemWindowInsets) {
+            Preconditions.checkNotNull(systemWindowInsets);
+            mSystemWindowInsets = systemWindowInsets;
+            return this;
+        }
+
+        /**
+         * Sets the stable insets in pixels.
+         *
+         * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
+         * partially or fully obscured by the system UI elements.  This value does not change
+         * based on the visibility state of those elements; for example, if the status bar is
+         * normally shown, but temporarily hidden, the stable inset will still provide the inset
+         * associated with the status bar being shown.</p>
+         *
+         * @see #getStableInsets()
+         * @return itself
+         */
+        @NonNull
+        public Builder setStableInsets(@NonNull Insets stableInsets) {
+            Preconditions.checkNotNull(stableInsets);
+            mStableInsets = stableInsets;
+            return this;
+        }
+
+        /**
+         * Sets the display cutout.
+         *
+         * @see #getDisplayCutout()
+         * @param displayCutout the display cutout or null if there is none
+         * @return itself
+         */
+        @NonNull
+        public Builder setDisplayCutout(@Nullable DisplayCutout displayCutout) {
+            mDisplayCutout = displayCutout != null ? displayCutout : DisplayCutout.NO_CUTOUT;
+            return this;
+        }
+
+        /** @hide */
+        @NonNull
+        public Builder setWindowDecorInsets(@NonNull Insets windowDecorInsets) {
+            Preconditions.checkNotNull(windowDecorInsets);
+            mWindowDecorInsets = windowDecorInsets;
+            return this;
+        }
+
+        /** @hide */
+        @NonNull
+        public Builder setRound(boolean round) {
+            mIsRound = round;
+            return this;
+        }
+
+        /** @hide */
+        @NonNull
+        public Builder setAlwaysConsumeNavBar(boolean alwaysConsumeNavBar) {
+            mAlwaysConsumeNavBar = alwaysConsumeNavBar;
+            return this;
+        }
+
+        /**
+         * Builds a {@link WindowInsets} instance.
+         *
+         * @return the {@link WindowInsets} instance.
+         */
+        @NonNull
+        public WindowInsets build() {
+            return new WindowInsets(mSystemWindowInsets, mWindowDecorInsets, mStableInsets,
+                    mIsRound, mAlwaysConsumeNavBar, mDisplayCutout);
+        }
+    }
 }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 2d77cb4..8d8a370 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -315,6 +315,36 @@
     @interface TransitionFlags {}
 
     /**
+     * Remove content mode: Indicates remove content mode is currently not defined.
+     * @hide
+     */
+    int REMOVE_CONTENT_MODE_UNDEFINED = 0;
+
+    /**
+     * Remove content mode: Indicates that when display is removed, all its activities will be moved
+     * to the primary display and the topmost activity should become focused.
+     * @hide
+     */
+    int REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY = 1;
+
+    /**
+     * Remove content mode: Indicates that when display is removed, all its stacks and tasks will be
+     * removed, all activities will be destroyed according to the usual lifecycle.
+     * @hide
+     */
+    int REMOVE_CONTENT_MODE_DESTROY = 2;
+
+    /**
+     * @hide
+     */
+    @IntDef(prefix = { "REMOVE_CONTENT_MODE_" }, value = {
+            REMOVE_CONTENT_MODE_UNDEFINED,
+            REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY,
+            REMOVE_CONTENT_MODE_DESTROY,
+    })
+    @interface RemoveContentMode {}
+
+    /**
      * Exception that is thrown when trying to add view whose
      * {@link LayoutParams} {@link LayoutParams#token}
      * is invalid.
@@ -422,6 +452,47 @@
     @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
     public Region getCurrentImeTouchRegion();
 
+    /**
+     * Sets that the display should show its content when non-secure keyguard is shown.
+     *
+     * @param displayId Display ID.
+     * @param shouldShow Indicates that the display should show its content when non-secure keyguard
+     *                  is shown.
+     * @see KeyguardManager#isDeviceSecure()
+     * @see KeyguardManager#isDeviceLocked()
+     * @hide
+     */
+    @TestApi
+    default void setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow) {
+    }
+
+    /**
+     * Sets that the display should show system decors.
+     * <p>
+     * System decors include status bar, navigation bar, launcher.
+     * </p>
+     *
+     * @param displayId The id of the display.
+     * @param shouldShow Indicates that the display should show system decors.
+     * @hide
+     */
+    @TestApi
+    default void setShouldShowSystemDecors(int displayId, boolean shouldShow) {
+    }
+
+    /**
+     * Sets that the display should show IME.
+     *
+     * @param displayId Display ID.
+     * @param shouldShow Indicates that the display should show IME.
+     * @see KeyguardManager#isDeviceSecure()
+     * @see KeyguardManager#isDeviceLocked()
+     * @hide
+     */
+    @TestApi
+    default void setShouldShowIme(int displayId, boolean shouldShow) {
+    }
+
     public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
         /**
          * X position for this window.  With the default gravity it is ignored.
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 2339d35..a102f6c 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -157,4 +157,30 @@
         }
         return null;
     }
+
+    @Override
+    public void setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow) {
+        try {
+            WindowManagerGlobal.getWindowManagerService()
+                    .setShouldShowWithInsecureKeyguard(displayId, shouldShow);
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public void setShouldShowSystemDecors(int displayId, boolean shouldShow) {
+        try {
+            WindowManagerGlobal.getWindowManagerService()
+                    .setShouldShowSystemDecors(displayId, shouldShow);
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public void setShouldShowIme(int displayId, boolean shouldShow) {
+        try {
+            WindowManagerGlobal.getWindowManagerService().setShouldShowIme(displayId, shouldShow);
+        } catch (RemoteException e) {
+        }
+    }
 }
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index a7d0cfb..88b9c80 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -21,6 +21,7 @@
 import android.Manifest;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.AccessibilityServiceInfo.FeedbackType;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -54,6 +55,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IntPair;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -117,6 +120,39 @@
     public static final String ACTION_CHOOSE_ACCESSIBILITY_BUTTON =
             "com.android.internal.intent.action.CHOOSE_ACCESSIBILITY_BUTTON";
 
+    /**
+     * Annotations for content flag of UI.
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true, prefix = { "FLAG_CONTENT_" }, value = {
+            FLAG_CONTENT_ICONS,
+            FLAG_CONTENT_TEXT,
+            FLAG_CONTENT_CONTROLS
+    })
+    public @interface ContentFlag {}
+
+    /**
+     * Use this flag to indicate the content of a UI that times out contains icons.
+     *
+     * @see #getRecommendedTimeoutMillis(int, int)
+     */
+    public static final int FLAG_CONTENT_ICONS = 1;
+
+    /**
+     * Use this flag to indicate the content of a UI that times out contains text.
+     *
+     * @see #getRecommendedTimeoutMillis(int, int)
+     */
+    public static final int FLAG_CONTENT_TEXT = 2;
+
+    /**
+     * Use this flag to indicate the content of a UI that times out contains interactive controls.
+     *
+     * @see #getRecommendedTimeoutMillis(int, int)
+     */
+    public static final int FLAG_CONTENT_CONTROLS = 4;
+
     @UnsupportedAppUsage
     static final Object sInstanceSync = new Object();
 
@@ -142,7 +178,8 @@
 
     int mRelevantEventTypes = AccessibilityEvent.TYPES_ALL_MASK;
 
-    int mMinimumUiTimeout;
+    int mInteractiveUiTimeout;
+    int mNonInteractiveUiTimeout;
 
     boolean mIsTouchExplorationEnabled;
 
@@ -304,7 +341,9 @@
         }
 
         @Override
-        public void notifyServicesStateChanged() {
+        public void notifyServicesStateChanged(long updatedUiTimeout) {
+            updateUiTimeout(updatedUiTimeout);
+
             final ArrayMap<AccessibilityServicesStateChangeListener, Handler> listeners;
             synchronized (mLock) {
                 if (mServicesStateChangeListeners.isEmpty()) {
@@ -326,11 +365,6 @@
         public void setRelevantEventTypes(int eventTypes) {
             mRelevantEventTypes = eventTypes;
         }
-
-        @Override
-        public void setMinimumUiTimeout(int uiTimeout) {
-            mMinimumUiTimeout = uiTimeout;
-        }
     };
 
     /**
@@ -840,16 +874,35 @@
     }
 
     /**
-     * Get the minimum timeout for changes to the UI needed by this user. Controls should remain
+     * Get the recommended timeout for changes to the UI needed by this user. Controls should remain
      * on the screen for at least this long to give users time to react. Some users may need
      * extra time to review the controls, or to reach them, or to activate assistive technology
      * to activate the controls automatically.
+     * <p>
+     * Use the combination of content flags to indicate contents of UI. For example, use
+     * {@code FLAG_CONTENT_ICONS | FLAG_CONTENT_TEXT} for message notification which contains
+     * icons and text, or use {@code FLAG_CONTENT_TEXT | FLAG_CONTENT_CONTROLS} for button dialog
+     * which contains text and button controls.
+     * <p/>
      *
-     * @return The minimum ui timeout for the current user in milliseconds.
-     * {@link Integer#MAX_VALUE} if timeout is infinite.
+     * @param originalTimeout The timeout appropriate for users with no accessibility needs.
+     * @param uiContentFlags The combination of flags {@link #FLAG_CONTENT_ICONS},
+     *                       {@link #FLAG_CONTENT_TEXT} or {@link #FLAG_CONTENT_CONTROLS} to
+     *                       indicate the contents of UI.
+     * @return The recommended UI timeout for the current user in milliseconds.
      */
-    public int getMinimumUiTimeoutMillis() {
-        return mMinimumUiTimeout;
+    public int getRecommendedTimeoutMillis(int originalTimeout, @ContentFlag int uiContentFlags) {
+        boolean hasControls = (uiContentFlags & FLAG_CONTENT_CONTROLS) != 0;
+        boolean hasIconsOrText = (uiContentFlags & FLAG_CONTENT_ICONS) != 0
+                || (uiContentFlags & FLAG_CONTENT_TEXT) != 0;
+        int recommendedTimeout = originalTimeout;
+        if (hasControls) {
+            recommendedTimeout = Math.max(recommendedTimeout, mInteractiveUiTimeout);
+        }
+        if (hasIconsOrText) {
+            recommendedTimeout = Math.max(recommendedTimeout, mNonInteractiveUiTimeout);
+        }
+        return recommendedTimeout;
     }
 
     /**
@@ -1192,7 +1245,7 @@
             final long userStateAndRelevantEvents = service.addClient(mClient, mUserId);
             setStateLocked(IntPair.first(userStateAndRelevantEvents));
             mRelevantEventTypes = IntPair.second(userStateAndRelevantEvents);
-            mMinimumUiTimeout = service.getMinimumUiTimeout();
+            updateUiTimeout(service.getRecommendedTimeoutMillis());
             mService = service;
         } catch (RemoteException re) {
             Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
@@ -1266,6 +1319,17 @@
     }
 
     /**
+     * Update interactive and non-interactive UI timeout.
+     *
+     * @param uiTimeout A pair of {@code int}s. First integer for interactive one, and second
+     *                  integer for non-interactive one.
+     */
+    private void updateUiTimeout(long uiTimeout) {
+        mInteractiveUiTimeout = IntPair.first(uiTimeout);
+        mNonInteractiveUiTimeout = IntPair.second(uiTimeout);
+    }
+
+    /**
      * Determines if the accessibility button within the system navigation area is supported.
      *
      * @return {@code true} if the accessibility button is supported on this device,
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index e129091..d7c8aed 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -3838,6 +3838,14 @@
                 return "ACTION_SCROLL_DOWN";
             case R.id.accessibilityActionScrollRight:
                 return "ACTION_SCROLL_RIGHT";
+            case R.id.accessibilityActionPageDown:
+                return "ACTION_PAGE_DOWN";
+            case R.id.accessibilityActionPageUp:
+                return "ACTION_PAGE_UP";
+            case R.id.accessibilityActionPageLeft:
+                return "ACTION_PAGE_LEFT";
+            case R.id.accessibilityActionPageRight:
+                return "ACTION_PAGE_RIGHT";
             case R.id.accessibilityActionSetProgress:
                 return "ACTION_SET_PROGRESS";
             case R.id.accessibilityActionContextClick:
@@ -4368,6 +4376,30 @@
                 new AccessibilityAction(R.id.accessibilityActionScrollRight);
 
         /**
+         * Action to move to the page above.
+         */
+        public static final AccessibilityAction ACTION_PAGE_UP =
+                new AccessibilityAction(R.id.accessibilityActionPageUp);
+
+        /**
+         * Action to move to the page below.
+         */
+        public static final AccessibilityAction ACTION_PAGE_DOWN =
+                new AccessibilityAction(R.id.accessibilityActionPageDown);
+
+        /**
+         * Action to move to the page left.
+         */
+        public static final AccessibilityAction ACTION_PAGE_LEFT =
+                new AccessibilityAction(R.id.accessibilityActionPageLeft);
+
+        /**
+         * Action to move to the page right.
+         */
+        public static final AccessibilityAction ACTION_PAGE_RIGHT =
+                new AccessibilityAction(R.id.accessibilityActionPageRight);
+
+        /**
          * Action that context clicks the node.
          */
         public static final AccessibilityAction ACTION_CONTEXT_CLICK =
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 61a8a1da..2767a82 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -76,5 +76,5 @@
     // System process only
     boolean sendFingerprintGesture(int gestureKeyCode);
 
-    int getMinimumUiTimeout();
+    long getRecommendedTimeoutMillis();
 }
diff --git a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
index d2ddca3..94b9ad1 100644
--- a/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManagerClient.aidl
@@ -26,9 +26,7 @@
 
     void setState(int stateFlags);
 
-    void notifyServicesStateChanged();
+    void notifyServicesStateChanged(long updatedUiTimeout);
 
     void setRelevantEventTypes(int eventTypes);
-
-    void setMinimumUiTimeout(int uiTimeout);
 }
diff --git a/core/java/android/view/inspector/ChildTraverser.java b/core/java/android/view/inspector/ChildTraverser.java
new file mode 100644
index 0000000..b775de5
--- /dev/null
+++ b/core/java/android/view/inspector/ChildTraverser.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import android.annotation.NonNull;
+
+/**
+ * Interface for visiting all the child nodes of an inspectable object.
+ *
+ * Inspectable objects may return a collection of children as an array, an {@link Iterable} or an
+ * {@link java.util.Iterator}. This provides a unified API for traversing across all the children
+ * of an inspectable node.
+ *
+ * This interface is consumed by {@link InspectionHelper#traverseChildren(Object, ChildTraverser)}
+ * and may be implemented as a lambda.
+ *
+ * @see InspectionHelper#traverseChildren(Object, ChildTraverser)
+ * @hide
+ */
+@FunctionalInterface
+public interface ChildTraverser {
+    /**
+     * Visit one child object of a parent inspectable object.
+     *
+     * The iteration interface will filter null values out before passing them to this method, but
+     * some child objects may not be inspectable. It is up to the implementor to determine their
+     * inspectablity and what to do with them.
+     *
+     * @param child A child object, guaranteed not to be null.
+     */
+    void traverseChild(@NonNull Object child);
+}
diff --git a/core/java/android/view/inspector/InspectableChildren.java b/core/java/android/view/inspector/InspectableChildren.java
new file mode 100644
index 0000000..de8fa29
--- /dev/null
+++ b/core/java/android/view/inspector/InspectableChildren.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a getter for an inspectable node's inspectable children.
+ *
+ * This annotation can be applied to any getter that returns a collection of objects, either an
+ * array, an {@link Iterable} or a {@link java.util.Iterator}. The getter may return null, which
+ * will be treated as an empty collection. Additionally, the inspector will discard any null
+ * entries in the collection.
+ *
+ * By default, this annotation is inherited. At runtime, the inspector introspects on the class
+ * hierachy and uses the annotated getter from the bottommost class, if different from any
+ * annoated getters of the parent class. If a class inherits from a parent class with an annotated
+ * getter, but does not include this annotation, the child class will be traversed using the
+ * getter annotated on the parent. This holds true even if the child class overrides the getter.
+ *
+ * @see InspectionHelper#traverseChildren(Object, ChildTraverser)
+ * @see InspectionHelper#hasChildTraversal()
+ * @hide
+ */
+@Target({METHOD})
+@Retention(SOURCE)
+public @interface InspectableChildren {
+}
diff --git a/core/java/android/view/inspector/InspectableNodeName.java b/core/java/android/view/inspector/InspectableNodeName.java
new file mode 100644
index 0000000..716409c
--- /dev/null
+++ b/core/java/android/view/inspector/InspectableNodeName.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marks the node name to display to a developer in the inspection tree.
+ *
+ * This annotation is optional to marking a class as inspectable. If it is omitted, the node name
+ * will be inferred using the semantics of {@link Class#getSimpleName()}. The fully qualified class
+ * name is always available in the tree, this is for display purposes only. If a class is inflated
+ * from XML and the tag it inflates from does not match its simple name, this annotation should be
+ * used to inform the inspector to display the XML tag name in the inspection tree view.
+ *
+ * This annotation does not inherit. If a class extends an annotated parent class, but does not
+ * annotate itself, its node name will be inferred from its Java name.
+ *
+ * @see InspectionHelper#getNodeName()
+ * @hide
+ */
+@Target({TYPE})
+@Retention(SOURCE)
+public @interface InspectableNodeName {
+    /**
+     * The display name for nodes of this type.
+     *
+     * @return The name for nodes of this type
+     */
+    String value();
+}
diff --git a/core/java/android/view/inspector/InspectableProperty.java b/core/java/android/view/inspector/InspectableProperty.java
new file mode 100644
index 0000000..b0fd503
--- /dev/null
+++ b/core/java/android/view/inspector/InspectableProperty.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a getter of a property on an inspectable node.
+ *
+ * This annotation is inherited by default. If a child class doesn't add it to a getter, but a
+ * parent class does, the property will be inspected, even if the child overrides the definition
+ * of the getter. If a child class defines a property of the same name of a property on the parent
+ * but on a different getter, the inspector will use the child's getter when inspecting instances
+ * of the child, and the parent's otherwise.
+ *
+ * @see InspectionHelper#mapProperties(PropertyMapper)
+ * @see InspectionHelper#readProperties(Object, PropertyReader)
+ * @hide
+ */
+@Target({METHOD})
+@Retention(SOURCE)
+public @interface InspectableProperty {
+    /**
+     * The name of the property.
+     *
+     * If left empty (the default), the property name will be inferred from the name of the getter
+     * method.
+     *
+     * @return The name of the property.
+     */
+    String value() default "";
+}
diff --git a/core/java/android/view/inspector/InspectionHelper.java b/core/java/android/view/inspector/InspectionHelper.java
new file mode 100644
index 0000000..27a9704
--- /dev/null
+++ b/core/java/android/view/inspector/InspectionHelper.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * An interface for companion objects used to inspect views.
+ *
+ * Inspection helpers only need to handle the properties, name and traversal of the specific class
+ * they are defined for, not anything from a parent class. At runtime, the inspector instantiates
+ * one instance of each inspection helper, and handles visiting them in the correct inheritance
+ * order for each type it inspects.
+ *
+ * Properties are read from the top of the type tree to the bottom, so that classes that override
+ * a property in their parent class can overwrite it in the reader. In general, properties will
+ * cleanly inherit through their getters, and the inspector runtime will read the properties of a
+ * parent class via the parent's inspection helper, and the child helper will only read properties
+ * added or changed since the parent was defined.
+ *
+ * Only one child traversal is considered for each class. If a descendant class defines a
+ * different child traversal than its parent, only the bottom traversal is used. If a class does
+ * not define its own child traversal, but one of its ancestors does, the bottom-most ancestor's
+ * traversal will be used.
+ *
+ * @param <T> The type of inspectable this helper operates on
+ * @hide
+ */
+public interface InspectionHelper<T> {
+    /**
+     * Map the string names of the properties this helper knows about to integer IDs.
+     *
+     * Each helper is responsible for storing the integer IDs of all its properties. This is the
+     * only method that is allowed to modify the stored IDs.
+     *
+     * Calling {@link #readProperties(T, PropertyReader)} before calling this results in
+     * undefined behavior.
+     *
+     * @param propertyMapper A {@link PropertyMapper} or lambda which maps string names to IDs.
+     */
+    void mapProperties(@NonNull PropertyMapper propertyMapper);
+
+    /**
+     * Read the values of an instance of this helper's type into a {@link PropertyReader}.
+     *
+     * This method needs to return the property IDs stored by
+     * {@link #mapProperties(PropertyMapper)}. Implementations should track if their properties
+     * have been mapped and throw a {@link UninitializedPropertyMapException} if this method is
+     * called before {mapProperties}.
+     *
+     * @param inspectable A object of type {@link T} to read the properties of.
+     * @param propertyReader An object which receives the property IDs and values.
+     */
+    void readProperties(@NonNull T inspectable, @NonNull PropertyReader propertyReader);
+
+    /**
+     * Query if this inspectable type can potentially have child nodes.
+     *
+     * E.g.: any descendant of {@link android.view.ViewGroup} can have child nodes, but a leaf
+     * view like {@link android.widget.ImageView} may not.
+     *
+     * The default implementation always returns false. If an implementing class overrides this, it
+     * should also define {@link #traverseChildren(T, ChildTraverser)}.
+     *
+     * @return True if this inspectable type can potentially have child nodes, false otherwise.
+     */
+    default boolean hasChildTraversal() {
+        return false;
+    }
+
+    /**
+     * Traverse the child nodes of an instance of this helper's type into a {@link ChildTraverser}.
+     *
+     * This provides the ability to traverse over a variety of collection APIs (e.g.: arrays,
+     * {@link Iterable}, or {@link java.util.Iterator}) in a uniform fashion. The traversal must be
+     * in the order defined by this helper's type. If the getter returns null, the helper must
+     * treat it as an empty collection.
+     *
+     * The default implementation throws a {@link NoChildTraversalException}. If
+     * {@link #hasChildTraversal()} returns is overriden to return true, it is expected that the
+     * implementing class will also override this method and provide a traversal.
+     *
+     * @param inspectable An object of type {@link T} to traverse the child nodes of.
+     * @param childTraverser A {@link ChildTraverser} or lamba to receive the children in order.
+     * @throws NoChildTraversalException If there is no defined child traversal
+     */
+    default void traverseChildren(
+            @NonNull T inspectable,
+            @SuppressWarnings("unused") @NonNull ChildTraverser childTraverser) {
+        throw new NoChildTraversalException(inspectable.getClass());
+    }
+
+    /**
+     * Get an optional name to display to developers for inspection nodes of this helper's type.
+     *
+     * The default implementation returns null, which will cause the runtime to use the class's
+     * simple name as defined by {@link Class#getSimpleName()} as the node name.
+     *
+     * If the type of this helper is inflated from XML, this method should be overridden to return
+     * the string used as the tag name for this type in XML.
+     *
+     * @return A string to use as the node name, or null to use the simple class name fallback.
+     */
+    @Nullable
+    default String getNodeName() {
+        return null;
+    }
+
+    /**
+     * Thrown by {@link #readProperties(Object, PropertyReader)} if called before
+     * {@link #mapProperties(PropertyMapper)}.
+     */
+    class UninitializedPropertyMapException extends RuntimeException {
+        public UninitializedPropertyMapException() {
+            super("Unable to read properties of an inspectable before mapping their IDs.");
+        }
+    }
+
+    /**
+     * Thrown by {@link #traverseChildren(Object, ChildTraverser)} if no child traversal exists.
+     */
+    class NoChildTraversalException extends RuntimeException {
+        public NoChildTraversalException(Class cls) {
+            super(String.format(
+                    "Class %s does not have a defined child traversal. Cannot traverse children.",
+                    cls.getCanonicalName()
+            ));
+        }
+    }
+}
diff --git a/core/java/android/view/inspector/OWNERS b/core/java/android/view/inspector/OWNERS
new file mode 100644
index 0000000..0473f54
--- /dev/null
+++ b/core/java/android/view/inspector/OWNERS
@@ -0,0 +1,3 @@
+alanv@google.com
+ashleyrose@google.com
+aurimas@google.com
\ No newline at end of file
diff --git a/core/java/android/view/inspector/PropertyMapper.java b/core/java/android/view/inspector/PropertyMapper.java
new file mode 100644
index 0000000..35550bd
--- /dev/null
+++ b/core/java/android/view/inspector/PropertyMapper.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import android.annotation.NonNull;
+
+/**
+ * An interface for mapping the string names of inspectable properties to integer identifiers.
+ *
+ * This interface is consumed by {@link InspectionHelper#mapProperties(PropertyMapper)}.
+ *
+ * Mapping properties to IDs enables quick comparisons against shadow copies of inspectable
+ * objects without performing a large number of string comparisons.
+ *
+ * @see InspectionHelper#mapProperties(PropertyMapper)
+ * @hide
+ */
+public interface PropertyMapper {
+    /**
+     * Map a string name to an integer ID for a primitive boolean property.
+     *
+     * @param name The name of the property
+     * @return An integer ID for the property
+     * @throws PropertyConflictException If the property name is already mapped as another type.
+     */
+    int mapBoolean(@NonNull String name);
+
+    /**
+     * Map a string name to an integer ID for a primitive byte property.
+     *
+     * @param name The name of the property
+     * @return An integer ID for the property
+     * @throws PropertyConflictException If the property name is already mapped as another type.
+     */
+    int mapByte(@NonNull String name);
+
+    /**
+     * Map a string name to an integer ID for a primitive char property.
+     *
+     * @param name The name of the property
+     * @return An integer ID for the property
+     * @throws PropertyConflictException If the property name is already mapped as another type.
+     */
+    int mapChar(@NonNull String name);
+
+    /**
+     * Map a string name to an integer ID for a primitive double property.
+     *
+     * @param name The name of the property
+     * @return An integer ID for the property
+     * @throws PropertyConflictException If the property name is already mapped as another type.
+     */
+    int mapDouble(@NonNull String name);
+
+    /**
+     * Map a string name to an integer ID for a primitive float property.
+     *
+     * @param name The name of the property
+     * @return An integer ID for the property
+     * @throws PropertyConflictException If the property name is already mapped as another type.
+     */
+    int mapFloat(@NonNull String name);
+
+    /**
+     * Map a string name to an integer ID for a primitive int property.
+     *
+     * @param name The name of the property
+     * @return An integer ID for the property
+     * @throws PropertyConflictException If the property name is already mapped as another type.
+     */
+    int mapInt(@NonNull String name);
+
+    /**
+     * Map a string name to an integer ID for a primitive long property.
+     *
+     * @param name The name of the property
+     * @return An integer ID for the property
+     * @throws PropertyConflictException If the property name is already mapped as another type.
+     */
+    int mapLong(@NonNull String name);
+
+    /**
+     * Map a string name to an integer ID for a primitive short property.
+     *
+     * @param name The name of the property
+     * @return An integer ID for the property
+     * @throws PropertyConflictException If the property name is already mapped as another type.
+     */
+    int mapShort(@NonNull String name);
+
+    /**
+     * Map a string name to an integer ID for an object property.
+     *
+     * @param name The name of the property
+     * @return An integer ID for the property
+     * @throws PropertyConflictException If the property name is already mapped as another type.
+     */
+    int mapObject(@NonNull String name);
+
+    /**
+     * Thrown from a map method if a property name is already mapped as different type.
+     */
+    class PropertyConflictException extends RuntimeException {
+        public PropertyConflictException(
+                @NonNull String name,
+                @NonNull String newPropertyType,
+                @NonNull String existingPropertyType) {
+            super(String.format(
+                    "Attempted to map property \"%s\" as type %s, but it is already mapped as %s.",
+                    name,
+                    newPropertyType,
+                    existingPropertyType
+            ));
+        }
+    }
+}
diff --git a/core/java/android/view/inspector/PropertyReader.java b/core/java/android/view/inspector/PropertyReader.java
new file mode 100644
index 0000000..df81c10
--- /dev/null
+++ b/core/java/android/view/inspector/PropertyReader.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inspector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * An interface for reading the properties of an inspectable object.
+ *
+ * Used as the parameter for {@link InspectionHelper#readProperties(Object, PropertyReader)}.
+ * It has separate methods for all primitive types to avoid autoboxing overhead if a concrete
+ * implementation is able to work with primitives. Implementations should be prepared to accept
+ * {null} as the value of {@link PropertyReader#readObject(int, Object)}.
+ *
+ * @see InspectionHelper#readProperties(Object, PropertyReader)
+ * @hide
+ */
+public interface PropertyReader {
+    /**
+     * Read a primitive boolean property.
+     *
+     * @param id Identifier of the property from a {@link PropertyMapper}
+     * @param value Value of the property
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {boolean}
+     */
+    void readBoolean(int id, boolean value);
+
+    /**
+     * Read a primitive byte property.
+     *
+     * @param id Identifier of the property from a {@link PropertyMapper}
+     * @param value Value of the property
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {byte}
+     */
+    void readByte(int id, byte value);
+
+    /**
+     * Read a primitive character property.
+     *
+     * @param id Identifier of the property from a {@link PropertyMapper}
+     * @param value Value of the property
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {char}
+     */
+    void readChar(int id, char value);
+
+    /**
+     * Read a read a primitive double property.
+     *
+     * @param id Identifier of the property from a {@link PropertyMapper}
+     * @param value Value of the property
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {double}
+     */
+    void readDouble(int id, double value);
+
+    /**
+     * Read a primitive float property.
+     *
+     * @param id Identifier of the property from a {@link PropertyMapper}
+     * @param value Value of the property
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {float}
+     */
+    void readFloat(int id, float value);
+
+    /**
+     * Read a primitive integer property.
+     *
+     * @param id Identifier of the property from a {@link PropertyMapper}
+     * @param value Value of the property
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as an {int}
+     */
+    void readInt(int id, int value);
+
+    /**
+     * Read a primitive long property.
+     *
+     * @param id Identifier of the property from a {@link PropertyMapper}
+     * @param value Value of the property
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {long}
+     */
+    void readLong(int id, long value);
+
+    /**
+     * Read a primitive short property.
+     *
+     * @param id Identifier of the property from a {@link PropertyMapper}
+     * @param value Value of the property
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as a {short}
+     */
+    void readShort(int id, short value);
+
+    /**
+     * Read any object as a property.
+     *
+     * If value is null, the property is marked as empty.
+     *
+     * @param id Identifier of the property from a {@link PropertyMapper}
+     * @param value Value of the property
+     * @throws PropertyTypeMismatchException If the property ID is not mapped as an object
+     */
+    void readObject(int id, @Nullable Object value);
+
+    /**
+     * Thrown if a client calls a typed read method for a property of a different type.
+     */
+    class PropertyTypeMismatchException extends RuntimeException {
+        public PropertyTypeMismatchException(
+                int id,
+                @NonNull String expectedPropertyType,
+                @NonNull String actualPropertyType,
+                @Nullable String propertyName) {
+            super(formatMessage(id, expectedPropertyType, actualPropertyType, propertyName));
+        }
+
+        public PropertyTypeMismatchException(
+                int id,
+                @NonNull String expectedPropertyType,
+                @NonNull String actualPropertyType) {
+            super(formatMessage(id, expectedPropertyType, actualPropertyType, null));
+        }
+
+        private static @NonNull String formatMessage(
+                int id,
+                @NonNull String expectedPropertyType,
+                @NonNull String actualPropertyType,
+                @Nullable String propertyName) {
+
+            if (propertyName == null) {
+                return String.format(
+                        "Attempted to read property with ID 0x%08X as type %s, "
+                            + "but the ID is of type %s.",
+                        id,
+                        expectedPropertyType,
+                        actualPropertyType
+                );
+            } else {
+                return String.format(
+                        "Attempted to read property \"%s\" with ID 0x%08X as type %s, "
+                            + "but the ID is of type %s.",
+                        propertyName,
+                        id,
+                        expectedPropertyType,
+                        actualPropertyType
+                );
+            }
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/core/java/android/view/intelligence/ContentCaptureEvent.aidl
similarity index 85%
rename from telephony/java/com/android/internal/telephony/IRcs.aidl
rename to core/java/android/view/intelligence/ContentCaptureEvent.aidl
index ede8695..c66a6cb 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/core/java/android/view/intelligence/ContentCaptureEvent.aidl
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package android.view.intelligence;
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+parcelable ContentCaptureEvent;
diff --git a/core/java/android/view/intelligence/ContentCaptureEvent.java b/core/java/android/view/intelligence/ContentCaptureEvent.java
index b8330e5..befcb55 100644
--- a/core/java/android/view/intelligence/ContentCaptureEvent.java
+++ b/core/java/android/view/intelligence/ContentCaptureEvent.java
@@ -16,12 +16,17 @@
 package android.view.intelligence;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 import android.view.autofill.AutofillId;
 
+import com.android.internal.util.Preconditions;
+
+import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -30,6 +35,11 @@
 @SystemApi
 public final class ContentCaptureEvent implements Parcelable {
 
+    /** @hide */
+    public static final int TYPE_ACTIVITY_DESTROYED = -2;
+    /** @hide */
+    public static final int TYPE_ACTIVITY_CREATED = -1;
+
     /**
      * Called when the activity is started.
      */
@@ -55,14 +65,14 @@
      *
      * <p>The metadata of the node is available through {@link #getViewNode()}.
      */
-    public static final int TYPE_VIEW_ADDED = 5;
+    public static final int TYPE_VIEW_APPEARED = 5;
 
     /**
      * Called when a node has been removed from the screen and is not visible to the user anymore.
      *
      * <p>The id of the node is available through {@link #getId()}.
      */
-    public static final int TYPE_VIEW_REMOVED = 6;
+    public static final int TYPE_VIEW_DISAPPEARED = 6;
 
     /**
      * Called when the text of a node has been changed.
@@ -80,15 +90,54 @@
             TYPE_ACTIVITY_PAUSED,
             TYPE_ACTIVITY_RESUMED,
             TYPE_ACTIVITY_STOPPED,
-            TYPE_VIEW_ADDED,
-            TYPE_VIEW_REMOVED,
+            TYPE_VIEW_APPEARED,
+            TYPE_VIEW_DISAPPEARED,
             TYPE_VIEW_TEXT_CHANGED
     })
     @Retention(RetentionPolicy.SOURCE)
-    @interface EventType{}
+    public @interface EventType{}
+
+    private final int mType;
+    private final long mEventTime;
+    private final int mFlags;
+    private @Nullable AutofillId mId;
+    private @Nullable ViewNode mNode;
+    private @Nullable CharSequence mText;
 
     /** @hide */
-    ContentCaptureEvent() {
+    public ContentCaptureEvent(int type, long eventTime, int flags) {
+        mType = type;
+        mEventTime = eventTime;
+        mFlags = flags;
+    }
+
+
+    /** @hide */
+    public ContentCaptureEvent(int type, int flags) {
+        this(type, SystemClock.uptimeMillis(), flags);
+    }
+
+    /** @hide */
+    public ContentCaptureEvent(int type) {
+        this(type, /* flags= */ 0);
+    }
+
+    /** @hide */
+    public ContentCaptureEvent setAutofillId(@NonNull AutofillId id) {
+        mId = Preconditions.checkNotNull(id);
+        return this;
+    }
+
+    /** @hide */
+    public ContentCaptureEvent setViewNode(@NonNull ViewNode node) {
+        mNode = Preconditions.checkNotNull(node);
+        return this;
+    }
+
+    /** @hide */
+    public ContentCaptureEvent setText(@Nullable CharSequence text) {
+        mText = text;
+        return this;
     }
 
     /**
@@ -96,17 +145,18 @@
      *
      * @return one of {@link #TYPE_ACTIVITY_STARTED}, {@link #TYPE_ACTIVITY_RESUMED},
      * {@link #TYPE_ACTIVITY_PAUSED}, {@link #TYPE_ACTIVITY_STOPPED},
-     * {@link #TYPE_VIEW_ADDED}, {@link #TYPE_VIEW_REMOVED}, or {@link #TYPE_VIEW_TEXT_CHANGED}.
+     * {@link #TYPE_VIEW_APPEARED}, {@link #TYPE_VIEW_DISAPPEARED},
+     * or {@link #TYPE_VIEW_TEXT_CHANGED}.
      */
     public @EventType int getType() {
-        return 42;
+        return mType;
     }
 
     /**
      * Gets when the event was generated, in ms.
      */
     public long getEventTime() {
-        return 48151623;
+        return mEventTime;
     }
 
     /**
@@ -116,27 +166,27 @@
      * {@link android.view.intelligence.IntelligenceManager#FLAG_USER_INPUT}.
      */
     public int getFlags() {
-        return 0;
+        return mFlags;
     }
 
     /**
      * Gets the whole metadata of the node associated with the event.
      *
-     * <p>Only set on {@link #TYPE_VIEW_ADDED} events.
+     * <p>Only set on {@link #TYPE_VIEW_APPEARED} events.
      */
     @Nullable
     public ViewNode getViewNode() {
-        return null;
+        return mNode;
     }
 
     /**
      * Gets the {@link AutofillId} of the node associated with the event.
      *
-     * <p>Only set on {@link #TYPE_VIEW_REMOVED} and {@link #TYPE_VIEW_TEXT_CHANGED} events.
+     * <p>Only set on {@link #TYPE_VIEW_DISAPPEARED} and {@link #TYPE_VIEW_TEXT_CHANGED} events.
      */
     @Nullable
     public AutofillId getId() {
-        return null;
+        return mId;
     }
 
     /**
@@ -146,9 +196,43 @@
      */
     @Nullable
     public CharSequence getText() {
-        return null;
+        return mText;
     }
 
+    /** @hide */
+    public void dump(@NonNull PrintWriter pw) {
+        pw.print("type="); pw.print(getTypeAsString(mType));
+        pw.print(", time="); pw.print(mEventTime);
+        if (mFlags > 0) {
+            pw.print(", flags="); pw.print(mFlags);
+        }
+        if (mId != null) {
+            pw.print(", id="); pw.print(mId);
+        }
+        if (mNode != null) {
+            pw.print(", id="); pw.print(mNode.getAutofillId());
+        }
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder string = new StringBuilder("ContentCaptureEvent[type=")
+                .append(getTypeAsString(mType));
+        if (mFlags > 0) {
+            string.append(", flags=").append(mFlags);
+        }
+        if (mId != null) {
+            string.append(", id=").append(mId);
+        }
+        if (mNode != null) {
+            final String className = mNode.getClassName();
+            if (mNode != null) {
+                string.append(", class=").append(className);
+            }
+            string.append(", id=").append(mNode.getAutofillId());
+        }
+        return string.append(']').toString();
+    }
 
     @Override
     public int describeContents() {
@@ -157,6 +241,12 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeInt(mType);
+        parcel.writeLong(mEventTime);
+        parcel.writeInt(mFlags);
+        parcel.writeParcelable(mId, flags);
+        ViewNode.writeToParcel(parcel, mNode, flags);
+        parcel.writeCharSequence(mText);
     }
 
     public static final Parcelable.Creator<ContentCaptureEvent> CREATOR =
@@ -164,8 +254,20 @@
 
         @Override
         public ContentCaptureEvent createFromParcel(Parcel parcel) {
-            // TODO(b/111276913): implement
-            return null;
+            final int type = parcel.readInt();
+            final long eventTime  = parcel.readLong();
+            final int flags = parcel.readInt();
+            final ContentCaptureEvent event = new ContentCaptureEvent(type, eventTime, flags);
+            final AutofillId id = parcel.readParcelable(null);
+            if (id != null) {
+                event.setAutofillId(id);
+            }
+            final ViewNode node = ViewNode.readFromParcel(parcel);
+            if (node != null) {
+                event.setViewNode(node);
+            }
+            event.setText(parcel.readCharSequence());
+            return event;
         }
 
         @Override
@@ -173,4 +275,26 @@
             return new ContentCaptureEvent[size];
         }
     };
+
+    /** @hide */
+    public static String getTypeAsString(@EventType int type) {
+        switch (type) {
+            case TYPE_ACTIVITY_STARTED:
+                return "ACTIVITY_STARTED";
+            case TYPE_ACTIVITY_RESUMED:
+                return "ACTIVITY_RESUMED";
+            case TYPE_ACTIVITY_PAUSED:
+                return "ACTIVITY_PAUSED";
+            case TYPE_ACTIVITY_STOPPED:
+                return "ACTIVITY_STOPPED";
+            case TYPE_VIEW_APPEARED:
+                return "VIEW_APPEARED";
+            case TYPE_VIEW_DISAPPEARED:
+                return "VIEW_DISAPPEARED";
+            case TYPE_VIEW_TEXT_CHANGED:
+                return "VIEW_TEXT_CHANGED";
+            default:
+                return "UKNOWN_TYPE: " + type;
+        }
+    }
 }
diff --git a/core/java/android/view/intelligence/IIntelligenceManager.aidl b/core/java/android/view/intelligence/IIntelligenceManager.aidl
new file mode 100644
index 0000000..2f128de
--- /dev/null
+++ b/core/java/android/view/intelligence/IIntelligenceManager.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.intelligence;
+
+import android.content.ComponentName;
+import android.os.IBinder;
+import android.service.intelligence.InteractionSessionId;
+import android.view.intelligence.ContentCaptureEvent;
+
+import com.android.internal.os.IResultReceiver;
+
+import java.util.List;
+
+/**
+ * {@hide}
+ */
+oneway interface IIntelligenceManager {
+    /**
+      * Starts a session, sending the "remote" sessionId to the receiver.
+      */
+    void startSession(int userId, IBinder activityToken, in ComponentName componentName,
+                      in InteractionSessionId sessionId, int flags, in IResultReceiver result);
+
+    /**
+      * Finishes a session.
+      */
+    void finishSession(int userId, in InteractionSessionId sessionId);
+
+    /**
+      * Sends a batch of events
+      */
+    void sendEvents(int userId, in InteractionSessionId sessionId,
+                    in List<ContentCaptureEvent> events);
+}
diff --git a/core/java/android/view/intelligence/IntelligenceManager.java b/core/java/android/view/intelligence/IntelligenceManager.java
index 5513ce2f..242bf6a 100644
--- a/core/java/android/view/intelligence/IntelligenceManager.java
+++ b/core/java/android/view/intelligence/IntelligenceManager.java
@@ -15,32 +15,358 @@
  */
 package android.view.intelligence;
 
+import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_APPEARED;
+import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
+import static android.view.intelligence.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.ComponentName;
 import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.service.intelligence.InteractionSessionId;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewStructure;
+import android.view.autofill.AutofillId;
+import android.view.intelligence.ContentCaptureEvent.EventType;
 
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.IResultReceiver;
 import com.android.internal.util.Preconditions;
 
+import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Set;
 
 /**
- * TODO(b/111276913): add javadocs / implement / add SystemService / PackageFeature
+ * TODO(b/111276913): add javadocs / implement
  */
+@SystemService(Context.INTELLIGENCE_MANAGER_SERVICE)
 public final class IntelligenceManager {
 
+    private static final String TAG = "IntelligenceManager";
+
+    // TODO(b/111276913): define a way to dynamically set them(for example, using settings?)
+    private static final boolean VERBOSE = false;
+    private static final boolean DEBUG = true; // STOPSHIP if not set to false
+
     /**
      * Used to indicate that a text change was caused by user input (for example, through IME).
      */
     //TODO(b/111276913): link to notifyTextChanged() method once available
     public static final int FLAG_USER_INPUT = 0x1;
 
+    /**
+     * Initial state, when there is no session.
+     *
+     * @hide
+     */
+    public static final int STATE_UNKNOWN = 0;
+
+    /**
+     * Service's startSession() was called, but server didn't confirm it was created yet.
+     *
+     * @hide
+     */
+    public static final int STATE_WAITING_FOR_SERVER = 1;
+
+    /**
+     * Session is active.
+     *
+     * @hide
+     */
+    public static final int STATE_ACTIVE = 2;
+
+    /**
+     * Session is disabled.
+     *
+     * @hide
+     */
+    public static final int STATE_DISABLED = 3;
+
+    private static final String BG_THREAD_NAME = "intel_svc_streamer_thread";
+
+    /**
+     * Maximum number of events that are delayed for an app.
+     *
+     * <p>If the session is not started after the limit is reached, it's discarded.
+     */
+    private static final int MAX_DELAYED_SIZE = 20;
+
     private final Context mContext;
 
+    @Nullable
+    private final IIntelligenceManager mService;
+
+    private final Object mLock = new Object();
+
+    @Nullable
+    @GuardedBy("mLock")
+    private InteractionSessionId mId;
+
+    @GuardedBy("mLock")
+    private int mState = STATE_UNKNOWN;
+
+    @GuardedBy("mLock")
+    private IBinder mApplicationToken;
+
+    // TODO(b/111276913): replace by an interface name implemented by Activity, similar to
+    // AutofillClient
+    @GuardedBy("mLock")
+    private ComponentName mComponentName;
+
+    // TODO(b/111276913): create using maximum batch size as capacity
+    /**
+     * List of events held to be sent as a batch.
+     */
+    @GuardedBy("mLock")
+    private final ArrayList<ContentCaptureEvent> mEvents = new ArrayList<>();
+
+    private final Handler mHandler;
+
     /** @hide */
-    public IntelligenceManager(@NonNull Context context) {
+    public IntelligenceManager(@NonNull Context context, @Nullable IIntelligenceManager service) {
         mContext = Preconditions.checkNotNull(context, "context cannot be null");
+        mService = service;
+
+        // TODO(b/111276913): use an existing bg thread instead...
+        final HandlerThread bgThread = new HandlerThread(BG_THREAD_NAME);
+        bgThread.start();
+        mHandler = Handler.createAsync(bgThread.getLooper());
+    }
+
+    /** @hide */
+    public void onActivityCreated(@NonNull IBinder token, @NonNull ComponentName componentName) {
+        if (!isContentCaptureEnabled()) return;
+
+        synchronized (mLock) {
+            if (mState != STATE_UNKNOWN) {
+                // TODO(b/111276913): revisit this scenario
+                Log.w(TAG, "ignoring onActivityStarted(" + token + ") while on state "
+                        + getStateAsString(mState));
+                return;
+            }
+            mState = STATE_WAITING_FOR_SERVER;
+            mId = new InteractionSessionId();
+            mApplicationToken = token;
+            mComponentName = componentName;
+
+            if (VERBOSE) {
+                Log.v(TAG, "onActivityCreated(): token=" + token + ", act="
+                        + getActivityDebugNameLocked() + ", id=" + mId);
+            }
+            final int flags = 0; // TODO(b/111276913): get proper flags
+
+            try {
+                mService.startSession(mContext.getUserId(), mApplicationToken, componentName,
+                        mId, flags, new IResultReceiver.Stub() {
+                            @Override
+                            public void send(int resultCode, Bundle resultData)
+                                    throws RemoteException {
+                                synchronized (mLock) {
+                                    mState = resultCode;
+                                    if (VERBOSE) {
+                                        Log.v(TAG, "onActivityStarted() result: code=" + resultCode
+                                                + ", id=" + mId
+                                                + ", state=" + getStateAsString(mState));
+                                    }
+                                }
+                            }
+                        });
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    //TODO(b/111276913): should buffer event (and call service on handler thread), instead of
+    // calling right away
+    private void sendEvent(@NonNull ContentCaptureEvent event) {
+        mHandler.sendMessage(obtainMessage(IntelligenceManager::handleSendEvent, this, event));
+    }
+
+    private void handleSendEvent(@NonNull ContentCaptureEvent event) {
+
+        //TODO(b/111276913): make a copy and don't use lock
+        synchronized (mLock) {
+            mEvents.add(event);
+            final int numberEvents = mEvents.size();
+            if (mState != STATE_ACTIVE) {
+                if (numberEvents >= MAX_DELAYED_SIZE) {
+                    // Typically happens on system apps that are started before the system service
+                    // is ready (like com.android.settings/.FallbackHome)
+                    //TODO(b/111276913): try to ignore session while system is not ready / boot
+                    // not complete instead. Similarly, the manager service should return right away
+                    // when the user does not have a service set
+                    if (VERBOSE) {
+                        Log.v(TAG, "Closing session for " + getActivityDebugNameLocked()
+                                + " after " + numberEvents + " delayed events and state "
+                                + getStateAsString(mState));
+                    }
+                    // TODO(b/111276913): blacklist activity / use special flag to indicate that
+                    // when it's launched again
+                    resetStateLocked();
+                    return;
+                }
+
+                if (VERBOSE) {
+                    Log.v(TAG, "Delaying " + numberEvents + " events for "
+                            + getActivityDebugNameLocked() + " while on state "
+                            + getStateAsString(mState));
+                }
+                return;
+            }
+
+            if (mId == null) {
+                // Sanity check - should not happen
+                Log.wtf(TAG, "null session id for " + mComponentName);
+                return;
+            }
+
+            //TODO(b/111276913): right now we're sending sending right away (unless not ready), but
+            // we should hold the events and flush later.
+            try {
+                if (DEBUG) {
+                    Log.d(TAG, "Sending " + numberEvents + " event(s) for "
+                            + getActivityDebugNameLocked());
+                }
+                mService.sendEvents(mContext.getUserId(), mId, mEvents);
+                mEvents.clear();
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Used for intermediate events (i.e, other than created and destroyed).
+     *
+     * @hide
+     */
+    public void onActivityLifecycleEvent(@EventType int type) {
+        if (!isContentCaptureEnabled()) return;
+        if (VERBOSE) {
+            Log.v(TAG, "onActivityLifecycleEvent() for " + getActivityDebugNameLocked()
+                    + ": " + ContentCaptureEvent.getTypeAsString(type));
+        }
+        sendEvent(new ContentCaptureEvent(type));
+    }
+
+    /** @hide */
+    public void onActivityDestroyed() {
+        if (!isContentCaptureEnabled()) return;
+
+        synchronized (mLock) {
+            //TODO(b/111276913): check state (for example, how to handle if it's waiting for remote
+            // id) and send it to the cache of batched commands
+
+            if (VERBOSE) {
+                Log.v(TAG, "onActivityDestroyed(): state=" + getStateAsString(mState)
+                        + ", mId=" + mId);
+            }
+
+            try {
+                mService.finishSession(mContext.getUserId(), mId);
+                resetStateLocked();
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void resetStateLocked() {
+        mState = STATE_UNKNOWN;
+        mId = null;
+        mApplicationToken = null;
+        mComponentName = null;
+        mEvents.clear();
+    }
+
+    /**
+     * Notifies the Intelligence Service that a node has been added to the view structure.
+     *
+     * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
+     * automatically by the Android System for views that return {@code true} on
+     * {@link View#onProvideContentCaptureStructure(ViewStructure, int)}.
+     *
+     * @param node node that has been added.
+     */
+    public void notifyViewAppeared(@NonNull ViewStructure node) {
+        Preconditions.checkNotNull(node);
+        if (!isContentCaptureEnabled()) return;
+
+        if (!(node instanceof ViewNode.ViewStructureImpl)) {
+            throw new IllegalArgumentException("Invalid node class: " + node.getClass());
+        }
+        sendEvent(new ContentCaptureEvent(TYPE_VIEW_APPEARED)
+                .setViewNode(((ViewNode.ViewStructureImpl) node).mNode));
+    }
+
+    /**
+     * Notifies the Intelligence Service that a node has been removed from the view structure.
+     *
+     * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
+     * automatically by the Android System for standard views.
+     *
+     * @param id id of the node that has been removed.
+     */
+    public void notifyViewDisappeared(@NonNull AutofillId id) {
+        Preconditions.checkNotNull(id);
+        if (!isContentCaptureEnabled()) return;
+
+        sendEvent(new ContentCaptureEvent(TYPE_VIEW_DISAPPEARED).setAutofillId(id));
+    }
+
+    /**
+     * Notifies the Intelligence Service that the value of a text node has been changed.
+     *
+     * @param id of the node.
+     * @param text new text.
+     * @param flags either {@code 0} or {@link #FLAG_USER_INPUT} when the value was explicitly
+     * changed by the user (for example, through the keyboard).
+     */
+    public void notifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text,
+            int flags) {
+        Preconditions.checkNotNull(id);
+        if (!isContentCaptureEnabled()) return;
+
+        sendEvent(new ContentCaptureEvent(TYPE_VIEW_TEXT_CHANGED, flags).setAutofillId(id)
+                .setText(text));
+    }
+
+    /**
+     * Creates a {@link ViewStructure} for a "standard" view.
+     *
+     * @hide
+     */
+    @NonNull
+    public ViewStructure newViewStructure(@NonNull View view) {
+        return new ViewNode.ViewStructureImpl(view);
+    }
+
+    /**
+     * Creates a {@link ViewStructure} for a "virtual" view, so it can be passed to
+     * {@link #notifyViewAppeared(ViewStructure)} by the view managing the virtual view hierarchy.
+     *
+     * @param parentId id of the virtual view parent (it can be obtained by calling
+     * {@link ViewStructure#getAutofillId()} on the parent).
+     * @param virtualId id of the virtual child, relative to the parent.
+     *
+     * @return a new {@link ViewStructure} that can be used for Content Capture purposes.
+     */
+    @NonNull
+    public ViewStructure newVirtualViewStructure(@NonNull AutofillId parentId, int virtualId) {
+        return new ViewNode.ViewStructureImpl(parentId, virtualId);
     }
 
     /**
@@ -54,11 +380,13 @@
     }
 
     /**
-     * Checks whether contents capture is enabled for this activity.
+     * Checks whether content capture is enabled for this activity.
      */
     public boolean isContentCaptureEnabled() {
-        //TODO(b/111276913): implement
-        return false;
+        //TODO(b/111276913): properly implement by checking if it was explicitly disabled by
+        // service, or if service is not set
+        // (and probably renamign to isEnabledLocked()
+        return mService != null && mState != STATE_DISABLED;
     }
 
     /**
@@ -68,6 +396,7 @@
      * it on {@link android.app.Activity#onCreate(android.os.Bundle, android.os.PersistableBundle)}.
      */
     public void disableContentCapture() {
+        //TODO(b/111276913): implement
     }
 
     /**
@@ -140,4 +469,56 @@
         //TODO(b/111276913): implement
         return null;
     }
+
+    /** @hide */
+    public void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.println("IntelligenceManager");
+        final String prefix2 = prefix + "  ";
+        synchronized (mLock) {
+            pw.print(prefix2); pw.print("mContext: "); pw.println(mContext);
+            pw.print(prefix2); pw.print("mService: "); pw.println(mService);
+            pw.print(prefix2); pw.print("user: "); pw.println(mContext.getUserId());
+            pw.print(prefix2); pw.print("enabled: "); pw.println(isContentCaptureEnabled());
+            pw.print(prefix2); pw.print("id: "); pw.println(mId);
+            pw.print(prefix2); pw.print("state: "); pw.print(mState); pw.print(" (");
+            pw.print(getStateAsString(mState)); pw.println(")");
+            pw.print(prefix2); pw.print("app token: "); pw.println(mApplicationToken);
+            pw.print(prefix2); pw.print("component name: ");
+            pw.println(mComponentName == null ? "null" : mComponentName.flattenToShortString());
+            final int numberEvents = mEvents.size();
+            pw.print(prefix2); pw.print("batched events: "); pw.println(numberEvents);
+            if (numberEvents > 0) {
+                for (int i = 0; i < numberEvents; i++) {
+                    final ContentCaptureEvent event = mEvents.get(i);
+                    pw.println(i); pw.print(": "); event.dump(pw); pw.println();
+                }
+
+            }
+        }
+    }
+
+    /**
+     * Gets a string that can be used to identify the activity on logging statements.
+     */
+    @GuardedBy("mLock")
+    private String getActivityDebugNameLocked() {
+        return mComponentName == null ? mContext.getPackageName()
+                : mComponentName.flattenToShortString();
+    }
+
+    @NonNull
+    private static String getStateAsString(int state) {
+        switch (state) {
+            case STATE_UNKNOWN:
+                return "UNKNOWN";
+            case STATE_WAITING_FOR_SERVER:
+                return "WAITING_FOR_SERVER";
+            case STATE_ACTIVE:
+                return "ACTIVE";
+            case STATE_DISABLED:
+                return "DISABLED";
+            default:
+                return "INVALID:" + state;
+        }
+    }
 }
diff --git a/core/java/android/view/intelligence/ViewNode.java b/core/java/android/view/intelligence/ViewNode.java
index 357ecf5..cc78e6b 100644
--- a/core/java/android/view/intelligence/ViewNode.java
+++ b/core/java/android/view/intelligence/ViewNode.java
@@ -15,10 +15,24 @@
  */
 package android.view.intelligence;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.app.assist.AssistStructure;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.LocaleList;
+import android.os.Parcel;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewParent;
+import android.view.ViewStructure;
+import android.view.ViewStructure.HtmlInfo.Builder;
 import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+
+import com.android.internal.util.Preconditions;
 
 //TODO(b/111276913): add javadocs / implement Parcelable / implement
 //TODO(b/111276913): for now it's extending ViewNode directly as it needs most of its properties,
@@ -28,6 +42,16 @@
 @SystemApi
 public final class ViewNode extends AssistStructure.ViewNode {
 
+    private static final String TAG = "ViewNode";
+
+    private AutofillId mParentAutofillId;
+
+    // TODO(b/111276913): temporarily setting some fields here while they're not accessible from the
+    // superclass
+    private AutofillId mAutofillId;
+    private CharSequence mText;
+    private String mClassName;
+
     /** @hide */
     public ViewNode() {
     }
@@ -38,7 +62,343 @@
      */
     @Nullable
     public AutofillId getParentAutofillId() {
-        //TODO(b/111276913): implement
-        return null;
+        return mParentAutofillId;
+    }
+
+    // TODO(b/111276913): temporarily overwriting some methods
+    @Override
+    public AutofillId getAutofillId() {
+        return mAutofillId;
+    }
+    @Override
+    public CharSequence getText() {
+        return mText;
+    }
+    @Override
+    public String getClassName() {
+        return mClassName;
+    }
+
+    /** @hide */
+    public static void writeToParcel(@NonNull Parcel parcel, @Nullable ViewNode node, int flags) {
+        if (node == null) {
+            parcel.writeParcelable(null, flags);
+            return;
+        }
+        parcel.writeParcelable(node.mAutofillId, flags);
+        parcel.writeParcelable(node.mParentAutofillId, flags);
+        parcel.writeCharSequence(node.mText);
+        parcel.writeString(node.mClassName);
+    }
+
+    /** @hide */
+    public static @Nullable ViewNode readFromParcel(@NonNull Parcel parcel) {
+        final AutofillId id = parcel.readParcelable(null);
+        if (id == null) return null;
+
+        final ViewNode node = new ViewNode();
+
+        node.mAutofillId = id;
+        node.mParentAutofillId = parcel.readParcelable(null);
+        node.mText = parcel.readCharSequence();
+        node.mClassName = parcel.readString();
+
+        return node;
+    }
+
+    /** @hide */
+    static final class ViewStructureImpl extends ViewStructure {
+
+        final ViewNode mNode = new ViewNode();
+
+        ViewStructureImpl(@NonNull View view) {
+            mNode.mAutofillId = Preconditions.checkNotNull(view).getAutofillId();
+            final ViewParent parent = view.getParent();
+            if (parent instanceof View) {
+                mNode.mParentAutofillId = ((View) parent).getAutofillId();
+            }
+        }
+
+        ViewStructureImpl(@NonNull AutofillId parentId, int virtualId) {
+            mNode.mParentAutofillId = Preconditions.checkNotNull(parentId);
+            mNode.mAutofillId = new AutofillId(parentId, virtualId);
+        }
+
+        @Override
+        public void setId(int id, String packageName, String typeName, String entryName) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setTransformation(Matrix matrix) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setElevation(float elevation) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setAlpha(float alpha) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setVisibility(int visibility) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setAssistBlocked(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setEnabled(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setClickable(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setLongClickable(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setContextClickable(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setFocusable(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setFocused(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setAccessibilityFocused(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setCheckable(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setChecked(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setSelected(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setActivated(boolean state) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setOpaque(boolean opaque) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setClassName(String className) {
+            // TODO(b/111276913): temporarily setting directly; should be done on superclass instead
+            mNode.mClassName = className;
+        }
+
+        @Override
+        public void setContentDescription(CharSequence contentDescription) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setText(CharSequence text) {
+            // TODO(b/111276913): temporarily setting directly; should be done on superclass instead
+            mNode.mText = text;
+        }
+
+        @Override
+        public void setText(CharSequence text, int selectionStart, int selectionEnd) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setTextStyle(float size, int fgColor, int bgColor, int style) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setTextLines(int[] charOffsets, int[] baselines) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setHint(CharSequence hint) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public CharSequence getText() {
+            // TODO(b/111276913): temporarily getting directly; should be done on superclass instead
+            return mNode.mText;
+        }
+
+        @Override
+        public int getTextSelectionStart() {
+            // TODO(b/111276913): implement or move to superclass
+            return 0;
+        }
+
+        @Override
+        public int getTextSelectionEnd() {
+            // TODO(b/111276913): implement or move to superclass
+            return 0;
+        }
+
+        @Override
+        public CharSequence getHint() {
+            // TODO(b/111276913): implement or move to superclass
+            return null;
+        }
+
+        @Override
+        public Bundle getExtras() {
+            // TODO(b/111276913): implement or move to superclass
+            return null;
+        }
+
+        @Override
+        public boolean hasExtras() {
+            // TODO(b/111276913): implement or move to superclass
+            return false;
+        }
+
+        @Override
+        public void setChildCount(int num) {
+            Log.w(TAG, "setChildCount() is not supported");
+        }
+
+        @Override
+        public int addChildCount(int num) {
+            Log.w(TAG, "addChildCount() is not supported");
+            return 0;
+        }
+
+        @Override
+        public int getChildCount() {
+            Log.w(TAG, "getChildCount() is not supported");
+            return 0;
+        }
+
+        @Override
+        public ViewStructure newChild(int index) {
+            Log.w(TAG, "newChild() is not supported");
+            return null;
+        }
+
+        @Override
+        public ViewStructure asyncNewChild(int index) {
+            Log.w(TAG, "asyncNewChild() is not supported");
+            return null;
+        }
+
+        @Override
+        public AutofillId getAutofillId() {
+            // TODO(b/111276913): temporarily getting directly; should be done on superclass instead
+            return mNode.mAutofillId;
+        }
+
+        @Override
+        public void setAutofillId(AutofillId id) {
+            // TODO(b/111276913): temporarily setting directly; should be done on superclass instead
+            mNode.mAutofillId = id;
+        }
+
+        @Override
+        public void setAutofillId(AutofillId parentId, int virtualId) {
+            // TODO(b/111276913): temporarily setting directly; should be done on superclass instead
+            mNode.mAutofillId = new AutofillId(parentId, virtualId);
+        }
+
+        @Override
+        public void setAutofillType(int type) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setAutofillHints(String[] hint) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setAutofillValue(AutofillValue value) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setAutofillOptions(CharSequence[] options) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setInputType(int inputType) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void setDataIsSensitive(boolean sensitive) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public void asyncCommit() {
+            Log.w(TAG, "asyncCommit() is not supported");
+        }
+
+        @Override
+        public Rect getTempRect() {
+            // TODO(b/111276913): implement or move to superclass
+            return null;
+        }
+
+        @Override
+        public void setWebDomain(String domain) {
+            Log.w(TAG, "setWebDomain() is not supported");
+        }
+
+        @Override
+        public void setLocaleList(LocaleList localeList) {
+            // TODO(b/111276913): implement or move to superclass
+        }
+
+        @Override
+        public Builder newHtmlInfoBuilder(String tagName) {
+            Log.w(TAG, "newHtmlInfoBuilder() is not supported");
+            return null;
+        }
+
+        @Override
+        public void setHtmlInfo(HtmlInfo htmlInfo) {
+            Log.w(TAG, "setHtmlInfo() is not supported");
+        }
     }
 }
diff --git a/core/java/android/view/textclassifier/ModelFileManager.java b/core/java/android/view/textclassifier/ModelFileManager.java
index adea125..8558a46 100644
--- a/core/java/android/view/textclassifier/ModelFileManager.java
+++ b/core/java/android/view/textclassifier/ModelFileManager.java
@@ -74,10 +74,9 @@
      * @param localeList the required locales, use {@code null} if there is no preference.
      */
     public ModelFile findBestModelFile(@Nullable LocaleList localeList) {
-        // Specified localeList takes priority over the system default, so it is listed first.
         final String languages = localeList == null || localeList.isEmpty()
                 ? LocaleList.getDefault().toLanguageTags()
-                : localeList.toLanguageTags() + "," + LocaleList.getDefault().toLanguageTags();
+                : localeList.toLanguageTags();
         final List<Locale.LanguageRange> languageRangeList = Locale.LanguageRange.parse(languages);
 
         ModelFile bestModel = null;
@@ -252,6 +251,9 @@
             if (!mLanguageIndependent && model.mLanguageIndependent) {
                 return true;
             }
+            if (mLanguageIndependent && !model.mLanguageIndependent) {
+                return false;
+            }
 
             // A higher-version model is preferred.
             if (mVersion > model.getVersion()) {
diff --git a/core/java/android/view/textclassifier/TextClassificationConstants.java b/core/java/android/view/textclassifier/TextClassificationConstants.java
index 2fc7422..50801a2 100644
--- a/core/java/android/view/textclassifier/TextClassificationConstants.java
+++ b/core/java/android/view/textclassifier/TextClassificationConstants.java
@@ -90,6 +90,10 @@
             "entity_list_not_editable";
     private static final String ENTITY_LIST_EDITABLE =
             "entity_list_editable";
+    private static final String IN_APP_CONVERSATION_ACTION_TYPES_DEFAULT =
+            "in_app_conversation_action_types_default";
+    private static final String NOTIFICATION_CONVERSATION_ACTION_TYPES_DEFAULT =
+            "notification_conversation_action_types_default";
 
     private static final boolean LOCAL_TEXT_CLASSIFIER_ENABLED_DEFAULT = true;
     private static final boolean SYSTEM_TEXT_CLASSIFIER_ENABLED_DEFAULT = true;
@@ -111,6 +115,18 @@
             .add(TextClassifier.TYPE_DATE)
             .add(TextClassifier.TYPE_DATE_TIME)
             .add(TextClassifier.TYPE_FLIGHT_NUMBER).toString();
+    private static final String CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES =
+            new StringJoiner(ENTITY_LIST_DELIMITER)
+                    .add(ConversationActions.TYPE_TEXT_REPLY)
+                    .add(ConversationActions.TYPE_CREATE_REMINDER)
+                    .add(ConversationActions.TYPE_CALL_PHONE)
+                    .add(ConversationActions.TYPE_OPEN_URL)
+                    .add(ConversationActions.TYPE_SEND_EMAIL)
+                    .add(ConversationActions.TYPE_SEND_SMS)
+                    .add(ConversationActions.TYPE_TRACK_FLIGHT)
+                    .add(ConversationActions.TYPE_VIEW_CALENDAR)
+                    .add(ConversationActions.TYPE_VIEW_MAP)
+                    .toString();
 
     private final boolean mSystemTextClassifierEnabled;
     private final boolean mLocalTextClassifierEnabled;
@@ -126,6 +142,8 @@
     private final List<String> mEntityListDefault;
     private final List<String> mEntityListNotEditable;
     private final List<String> mEntityListEditable;
+    private final List<String> mInAppConversationActionTypesDefault;
+    private final List<String> mNotificationConversationActionTypesDefault;
 
     private TextClassificationConstants(@Nullable String settings) {
         final KeyValueListParser parser = new KeyValueListParser(',');
@@ -177,6 +195,12 @@
         mEntityListEditable = parseEntityList(parser.getString(
                 ENTITY_LIST_EDITABLE,
                 ENTITY_LIST_DEFAULT_VALUE));
+        mInAppConversationActionTypesDefault = parseEntityList(parser.getString(
+                IN_APP_CONVERSATION_ACTION_TYPES_DEFAULT,
+                CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES));
+        mNotificationConversationActionTypesDefault = parseEntityList(parser.getString(
+                NOTIFICATION_CONVERSATION_ACTION_TYPES_DEFAULT,
+                CONVERSATION_ACTIONS_TYPES_DEFAULT_VALUES));
     }
 
     /** Load from a settings string. */
@@ -240,6 +264,14 @@
         return mEntityListEditable;
     }
 
+    public List<String> getInAppConversationActionTypes() {
+        return mInAppConversationActionTypesDefault;
+    }
+
+    public List<String> getNotificationConversationActionTypes() {
+        return mNotificationConversationActionTypesDefault;
+    }
+
     private static List<String> parseEntityList(String listStr) {
         return Collections.unmodifiableList(Arrays.asList(listStr.split(ENTITY_LIST_DELIMITER)));
     }
@@ -261,6 +293,9 @@
         pw.printPair("getEntityListDefault", mEntityListDefault);
         pw.printPair("getEntityListNotEditable", mEntityListNotEditable);
         pw.printPair("getEntityListEditable", mEntityListEditable);
+        pw.printPair("getInAppConversationActionTypes", mInAppConversationActionTypesDefault);
+        pw.printPair("getNotificationConversationActionTypes",
+                mNotificationConversationActionTypesDefault);
         pw.decreaseIndent();
         pw.println();
     }
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index e675744..524f709 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -48,6 +48,9 @@
 
 /**
  * Interface for providing text classification related features.
+ * <p>
+ * The TextClassifier may be used to understand the meaning of text, as well as generating predicted
+ * next actions based on the text.
  *
  * <p><strong>NOTE: </strong>Unless otherwise stated, methods of this interface are blocking
  * operations. Call on a worker thread.
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 159bfaa..798a820 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -40,11 +40,13 @@
 import android.provider.Browser;
 import android.provider.CalendarContract;
 import android.provider.ContactsContract;
+import android.text.TextUtils;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 
+import com.google.android.textclassifier.ActionsSuggestionsModel;
 import com.google.android.textclassifier.AnnotatorModel;
 import com.google.android.textclassifier.LangIdModel;
 
@@ -90,6 +92,11 @@
     private static final File UPDATED_LANG_ID_MODEL_FILE =
             new File("/data/misc/textclassifier/lang_id.model");
 
+    // Actions
+    private static final String ACTIONS_FACTORY_MODEL_FILENAME_REGEX = "actions_suggestions.model";
+    private static final File UPDATED_ACTIONS_MODEL =
+            new File("/data/misc/textclassifier/actions_suggestions.model");
+
     private final Context mContext;
     private final TextClassifier mFallback;
     private final GenerateLinksLogger mGenerateLinksLogger;
@@ -101,6 +108,8 @@
     private AnnotatorModel mAnnotatorImpl;
     @GuardedBy("mLock") // Do not access outside this lock.
     private LangIdModel mLangIdImpl;
+    @GuardedBy("mLock") // Do not access outside this lock.
+    private ActionsSuggestionsModel mActionsImpl;
 
     private final Object mLoggerLock = new Object();
     @GuardedBy("mLoggerLock") // Do not access outside this lock.
@@ -110,6 +119,7 @@
 
     private final ModelFileManager mAnnotatorModelFileManager;
     private final ModelFileManager mLangIdModelFileManager;
+    private final ModelFileManager mActionsModelFileManager;
 
     public TextClassifierImpl(
             Context context, TextClassificationConstants settings, TextClassifier fallback) {
@@ -131,6 +141,13 @@
                         UPDATED_LANG_ID_MODEL_FILE,
                         fd -> -1, // TODO: Replace this with LangIdModel.getVersion(fd)
                         fd -> ModelFileManager.ModelFile.LANGUAGE_INDEPENDENT));
+        mActionsModelFileManager = new ModelFileManager(
+                new ModelFileManager.ModelFileSupplierImpl(
+                        FACTORY_MODEL_DIR,
+                        ACTIONS_FACTORY_MODEL_FILENAME_REGEX,
+                        UPDATED_ACTIONS_MODEL,
+                        ActionsSuggestionsModel::getVersion,
+                        ActionsSuggestionsModel::getLocales));
     }
 
     public TextClassifierImpl(Context context, TextClassificationConstants settings) {
@@ -346,10 +363,69 @@
         return mFallback.detectLanguage(request);
     }
 
+    @Override
+    public ConversationActions suggestConversationActions(ConversationActions.Request request) {
+        Preconditions.checkNotNull(request);
+        Utils.checkMainThread();
+        try {
+            ActionsSuggestionsModel actionsImpl = getActionsImpl();
+            if (actionsImpl == null) {
+                // Actions model is optional, fallback if it is not available.
+                return mFallback.suggestConversationActions(request);
+            }
+            List<ActionsSuggestionsModel.ConversationMessage> nativeMessages = new ArrayList<>();
+            for (ConversationActions.Message message : request.getConversation()) {
+                if (TextUtils.isEmpty(message.getText())) {
+                    continue;
+                }
+                // TODO: We need to map the Person object to user id.
+                int userId = 1;
+                nativeMessages.add(
+                        new ActionsSuggestionsModel.ConversationMessage(
+                                userId, message.getText().toString()));
+            }
+            ActionsSuggestionsModel.Conversation nativeConversation =
+                    new ActionsSuggestionsModel.Conversation(nativeMessages.toArray(
+                            new ActionsSuggestionsModel.ConversationMessage[0]));
+
+            ActionsSuggestionsModel.ActionSuggestion[] nativeSuggestions =
+                    actionsImpl.suggestActions(nativeConversation, null);
+
+            Collection<String> expectedTypes = resolveActionTypesFromRequest(request);
+            List<ConversationActions.ConversationAction> conversationActions = new ArrayList<>();
+            int maxSuggestions = Math.min(request.getMaxSuggestions(), nativeSuggestions.length);
+            for (int i = 0; i < maxSuggestions; i++) {
+                ActionsSuggestionsModel.ActionSuggestion nativeSuggestion = nativeSuggestions[i];
+                String actionType = nativeSuggestion.getActionType();
+                if (!expectedTypes.contains(actionType)) {
+                    continue;
+                }
+                conversationActions.add(
+                        new ConversationActions.ConversationAction.Builder(actionType)
+                                .setTextReply(nativeSuggestion.getResponseText())
+                                .setConfidenceScore(nativeSuggestion.getScore())
+                                .build());
+            }
+            return new ConversationActions(conversationActions);
+        } catch (Throwable t) {
+            // Avoid throwing from this method. Log the error.
+            Log.e(LOG_TAG, "Error suggesting conversation actions.", t);
+        }
+        return mFallback.suggestConversationActions(request);
+    }
+
+    private Collection<String> resolveActionTypesFromRequest(ConversationActions.Request request) {
+        List<String> defaultActionTypes =
+                request.getHints().contains(ConversationActions.HINT_FOR_NOTIFICATION)
+                        ? mSettings.getNotificationConversationActionTypes()
+                        : mSettings.getInAppConversationActionTypes();
+        return request.getTypeConfig().resolveTypes(defaultActionTypes);
+    }
+
     private AnnotatorModel getAnnotatorImpl(LocaleList localeList)
             throws FileNotFoundException {
         synchronized (mLock) {
-            localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList;
+            localeList = localeList == null ? LocaleList.getDefault() : localeList;
             final ModelFileManager.ModelFile bestModel =
                     mAnnotatorModelFileManager.findBestModelFile(localeList);
             if (bestModel == null) {
@@ -386,7 +462,7 @@
         synchronized (mLock) {
             if (mLangIdImpl == null) {
                 final ModelFileManager.ModelFile bestModel =
-                        mLangIdModelFileManager.findBestModelFile(LocaleList.getEmptyLocaleList());
+                        mLangIdModelFileManager.findBestModelFile(null);
                 if (bestModel == null) {
                     throw new FileNotFoundException("No LangID model is found");
                 }
@@ -404,6 +480,30 @@
         }
     }
 
+    @Nullable
+    private ActionsSuggestionsModel getActionsImpl() throws FileNotFoundException {
+        synchronized (mLock) {
+            if (mActionsImpl == null) {
+                // TODO: Use LangID to determine the locale we should use here?
+                final ModelFileManager.ModelFile bestModel =
+                        mActionsModelFileManager.findBestModelFile(LocaleList.getDefault());
+                if (bestModel == null) {
+                    return null;
+                }
+                final ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
+                        new File(bestModel.getPath()), ParcelFileDescriptor.MODE_READ_ONLY);
+                try {
+                    if (pfd != null) {
+                        mActionsImpl = new ActionsSuggestionsModel(pfd.getFd());
+                    }
+                } finally {
+                    maybeCloseAndLogError(pfd);
+                }
+            }
+            return mActionsImpl;
+        }
+    }
+
     private String createId(String text, int start, int end) {
         synchronized (mLock) {
             return SelectionSessionLogger.createId(text, start, end, mContext,
@@ -471,11 +571,19 @@
             }
             printWriter.decreaseIndent();
             printWriter.println("LangID model file(s):");
+            printWriter.increaseIndent();
             for (ModelFileManager.ModelFile modelFile :
                     mLangIdModelFileManager.listModelFiles()) {
                 printWriter.println(modelFile.toString());
             }
             printWriter.decreaseIndent();
+            printWriter.println("Actions model file(s):");
+            printWriter.increaseIndent();
+            for (ModelFileManager.ModelFile modelFile :
+                    mActionsModelFileManager.listModelFiles()) {
+                printWriter.println(modelFile.toString());
+            }
+            printWriter.decreaseIndent();
             printWriter.printPair("mFallback", mFallback);
             printWriter.decreaseIndent();
             printWriter.println();
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index b31438f..02aee50 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -92,10 +93,12 @@
 
     private final String mFullText;
     private final List<TextLink> mLinks;
+    private final Bundle mExtras;
 
-    private TextLinks(String fullText, ArrayList<TextLink> links) {
+    private TextLinks(String fullText, ArrayList<TextLink> links, Bundle extras) {
         mFullText = fullText;
         mLinks = Collections.unmodifiableList(links);
+        mExtras = extras;
     }
 
     /**
@@ -116,6 +119,18 @@
     }
 
     /**
+     * Returns the extended data.
+     *
+     * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+     * prefer to hold a reference to the returned bundle rather than frequently calling this
+     * method.
+     */
+    @NonNull
+    public Bundle getExtras() {
+        return mExtras.deepCopy();
+    }
+
+    /**
      * Annotates the given text with the generated links. It will fail if the provided text doesn't
      * match the original text used to create the TextLinks.
      *
@@ -158,6 +173,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(mFullText);
         dest.writeTypedList(mLinks);
+        dest.writeBundle(mExtras);
     }
 
     public static final Parcelable.Creator<TextLinks> CREATOR =
@@ -176,6 +192,7 @@
     private TextLinks(Parcel in) {
         mFullText = in.readString();
         mLinks = in.createTypedArrayList(TextLink.CREATOR);
+        mExtras = in.readBundle();
     }
 
     /**
@@ -304,18 +321,21 @@
         @Nullable private final TextClassifier.EntityConfig mEntityConfig;
         private final boolean mLegacyFallback;
         private String mCallingPackageName;
+        private final Bundle mExtras;
 
         private Request(
                 CharSequence text,
                 LocaleList defaultLocales,
                 TextClassifier.EntityConfig entityConfig,
                 boolean legacyFallback,
-                String callingPackageName) {
+                String callingPackageName,
+                Bundle extras) {
             mText = text;
             mDefaultLocales = defaultLocales;
             mEntityConfig = entityConfig;
             mLegacyFallback = legacyFallback;
             mCallingPackageName = callingPackageName;
+            mExtras = extras;
         }
 
         /**
@@ -362,6 +382,18 @@
         }
 
         /**
+         * Returns the extended data.
+         *
+         * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+         * prefer to hold a reference to the returned bundle rather than frequently calling this
+         * method.
+         */
+        @NonNull
+        public Bundle getExtras() {
+            return mExtras.deepCopy();
+        }
+
+        /**
          * A builder for building TextLinks requests.
          */
         public static final class Builder {
@@ -372,6 +404,7 @@
             @Nullable private TextClassifier.EntityConfig mEntityConfig;
             private boolean mLegacyFallback = true; // Use legacy fall back by default.
             private String mCallingPackageName;
+            @Nullable private Bundle mExtras;
 
             public Builder(@NonNull CharSequence text) {
                 mText = Preconditions.checkNotNull(text);
@@ -431,15 +464,25 @@
             }
 
             /**
+             * Sets the extended data.
+             *
+             * @return this builder
+             */
+            public Builder setExtras(@Nullable Bundle extras) {
+                mExtras = extras;
+                return this;
+            }
+
+            /**
              * Builds and returns the request object.
              */
             @NonNull
             public Request build() {
                 return new Request(
                         mText, mDefaultLocales, mEntityConfig,
-                        mLegacyFallback, mCallingPackageName);
+                        mLegacyFallback, mCallingPackageName,
+                        mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
             }
-
         }
 
         /**
@@ -469,6 +512,7 @@
                 mEntityConfig.writeToParcel(dest, flags);
             }
             dest.writeString(mCallingPackageName);
+            dest.writeBundle(mExtras);
         }
 
         public static final Parcelable.Creator<Request> CREATOR =
@@ -491,6 +535,7 @@
                     ? null : TextClassifier.EntityConfig.CREATOR.createFromParcel(in);
             mLegacyFallback = true;
             mCallingPackageName = in.readString();
+            mExtras = in.readBundle();
         }
     }
 
@@ -575,6 +620,7 @@
     public static final class Builder {
         private final String mFullText;
         private final ArrayList<TextLink> mLinks;
+        private Bundle mExtras;
 
         /**
          * Create a new TextLinks.Builder.
@@ -622,13 +668,24 @@
         }
 
         /**
+         * Sets the extended data.
+         *
+         * @return this builder
+         */
+        public Builder setExtras(@Nullable Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
          * Constructs a TextLinks instance.
          *
          * @return the constructed TextLinks
          */
         @NonNull
         public TextLinks build() {
-            return new TextLinks(mFullText, mLinks);
+            return new TextLinks(mFullText, mLinks,
+                    mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
         }
     }
 }
diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java
index 52d01ea..f236915 100644
--- a/core/java/android/view/textclassifier/TextSelection.java
+++ b/core/java/android/view/textclassifier/TextSelection.java
@@ -20,6 +20,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -41,13 +42,16 @@
     private final int mEndIndex;
     private final EntityConfidence mEntityConfidence;
     @Nullable private final String mId;
+    private final Bundle mExtras;
 
     private TextSelection(
-            int startIndex, int endIndex, Map<String, Float> entityConfidence, String id) {
+            int startIndex, int endIndex, Map<String, Float> entityConfidence, String id,
+            Bundle extras) {
         mStartIndex = startIndex;
         mEndIndex = endIndex;
         mEntityConfidence = new EntityConfidence(entityConfidence);
         mId = id;
+        mExtras = extras;
     }
 
     /**
@@ -103,6 +107,18 @@
         return mId;
     }
 
+    /**
+     * Returns the extended data.
+     *
+     * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+     * prefer to hold a reference to the returned bundle rather than frequently calling this
+     * method.
+     */
+    @NonNull
+    public Bundle getExtras() {
+        return mExtras.deepCopy();
+    }
+
     @Override
     public String toString() {
         return String.format(
@@ -120,6 +136,8 @@
         private final int mEndIndex;
         private final Map<String, Float> mEntityConfidence = new ArrayMap<>();
         @Nullable private String mId;
+        @Nullable
+        private Bundle mExtras;
 
         /**
          * Creates a builder used to build {@link TextSelection} objects.
@@ -160,12 +178,23 @@
         }
 
         /**
+         * Sets the extended data.
+         *
+         * @return this builder
+         */
+        public Builder setExtras(@Nullable Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
          * Builds and returns {@link TextSelection} object.
          */
         @NonNull
         public TextSelection build() {
             return new TextSelection(
-                    mStartIndex, mEndIndex, mEntityConfidence, mId);
+                    mStartIndex, mEndIndex, mEntityConfidence, mId,
+                    mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
         }
     }
 
@@ -179,18 +208,21 @@
         private final int mEndIndex;
         @Nullable private final LocaleList mDefaultLocales;
         private final boolean mDarkLaunchAllowed;
+        private final Bundle mExtras;
 
         private Request(
                 CharSequence text,
                 int startIndex,
                 int endIndex,
                 LocaleList defaultLocales,
-                boolean darkLaunchAllowed) {
+                boolean darkLaunchAllowed,
+                Bundle extras) {
             mText = text;
             mStartIndex = startIndex;
             mEndIndex = endIndex;
             mDefaultLocales = defaultLocales;
             mDarkLaunchAllowed = darkLaunchAllowed;
+            mExtras = extras;
         }
 
         /**
@@ -238,6 +270,18 @@
         }
 
         /**
+         * Returns the extended data.
+         *
+         * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+         * prefer to hold a reference to the returned bundle rather than frequently calling this
+         * method.
+         */
+        @NonNull
+        public Bundle getExtras() {
+            return mExtras.deepCopy();
+        }
+
+        /**
          * A builder for building TextSelection requests.
          */
         public static final class Builder {
@@ -248,6 +292,7 @@
 
             @Nullable private LocaleList mDefaultLocales;
             private boolean mDarkLaunchAllowed;
+            private Bundle mExtras;
 
             /**
              * @param text text providing context for the selected text (which is specified by the
@@ -296,12 +341,23 @@
             }
 
             /**
+             * Sets the extended data.
+             *
+             * @return this builder
+             */
+            public Builder setExtras(@Nullable Bundle extras) {
+                mExtras = extras;
+                return this;
+            }
+
+            /**
              * Builds and returns the request object.
              */
             @NonNull
             public Request build() {
                 return new Request(mText, mStartIndex, mEndIndex,
-                        mDefaultLocales, mDarkLaunchAllowed);
+                        mDefaultLocales, mDarkLaunchAllowed,
+                        mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
             }
         }
 
@@ -319,6 +375,7 @@
             if (mDefaultLocales != null) {
                 mDefaultLocales.writeToParcel(dest, flags);
             }
+            dest.writeBundle(mExtras);
         }
 
         public static final Parcelable.Creator<Request> CREATOR =
@@ -340,6 +397,7 @@
             mEndIndex = in.readInt();
             mDefaultLocales = in.readInt() == 0 ? null : LocaleList.CREATOR.createFromParcel(in);
             mDarkLaunchAllowed = false;
+            mExtras = in.readBundle();
         }
     }
 
@@ -354,6 +412,7 @@
         dest.writeInt(mEndIndex);
         mEntityConfidence.writeToParcel(dest, flags);
         dest.writeString(mId);
+        dest.writeBundle(mExtras);
     }
 
     public static final Parcelable.Creator<TextSelection> CREATOR =
@@ -374,5 +433,6 @@
         mEndIndex = in.readInt();
         mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
         mId = in.readString();
+        mExtras = in.readBundle();
     }
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f343a52..1093719 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2695,6 +2695,11 @@
     }
 
     @Override
+    public boolean onProvideContentCaptureStructure(ViewStructure structure, int flags) {
+        return mProvider.getViewDelegate().onProvideContentCaptureStructure(structure, flags);
+    }
+
+    @Override
     public void autofill(SparseArray<AutofillValue>values) {
         mProvider.getViewDelegate().autofill(values);
     }
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 00e782b..ceada07 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -341,6 +341,12 @@
             return true; // true is the default value returned by View.isVisibleToUserForAutofill()
         }
 
+        default boolean onProvideContentCaptureStructure(
+                @SuppressWarnings("unused") android.view.ViewStructure structure,
+                @SuppressWarnings("unused") int flags) {
+            return false; // WebView provides virtual views and is responsible to notify manager
+        }
+
         public AccessibilityNodeProvider getAccessibilityNodeProvider();
 
         public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index f3fe16e..ddff858 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -1309,13 +1309,23 @@
     @Override
     public void onProvideAutofillStructure(ViewStructure structure, int flags) {
         super.onProvideAutofillStructure(structure, flags);
+    }
 
-        final Adapter adapter = getAdapter();
-        if (adapter == null) return;
+    /** @hide */
+    @Override
+    protected void onProvideStructure(@NonNull ViewStructure structure,
+            @ViewStructureType int viewFor, int flags) {
+        super.onProvideStructure(structure, viewFor, flags);
 
-        final CharSequence[] options = adapter.getAutofillOptions();
-        if (options != null) {
-            structure.setAutofillOptions(options);
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+            final Adapter adapter = getAdapter();
+            if (adapter == null) return;
+
+            final CharSequence[] options = adapter.getAutofillOptions();
+            if (options != null) {
+                structure.setAutofillOptions(options);
+            }
         }
     }
 }
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index b754d84..eb35587 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -16,302 +16,22 @@
 */
 package android.widget;
 
-import android.annotation.UnsupportedAppUsage;
-import android.app.AlertDialog;
 import android.content.Context;
-import android.content.DialogInterface;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageItemInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
 import android.graphics.drawable.Drawable;
-import android.os.Parcel;
-import android.os.UserHandle;
-import android.text.SpannableStringBuilder;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
 
 import com.android.internal.R;
 
-import java.text.Collator;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 /**
- * This class contains the SecurityPermissions view implementation.
- * Initially the package's advanced or dangerous security permissions
- * are displayed under categorized
- * groups. Clicking on the additional permissions presents
- * extended information consisting of all groups and permissions.
- * To use this view define a LinearLayout or any ViewGroup and add this
- * view by instantiating AppSecurityPermissions and invoking getPermissionsView.
+ * Allows the device admin to show certain dialogs. Should be integrated into settings.
  *
+ * @deprecated
  * {@hide}
  */
+@Deprecated
 public class AppSecurityPermissions {
 
-    public static final int WHICH_NEW = 1<<2;
-    public static final int WHICH_ALL = 0xffff;
-
-    private final static String TAG = "AppSecurityPermissions";
-    private final static boolean localLOGV = false;
-    private final Context mContext;
-    private final LayoutInflater mInflater;
-    private final PackageManager mPm;
-    private final Map<String, MyPermissionGroupInfo> mPermGroups
-            = new HashMap<String, MyPermissionGroupInfo>();
-    private final List<MyPermissionGroupInfo> mPermGroupsList
-            = new ArrayList<MyPermissionGroupInfo>();
-    private final PermissionGroupInfoComparator mPermGroupComparator =
-            new PermissionGroupInfoComparator();
-    private final PermissionInfoComparator mPermComparator = new PermissionInfoComparator();
-    private final List<MyPermissionInfo> mPermsList = new ArrayList<MyPermissionInfo>();
-    private final CharSequence mNewPermPrefix;
-    private String mPackageName;
-
-    /** @hide */
-    static class MyPermissionGroupInfo extends PermissionGroupInfo {
-        CharSequence mLabel;
-
-        final ArrayList<MyPermissionInfo> mNewPermissions = new ArrayList<MyPermissionInfo>();
-        final ArrayList<MyPermissionInfo> mAllPermissions = new ArrayList<MyPermissionInfo>();
-
-        MyPermissionGroupInfo(PermissionInfo perm) {
-            name = perm.packageName;
-            packageName = perm.packageName;
-        }
-
-        MyPermissionGroupInfo(PermissionGroupInfo info) {
-            super(info);
-        }
-
-        public Drawable loadGroupIcon(Context context, PackageManager pm) {
-            if (icon != 0) {
-                return loadUnbadgedIcon(pm);
-            } else {
-                return context.getDrawable(R.drawable.ic_perm_device_info);
-            }
-        }
-    }
-
-    /** @hide */
-    private static class MyPermissionInfo extends PermissionInfo {
-        CharSequence mLabel;
-
-        /**
-         * PackageInfo.requestedPermissionsFlags for the new package being installed.
-         */
-        int mNewReqFlags;
-
-        /**
-         * PackageInfo.requestedPermissionsFlags for the currently installed
-         * package, if it is installed.
-         */
-        int mExistingReqFlags;
-
-        /**
-         * True if this should be considered a new permission.
-         */
-        boolean mNew;
-
-        MyPermissionInfo(PermissionInfo info) {
-            super(info);
-        }
-    }
-
-    /** @hide */
-    public static class PermissionItemView extends LinearLayout implements View.OnClickListener {
-        MyPermissionGroupInfo mGroup;
-        MyPermissionInfo mPerm;
-        AlertDialog mDialog;
-        private boolean mShowRevokeUI = false;
-        private String mPackageName;
-
-        public PermissionItemView(Context context, AttributeSet attrs) {
-            super(context, attrs);
-            setClickable(true);
-        }
-
-        public void setPermission(MyPermissionGroupInfo grp, MyPermissionInfo perm,
-                boolean first, CharSequence newPermPrefix, String packageName,
-                boolean showRevokeUI) {
-            mGroup = grp;
-            mPerm = perm;
-            mShowRevokeUI = showRevokeUI;
-            mPackageName = packageName;
-
-            ImageView permGrpIcon = findViewById(R.id.perm_icon);
-            TextView permNameView = findViewById(R.id.perm_name);
-
-            PackageManager pm = getContext().getPackageManager();
-            Drawable icon = null;
-            if (first) {
-                icon = grp.loadGroupIcon(getContext(), pm);
-            }
-            CharSequence label = perm.mLabel;
-            if (perm.mNew && newPermPrefix != null) {
-                // If this is a new permission, format it appropriately.
-                SpannableStringBuilder builder = new SpannableStringBuilder();
-                Parcel parcel = Parcel.obtain();
-                TextUtils.writeToParcel(newPermPrefix, parcel, 0);
-                parcel.setDataPosition(0);
-                CharSequence newStr = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
-                parcel.recycle();
-                builder.append(newStr);
-                builder.append(label);
-                label = builder;
-            }
-
-            permGrpIcon.setImageDrawable(icon);
-            permNameView.setText(label);
-            setOnClickListener(this);
-            if (localLOGV) Log.i(TAG, "Made perm item " + perm.name
-                    + ": " + label + " in group " + grp.name);
-        }
-
-        @Override
-        public void onClick(View v) {
-            if (mGroup != null && mPerm != null) {
-                if (mDialog != null) {
-                    mDialog.dismiss();
-                }
-                PackageManager pm = getContext().getPackageManager();
-                AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
-                builder.setTitle(mGroup.mLabel);
-                if (mPerm.descriptionRes != 0) {
-                    builder.setMessage(mPerm.loadDescription(pm));
-                } else {
-                    CharSequence appName;
-                    try {
-                        ApplicationInfo app = pm.getApplicationInfo(mPerm.packageName, 0);
-                        appName = app.loadLabel(pm);
-                    } catch (NameNotFoundException e) {
-                        appName = mPerm.packageName;
-                    }
-                    StringBuilder sbuilder = new StringBuilder(128);
-                    sbuilder.append(getContext().getString(
-                            R.string.perms_description_app, appName));
-                    sbuilder.append("\n\n");
-                    sbuilder.append(mPerm.name);
-                    builder.setMessage(sbuilder.toString());
-                }
-                builder.setCancelable(true);
-                builder.setIcon(mGroup.loadGroupIcon(getContext(), pm));
-                addRevokeUIIfNecessary(builder);
-                mDialog = builder.show();
-                mDialog.setCanceledOnTouchOutside(true);
-            }
-        }
-
-        @Override
-        protected void onDetachedFromWindow() {
-            super.onDetachedFromWindow();
-            if (mDialog != null) {
-                mDialog.dismiss();
-            }
-        }
-
-        private void addRevokeUIIfNecessary(AlertDialog.Builder builder) {
-            if (!mShowRevokeUI) {
-                return;
-            }
-
-            final boolean isRequired =
-                    ((mPerm.mExistingReqFlags & PackageInfo.REQUESTED_PERMISSION_REQUIRED) != 0);
-
-            if (isRequired) {
-                return;
-            }
-
-            DialogInterface.OnClickListener ocl = new DialogInterface.OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int which) {
-                    PackageManager pm = getContext().getPackageManager();
-                    pm.revokeRuntimePermission(mPackageName, mPerm.name,
-                            new UserHandle(mContext.getUserId()));
-                    PermissionItemView.this.setVisibility(View.GONE);
-                }
-            };
-            builder.setNegativeButton(R.string.revoke, ocl);
-            builder.setPositiveButton(R.string.ok, null);
-        }
-    }
-
-    private AppSecurityPermissions(Context context) {
-        mContext = context;
-        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        mPm = mContext.getPackageManager();
-        // Pick up from framework resources instead.
-        mNewPermPrefix = mContext.getText(R.string.perms_new_perm_prefix);
-    }
-
-    @UnsupportedAppUsage
-    public AppSecurityPermissions(Context context, String packageName) {
-        this(context);
-        mPackageName = packageName;
-        Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
-        PackageInfo pkgInfo;
-        try {
-            pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
-        } catch (NameNotFoundException e) {
-            Log.w(TAG, "Couldn't retrieve permissions for package:"+packageName);
-            return;
-        }
-        // Extract all user permissions
-        if((pkgInfo.applicationInfo != null) && (pkgInfo.applicationInfo.uid != -1)) {
-            getAllUsedPermissions(pkgInfo.applicationInfo.uid, permSet);
-        }
-        mPermsList.addAll(permSet);
-        setPermissions(mPermsList);
-    }
-
-    public AppSecurityPermissions(Context context, PackageInfo info) {
-        this(context);
-        Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
-        if(info == null) {
-            return;
-        }
-        mPackageName = info.packageName;
-
-        // Convert to a PackageInfo
-        PackageInfo installedPkgInfo = null;
-        // Get requested permissions
-        if (info.requestedPermissions != null) {
-            try {
-                installedPkgInfo = mPm.getPackageInfo(info.packageName,
-                        PackageManager.GET_PERMISSIONS);
-            } catch (NameNotFoundException e) {
-            }
-            extractPerms(info, permSet, installedPkgInfo);
-        }
-        // Get permissions related to shared user if any
-        if (info.sharedUserId != null) {
-            int sharedUid;
-            try {
-                sharedUid = mPm.getUidForSharedUser(info.sharedUserId);
-                getAllUsedPermissions(sharedUid, permSet);
-            } catch (NameNotFoundException e) {
-                Log.w(TAG, "Couldn't retrieve shared user id for: " + info.packageName);
-            }
-        }
-        // Retrieve list of permissions
-        mPermsList.addAll(permSet);
-        setPermissions(mPermsList);
-    }
-
     /**
      * Utility to retrieve a view displaying a single permission.  This provides
      * the old UI layout for permissions; it is only here for the device admin
@@ -327,197 +47,6 @@
                 description, dangerous, icon);
     }
 
-    private void getAllUsedPermissions(int sharedUid, Set<MyPermissionInfo> permSet) {
-        String sharedPkgList[] = mPm.getPackagesForUid(sharedUid);
-        if(sharedPkgList == null || (sharedPkgList.length == 0)) {
-            return;
-        }
-        for(String sharedPkg : sharedPkgList) {
-            getPermissionsForPackage(sharedPkg, permSet);
-        }
-    }
-
-    private void getPermissionsForPackage(String packageName, Set<MyPermissionInfo> permSet) {
-        try {
-            PackageInfo pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
-            extractPerms(pkgInfo, permSet, pkgInfo);
-        } catch (NameNotFoundException e) {
-            Log.w(TAG, "Couldn't retrieve permissions for package: " + packageName);
-        }
-    }
-
-    private void extractPerms(PackageInfo info, Set<MyPermissionInfo> permSet,
-            PackageInfo installedPkgInfo) {
-        String[] strList = info.requestedPermissions;
-        int[] flagsList = info.requestedPermissionsFlags;
-        if ((strList == null) || (strList.length == 0)) {
-            return;
-        }
-        for (int i=0; i<strList.length; i++) {
-            String permName = strList[i];
-            try {
-                PermissionInfo tmpPermInfo = mPm.getPermissionInfo(permName, 0);
-                if (tmpPermInfo == null) {
-                    continue;
-                }
-                int existingIndex = -1;
-                if (installedPkgInfo != null
-                        && installedPkgInfo.requestedPermissions != null) {
-                    for (int j=0; j<installedPkgInfo.requestedPermissions.length; j++) {
-                        if (permName.equals(installedPkgInfo.requestedPermissions[j])) {
-                            existingIndex = j;
-                            break;
-                        }
-                    }
-                }
-                final int existingFlags = existingIndex >= 0 ?
-                        installedPkgInfo.requestedPermissionsFlags[existingIndex] : 0;
-                if (!isDisplayablePermission(tmpPermInfo, flagsList[i], existingFlags)) {
-                    // This is not a permission that is interesting for the user
-                    // to see, so skip it.
-                    continue;
-                }
-                final String origGroupName = tmpPermInfo.group;
-                String groupName = origGroupName;
-                if (groupName == null) {
-                    groupName = tmpPermInfo.packageName;
-                    tmpPermInfo.group = groupName;
-                }
-                MyPermissionGroupInfo group = mPermGroups.get(groupName);
-                if (group == null) {
-                    PermissionGroupInfo grp = null;
-                    if (origGroupName != null) {
-                        grp = mPm.getPermissionGroupInfo(origGroupName, 0);
-                    }
-                    if (grp != null) {
-                        group = new MyPermissionGroupInfo(grp);
-                    } else {
-                        // We could be here either because the permission
-                        // didn't originally specify a group or the group it
-                        // gave couldn't be found.  In either case, we consider
-                        // its group to be the permission's package name.
-                        tmpPermInfo.group = tmpPermInfo.packageName;
-                        group = mPermGroups.get(tmpPermInfo.group);
-                        if (group == null) {
-                            group = new MyPermissionGroupInfo(tmpPermInfo);
-                        }
-                        group = new MyPermissionGroupInfo(tmpPermInfo);
-                    }
-                    mPermGroups.put(tmpPermInfo.group, group);
-                }
-                final boolean newPerm = installedPkgInfo != null
-                        && (existingFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0;
-                MyPermissionInfo myPerm = new MyPermissionInfo(tmpPermInfo);
-                myPerm.mNewReqFlags = flagsList[i];
-                myPerm.mExistingReqFlags = existingFlags;
-                // This is a new permission if the app is already installed and
-                // doesn't currently hold this permission.
-                myPerm.mNew = newPerm;
-                permSet.add(myPerm);
-            } catch (NameNotFoundException e) {
-                Log.i(TAG, "Ignoring unknown permission:"+permName);
-            }
-        }
-    }
-
-    @UnsupportedAppUsage
-    public int getPermissionCount() {
-        return getPermissionCount(WHICH_ALL);
-    }
-
-    private List<MyPermissionInfo> getPermissionList(MyPermissionGroupInfo grp, int which) {
-        if (which == WHICH_NEW) {
-            return grp.mNewPermissions;
-        } else {
-            return grp.mAllPermissions;
-        }
-    }
-
-    public int getPermissionCount(int which) {
-        int N = 0;
-        for (int i=0; i<mPermGroupsList.size(); i++) {
-            N += getPermissionList(mPermGroupsList.get(i), which).size();
-        }
-        return N;
-    }
-
-    @UnsupportedAppUsage
-    public View getPermissionsView() {
-        return getPermissionsView(WHICH_ALL, false);
-    }
-
-    public View getPermissionsViewWithRevokeButtons() {
-        return getPermissionsView(WHICH_ALL, true);
-    }
-
-    public View getPermissionsView(int which) {
-        return getPermissionsView(which, false);
-    }
-
-    private View getPermissionsView(int which, boolean showRevokeUI) {
-        LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
-        LinearLayout displayList = permsView.findViewById(R.id.perms_list);
-        View noPermsView = permsView.findViewById(R.id.no_permissions);
-
-        displayPermissions(mPermGroupsList, displayList, which, showRevokeUI);
-        if (displayList.getChildCount() <= 0) {
-            noPermsView.setVisibility(View.VISIBLE);
-        }
-
-        return permsView;
-    }
-
-    /**
-     * Utility method that displays permissions from a map containing group name and
-     * list of permission descriptions.
-     */
-    private void displayPermissions(List<MyPermissionGroupInfo> groups,
-            LinearLayout permListView, int which, boolean showRevokeUI) {
-        permListView.removeAllViews();
-
-        int spacing = (int)(8*mContext.getResources().getDisplayMetrics().density);
-
-        for (int i=0; i<groups.size(); i++) {
-            MyPermissionGroupInfo grp = groups.get(i);
-            final List<MyPermissionInfo> perms = getPermissionList(grp, which);
-            for (int j=0; j<perms.size(); j++) {
-                MyPermissionInfo perm = perms.get(j);
-                View view = getPermissionItemView(grp, perm, j == 0,
-                        which != WHICH_NEW ? mNewPermPrefix : null, showRevokeUI);
-                LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
-                        ViewGroup.LayoutParams.MATCH_PARENT,
-                        ViewGroup.LayoutParams.WRAP_CONTENT);
-                if (j == 0) {
-                    lp.topMargin = spacing;
-                }
-                if (j == grp.mAllPermissions.size()-1) {
-                    lp.bottomMargin = spacing;
-                }
-                if (permListView.getChildCount() == 0) {
-                    lp.topMargin *= 2;
-                }
-                permListView.addView(view, lp);
-            }
-        }
-    }
-
-    private PermissionItemView getPermissionItemView(MyPermissionGroupInfo grp,
-            MyPermissionInfo perm, boolean first, CharSequence newPermPrefix, boolean showRevokeUI) {
-        return getPermissionItemView(mContext, mInflater, grp, perm, first, newPermPrefix,
-                mPackageName, showRevokeUI);
-    }
-
-    private static PermissionItemView getPermissionItemView(Context context, LayoutInflater inflater,
-            MyPermissionGroupInfo grp, MyPermissionInfo perm, boolean first,
-            CharSequence newPermPrefix, String packageName, boolean showRevokeUI) {
-            PermissionItemView permView = (PermissionItemView)inflater.inflate(
-                (perm.flags & PermissionInfo.FLAG_COSTS_MONEY) != 0
-                        ? R.layout.app_permission_item_money : R.layout.app_permission_item,
-                null);
-        permView.setPermission(grp, perm, first, newPermPrefix, packageName, showRevokeUI);
-        return permView;
-    }
-
     private static View getPermissionItemViewOld(Context context, LayoutInflater inflater,
             CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
         View permView = inflater.inflate(R.layout.app_permission_item_old, null);
@@ -536,116 +65,4 @@
         }
         return permView;
     }
-
-    private boolean isDisplayablePermission(PermissionInfo pInfo, int newReqFlags,
-            int existingReqFlags) {
-        final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
-        final boolean isNormal = (base == PermissionInfo.PROTECTION_NORMAL);
-
-        // We do not show normal permissions in the UI.
-        if (isNormal) {
-            return false;
-        }
-
-        final boolean isDangerous = (base == PermissionInfo.PROTECTION_DANGEROUS)
-                || ((pInfo.protectionLevel&PermissionInfo.PROTECTION_FLAG_PRE23) != 0);
-        final boolean isRequired =
-                ((newReqFlags&PackageInfo.REQUESTED_PERMISSION_REQUIRED) != 0);
-        final boolean isDevelopment =
-                ((pInfo.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0);
-        final boolean wasGranted =
-                ((existingReqFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0);
-        final boolean isGranted =
-                ((newReqFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0);
-
-        // Dangerous and normal permissions are always shown to the user if the permission
-        // is required, or it was previously granted
-        if (isDangerous && (isRequired || wasGranted || isGranted)) {
-            return true;
-        }
-
-        // Development permissions are only shown to the user if they are already
-        // granted to the app -- if we are installing an app and they are not
-        // already granted, they will not be granted as part of the install.
-        if (isDevelopment && wasGranted) {
-            if (localLOGV) Log.i(TAG, "Special perm " + pInfo.name
-                    + ": protlevel=0x" + Integer.toHexString(pInfo.protectionLevel));
-            return true;
-        }
-        return false;
-    }
-
-    private static class PermissionGroupInfoComparator implements Comparator<MyPermissionGroupInfo> {
-        private final Collator sCollator = Collator.getInstance();
-        @Override
-        public final int compare(MyPermissionGroupInfo a, MyPermissionGroupInfo b) {
-            return sCollator.compare(a.mLabel, b.mLabel);
-        }
-    }
-
-    private static class PermissionInfoComparator implements Comparator<MyPermissionInfo> {
-        private final Collator sCollator = Collator.getInstance();
-        PermissionInfoComparator() {
-        }
-        public final int compare(MyPermissionInfo a, MyPermissionInfo b) {
-            return sCollator.compare(a.mLabel, b.mLabel);
-        }
-    }
-
-    private void addPermToList(List<MyPermissionInfo> permList,
-            MyPermissionInfo pInfo) {
-        if (pInfo.mLabel == null) {
-            pInfo.mLabel = pInfo.loadSafeLabel(mPm, 20000, PackageItemInfo.SAFE_LABEL_FLAG_TRIM
-                    | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
-        }
-        int idx = Collections.binarySearch(permList, pInfo, mPermComparator);
-        if(localLOGV) Log.i(TAG, "idx="+idx+", list.size="+permList.size());
-        if (idx < 0) {
-            idx = -idx-1;
-            permList.add(idx, pInfo);
-        }
-    }
-
-    private void setPermissions(List<MyPermissionInfo> permList) {
-        if (permList != null) {
-            // First pass to group permissions
-            for (MyPermissionInfo pInfo : permList) {
-                if(localLOGV) Log.i(TAG, "Processing permission:"+pInfo.name);
-                if(!isDisplayablePermission(pInfo, pInfo.mNewReqFlags, pInfo.mExistingReqFlags)) {
-                    if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" is not displayable");
-                    continue;
-                }
-                MyPermissionGroupInfo group = mPermGroups.get(pInfo.group);
-                if (group != null) {
-                    pInfo.mLabel = pInfo.loadSafeLabel(mPm, 20000,
-                            PackageItemInfo.SAFE_LABEL_FLAG_TRIM
-                            | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
-                    addPermToList(group.mAllPermissions, pInfo);
-                    if (pInfo.mNew) {
-                        addPermToList(group.mNewPermissions, pInfo);
-                    }
-                }
-            }
-        }
-
-        for (MyPermissionGroupInfo pgrp : mPermGroups.values()) {
-            if (pgrp.labelRes != 0 || pgrp.nonLocalizedLabel != null) {
-                pgrp.mLabel = pgrp.loadSafeLabel(mPm, 20000, PackageItemInfo.SAFE_LABEL_FLAG_TRIM
-                        | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
-            } else {
-                ApplicationInfo app;
-                try {
-                    app = mPm.getApplicationInfo(pgrp.packageName, 0);
-                    pgrp.mLabel = app.loadSafeLabel(mPm, 20000, PackageItemInfo.SAFE_LABEL_FLAG_TRIM
-                            | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
-                } catch (NameNotFoundException e) {
-                    pgrp.mLabel = pgrp.loadSafeLabel(mPm, 20000,
-                            PackageItemInfo.SAFE_LABEL_FLAG_TRIM
-                            | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
-                }
-            }
-            mPermGroupsList.add(pgrp);
-        }
-        Collections.sort(mPermGroupsList, mPermGroupComparator);
-    }
 }
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 8d09489..d35bec8 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -578,11 +578,16 @@
         stream.addProperty("checked", isChecked());
     }
 
-    @Override
-    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
-        super.onProvideAutofillStructure(structure, flags);
 
-        structure.setDataIsSensitive(!mCheckedFromResource);
+    /** @hide */
+    @Override
+    protected void onProvideStructure(@NonNull ViewStructure structure,
+            @ViewStructureType int viewFor, int flags) {
+        super.onProvideStructure(structure, viewFor, flags);
+
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
+            structure.setDataIsSensitive(!mCheckedFromResource);
+        }
     }
 
     @Override
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index f96f088..5b1544b 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3928,6 +3928,7 @@
                 SelectionModifierCursorController selectionController = getSelectionController();
                 if (selectionController.mStartHandle == null) {
                     // As these are for initializing selectionController, hide() must be called.
+                    loadHandleDrawables(false /* overwrite */);
                     selectionController.initHandles();
                     selectionController.hide();
                 }
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 6a3fc0f..7756a19 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.FloatRange;
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -28,6 +29,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Color;
+import android.graphics.Insets;
 import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
@@ -39,6 +41,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Message;
+import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.PixelCopy;
@@ -54,11 +57,15 @@
 import com.android.internal.R;
 import com.android.internal.util.Preconditions;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Android magnifier widget. Can be used by any view which is attached to a window.
  */
 @UiThread
 public final class Magnifier {
+    private static final String TAG = "Magnifier";
     // Use this to specify that a previous configuration value does not exist.
     private static final int NONEXISTENT_PREVIOUS_CONFIG_VALUE = -1;
     // The callbacks of the pixel copy requests will be invoked on
@@ -82,8 +89,8 @@
     private int mSourceWidth;
     // The height of the content that will be copied to the magnifier.
     private int mSourceHeight;
-    // Whether the zoom of the magnifier has changed since last content copy.
-    private boolean mDirtyZoom;
+    // Whether the zoom of the magnifier or the view position have changed since last content copy.
+    private boolean mDirtyState;
     // The elevation of the window containing the magnifier.
     private final float mWindowElevation;
     // The corner radius of the window containing the magnifier.
@@ -92,6 +99,16 @@
     private final int mDefaultHorizontalSourceToMagnifierOffset;
     // The vertical offset between the source and window coords when #show(float, float) is used.
     private final int mDefaultVerticalSourceToMagnifierOffset;
+    // Whether the magnifier will be clamped inside the main surface and not overlap system insets.
+    private final boolean mForcePositionWithinWindowSystemInsetsBounds;
+    // The behavior of the left bound of the rectangle where the content can be copied from.
+    private @SourceBound int mLeftContentBound;
+    // The behavior of the top bound of the rectangle where the content can be copied from.
+    private @SourceBound int mTopContentBound;
+    // The behavior of the right bound of the rectangle where the content can be copied from.
+    private @SourceBound int mRightContentBound;
+    // The behavior of the bottom bound of the rectangle where the content can be copied from.
+    private @SourceBound int mBottomContentBound;
     // The parent surface for the magnifier surface.
     private SurfaceInfo mParentSurface;
     // The surface where the content will be copied from.
@@ -140,6 +157,12 @@
                 params.mHorizontalDefaultSourceToMagnifierOffset;
         mDefaultVerticalSourceToMagnifierOffset =
                 params.mVerticalDefaultSourceToMagnifierOffset;
+        mForcePositionWithinWindowSystemInsetsBounds =
+                params.mForcePositionWithinWindowSystemInsetsBounds;
+        mLeftContentBound = params.mLeftContentBound;
+        mTopContentBound = params.mTopContentBound;
+        mRightContentBound = params.mRightContentBound;
+        mBottomContentBound = params.mBottomContentBound;
         // The view's surface coordinates will not be updated until the magnifier is first shown.
         mViewCoordinatesInSurface = new int[2];
     }
@@ -190,8 +213,6 @@
     public void show(@FloatRange(from = 0) float sourceCenterX,
             @FloatRange(from = 0) float sourceCenterY,
             float magnifierCenterX, float magnifierCenterY) {
-        sourceCenterX = Math.max(0, Math.min(sourceCenterX, mView.getWidth()));
-        sourceCenterY = Math.max(0, Math.min(sourceCenterY, mView.getHeight()));
 
         obtainSurfaces();
         obtainContentCoordinates(sourceCenterX, sourceCenterY);
@@ -200,7 +221,7 @@
         final int startX = mClampedCenterZoomCoords.x - mSourceWidth / 2;
         final int startY = mClampedCenterZoomCoords.y - mSourceHeight / 2;
         if (sourceCenterX != mPrevShowSourceCoords.x || sourceCenterY != mPrevShowSourceCoords.y
-                || mDirtyZoom) {
+                || mDirtyState) {
             if (mWindow == null) {
                 synchronized (mLock) {
                     mWindow = new InternalPopupWindow(mView.getContext(), mView.getDisplay(),
@@ -257,13 +278,13 @@
     public void update() {
         if (mWindow != null) {
             obtainSurfaces();
-            if (!mDirtyZoom) {
+            if (!mDirtyState) {
                 // Update the content shown in the magnifier.
                 performPixelCopy(mPrevStartCoordsInSurface.x, mPrevStartCoordsInSurface.y,
                         false /* update window position */);
             } else {
-                // If the zoom has changed, we cannot use the same top left coordinates
-                // as before, so just #show again to have them recomputed.
+                // If for example the zoom has changed, we cannot use the same top left
+                // coordinates as before, so just #show again to have them recomputed.
                 show(mPrevShowSourceCoords.x, mPrevShowSourceCoords.y,
                         mPrevShowWindowCoords.x, mPrevShowWindowCoords.y);
             }
@@ -310,6 +331,7 @@
 
     /**
      * Sets the zoom to be applied to the chosen content before being copied to the magnifier popup.
+     * The change will become effective at the next #show or #update call.
      * @param zoom the zoom to be set
      */
     public void setZoom(@FloatRange(from = 0f) float zoom) {
@@ -317,7 +339,7 @@
         mZoom = zoom;
         mSourceWidth = Math.round(mWindowWidth / mZoom);
         mSourceHeight = Math.round(mWindowHeight / mZoom);
-        mDirtyZoom = true;
+        mDirtyState = true;
     }
 
     /**
@@ -378,6 +400,17 @@
     }
 
     /**
+     * Returns whether the magnifier position will be adjusted such that the magnifier will be
+     * fully within the bounds of the main application window, by also avoiding any overlap with
+     * system insets (such as the one corresponding to the status bar).
+     * @return whether the magnifier position will be adjusted
+     * @see Magnifier.Builder#setForcePositionWithinWindowSystemInsetsBounds(boolean)
+     */
+    public boolean isForcePositionWithinWindowSystemInsetsBounds() {
+        return mForcePositionWithinWindowSystemInsetsBounds;
+    }
+
+    /**
      * Returns the top left coordinates of the magnifier, relative to the surface of the
      * main application window. They will be determined by the coordinates of the last
      * {@link #show(float, float)} or {@link #show(float, float, float, float)} call, adjusted
@@ -464,7 +497,14 @@
      * magnifier. These are relative to the surface the content is copied from.
      */
     private void obtainContentCoordinates(final float xPosInView, final float yPosInView) {
+        final int prevViewXInSurface = mViewCoordinatesInSurface[0];
+        final int prevViewYInSurface = mViewCoordinatesInSurface[1];
         mView.getLocationInSurface(mViewCoordinatesInSurface);
+        if (mViewCoordinatesInSurface[0] != prevViewXInSurface
+                || mViewCoordinatesInSurface[1] != prevViewYInSurface) {
+            mDirtyState = true;
+        }
+
         final int zoomCenterX;
         final int zoomCenterY;
         if (mView instanceof SurfaceView) {
@@ -476,8 +516,25 @@
             zoomCenterY = Math.round(yPosInView + mViewCoordinatesInSurface[1]);
         }
 
-        // Clamp the x location to avoid magnifying content which does not belong
-        // to the magnified view. This will not take into account overlapping views.
+        final Rect[] bounds = new Rect[3]; // [MAX_IN_SURFACE, MAX_IN_VIEW, MAX_VISIBLE]
+        // Obtain the surface bounds rectangle.
+        final Rect surfaceBounds = new Rect(0, 0,
+                mContentCopySurface.mWidth, mContentCopySurface.mHeight);
+        bounds[0] = surfaceBounds;
+        // Obtain the view bounds rectangle.
+        final Rect viewBounds;
+        if (mView instanceof SurfaceView) {
+            viewBounds = new Rect(0, 0, mContentCopySurface.mWidth, mContentCopySurface.mHeight);
+        } else {
+            viewBounds = new Rect(
+                    mViewCoordinatesInSurface[0],
+                    mViewCoordinatesInSurface[1],
+                    mViewCoordinatesInSurface[0] + mView.getWidth(),
+                    mViewCoordinatesInSurface[1] + mView.getHeight()
+            );
+        }
+        bounds[1] = viewBounds;
+        // Obtain the visible view region rectangle.
         final Rect viewVisibleRegion = new Rect();
         mView.getGlobalVisibleRect(viewVisibleRegion);
         if (mView.getViewRootImpl() != null) {
@@ -489,9 +546,40 @@
             // If we copy content from a SurfaceView, clamp coordinates relative to it.
             viewVisibleRegion.offset(-mViewCoordinatesInSurface[0], -mViewCoordinatesInSurface[1]);
         }
-        mClampedCenterZoomCoords.x = Math.max(viewVisibleRegion.left + mSourceWidth / 2, Math.min(
-                zoomCenterX, viewVisibleRegion.right - mSourceWidth / 2));
-        mClampedCenterZoomCoords.y = zoomCenterY;
+        bounds[2] = viewVisibleRegion;
+
+        // Aggregate the above to obtain the bounds where the content copy will be restricted.
+        int resolvedLeft = Integer.MIN_VALUE;
+        for (int i = mLeftContentBound; i >= 0; --i) {
+            resolvedLeft = Math.max(resolvedLeft, bounds[i].left);
+        }
+        int resolvedTop = Integer.MIN_VALUE;
+        for (int i = mTopContentBound; i >= 0; --i) {
+            resolvedTop = Math.max(resolvedTop, bounds[i].top);
+        }
+        int resolvedRight = Integer.MAX_VALUE;
+        for (int i = mRightContentBound; i >= 0; --i) {
+            resolvedRight = Math.min(resolvedRight, bounds[i].right);
+        }
+        int resolvedBottom = Integer.MAX_VALUE;
+        for (int i = mBottomContentBound; i >= 0; --i) {
+            resolvedBottom = Math.min(resolvedBottom, bounds[i].bottom);
+        }
+        // Adjust <left-right> and <top-bottom> pairs of bounds to make sense.
+        resolvedLeft = Math.min(resolvedLeft, mContentCopySurface.mWidth - mSourceWidth);
+        resolvedTop = Math.min(resolvedTop, mContentCopySurface.mHeight - mSourceHeight);
+        if (resolvedLeft < 0 || resolvedTop < 0) {
+            Log.e(TAG, "Magnifier's content is copied from a surface smaller than"
+                    + "the content requested size. This will probably lead to distorted content.");
+        }
+        resolvedRight = Math.max(resolvedRight, resolvedLeft + mSourceWidth);
+        resolvedBottom = Math.max(resolvedBottom, resolvedTop + mSourceHeight);
+
+        // Finally compute the coordinates of the source center.
+        mClampedCenterZoomCoords.x = Math.max(resolvedLeft + mSourceWidth / 2, Math.min(
+                zoomCenterX, resolvedRight - mSourceWidth / 2));
+        mClampedCenterZoomCoords.y = Math.max(resolvedTop + mSourceHeight / 2, Math.min(
+                zoomCenterY, resolvedBottom - mSourceHeight / 2));
     }
 
     /**
@@ -523,20 +611,16 @@
         if (mContentCopySurface.mSurface == null || !mContentCopySurface.mSurface.isValid()) {
             return;
         }
-        // Clamp copy coordinates inside the surface to avoid displaying distorted content.
-        final int clampedStartXInSurface = Math.max(0,
-                Math.min(startXInSurface, mContentCopySurface.mWidth - mSourceWidth));
-        final int clampedStartYInSurface = Math.max(0,
-                Math.min(startYInSurface, mContentCopySurface.mHeight - mSourceHeight));
+
         // Clamp window coordinates inside the parent surface, to avoid displaying
         // the magnifier out of screen or overlapping with system insets.
         final Point windowCoords = getCurrentClampedWindowCoordinates();
 
         // Perform the pixel copy.
-        mPixelCopyRequestRect.set(clampedStartXInSurface,
-                clampedStartYInSurface,
-                clampedStartXInSurface + mSourceWidth,
-                clampedStartYInSurface + mSourceHeight);
+        mPixelCopyRequestRect.set(startXInSurface,
+                startYInSurface,
+                startXInSurface + mSourceWidth,
+                startYInSurface + mSourceHeight);
         final InternalPopupWindow currentWindowInstance = mWindow;
         final Bitmap bitmap =
                 Bitmap.createBitmap(mSourceWidth, mSourceHeight, Bitmap.Config.ARGB_8888);
@@ -557,7 +641,7 @@
                 sPixelCopyHandlerThread.getThreadHandler());
         mPrevStartCoordsInSurface.x = startXInSurface;
         mPrevStartCoordsInSurface.y = startYInSurface;
-        mDirtyZoom = false;
+        mDirtyState = false;
     }
 
     /**
@@ -566,9 +650,14 @@
      * @return the current window coordinates, after they are clamped inside the parent surface
      */
     private Point getCurrentClampedWindowCoordinates() {
+        if (!mForcePositionWithinWindowSystemInsetsBounds) {
+            // No position adjustment should be done, so return the raw coordinates.
+            return new Point(mWindowCoords);
+        }
+
         final Rect windowBounds;
         if (mParentSurface.mIsMainWindowSurface) {
-            final Rect systemInsets = mView.getRootWindowInsets().getSystemWindowInsets();
+            final Insets systemInsets = mView.getRootWindowInsets().getSystemWindowInsets();
             windowBounds = new Rect(systemInsets.left, systemInsets.top,
                     mParentSurface.mWidth - systemInsets.right,
                     mParentSurface.mHeight - systemInsets.bottom);
@@ -890,6 +979,11 @@
         private @FloatRange(from = 0f) float mCornerRadius;
         private int mHorizontalDefaultSourceToMagnifierOffset;
         private int mVerticalDefaultSourceToMagnifierOffset;
+        private boolean mForcePositionWithinWindowSystemInsetsBounds;
+        private @SourceBound int mLeftContentBound;
+        private @SourceBound int mTopContentBound;
+        private @SourceBound int mRightContentBound;
+        private @SourceBound int  mBottomContentBound;
 
         /**
          * Construct a new builder for {@link Magnifier} objects.
@@ -914,6 +1008,11 @@
             mVerticalDefaultSourceToMagnifierOffset =
                     a.getDimensionPixelSize(R.styleable.Magnifier_magnifierVerticalOffset, 0);
             a.recycle();
+            mForcePositionWithinWindowSystemInsetsBounds = true;
+            mLeftContentBound = SOURCE_BOUND_MAX_VISIBLE;
+            mTopContentBound = SOURCE_BOUND_MAX_IN_SURFACE;
+            mRightContentBound = SOURCE_BOUND_MAX_VISIBLE;
+            mBottomContentBound = SOURCE_BOUND_MAX_IN_SURFACE;
         }
 
         /**
@@ -999,6 +1098,74 @@
         }
 
         /**
+         * Defines the behavior of the magnifier when it is requested to position outside the
+         * surface of the main application window. The default value is {@code true}, which means
+         * that the position will be adjusted such that the magnifier will be fully within the
+         * bounds of the main application window, by also avoiding any overlap with system insets
+         * (such as the one corresponding to the status bar). If you require a custom behavior, this
+         * flag should be set to {@code false}, meaning that the magnifier will be able to cross the
+         * main application surface boundaries (and also overlap the system insets). This should be
+         * handled with care, when passing coordinates to {@link #show(float, float)}; note that:
+         * <ul>
+         *   <li>in a multiwindow context, if the magnifier crosses the boundary between the two
+         *   windows, it will not be able to show over the window of the other application</li>
+         *   <li>if the magnifier overlaps the status bar, there is no guarantee about which one
+         *   will be displayed on top. This should be handled with care.</li>
+         * </ul>
+         * @param force whether the magnifier position will be adjusted
+         */
+        public Builder setForcePositionWithinWindowSystemInsetsBounds(boolean force) {
+            mForcePositionWithinWindowSystemInsetsBounds = force;
+            return this;
+        }
+
+        /**
+         * Defines the bounds of the rectangle where the magnifier will be able to copy its content
+         * from. The content will always be copied from the {@link Surface} of the main application
+         * window unless the magnified view is a {@link SurfaceView}, in which case its backing
+         * surface will be used. Each bound can have a different behavior, with the options being:
+         * <ul>
+         *   <li>{@link #SOURCE_BOUND_MAX_VISIBLE}, which extends the bound as much as possible
+         *   while remaining in the visible region of the magnified view, as given by
+         *   {@link android.view.View#getGlobalVisibleRect(Rect)}. For example, this will take into
+         *   account the case when the view is contained in a scrollable container, and the
+         *   magnifier will refuse to copy content outside of the visible view region</li>
+         *   <li>{@link #SOURCE_BOUND_MAX_IN_VIEW}, which extends the bound as much as possible
+         *   while remaining in the bounds of the view. Note that, although this option is
+         *   used, the magnifier will always only display content visible on the screen: if the
+         *   view lays outside the screen or is covered by a different view either partially or
+         *   totally, the magnifier will not show any view region not visible on the screen.</li>
+         *   <li>{@link #SOURCE_BOUND_MAX_IN_SURFACE}, which extends the bound as much
+         *   as possible while remaining inside the surface the content is copied from.</li>
+         * </ul>
+         * Note that if either of the first three options is used, the bound will be compared to
+         * the bound of the surface (i.e. as if {@link #SOURCE_BOUND_MAX_IN_SURFACE} was used),
+         * and the more restrictive one will be chosen. In other words, no attempt to copy content
+         * from outside the surface will be permitted. If two opposite bounds are not well-behaved
+         * (i.e. left + sourceWidth > right or top + sourceHeight > bottom), the left and top
+         * bounds will have priority and the others will be extended accordingly. If the pairs
+         * obtained this way still remain out of bounds, the smallest possible offset will be added
+         * to the pairs to bring them inside the surface bounds. If this is impossible
+         * (i.e. the surface is too small for the size of the content we try to copy on either
+         * dimension), an error will be logged and the magnifier content will look distorted.
+         * The default values assumed by the builder for the source bounds are
+         * left: {@link #SOURCE_BOUND_MAX_VISIBLE}, top: {@link #SOURCE_BOUND_MAX_IN_SURFACE},
+         * right: {@link #SOURCE_BOUND_MAX_VISIBLE}, bottom: {@link #SOURCE_BOUND_MAX_IN_SURFACE}.
+         * @param left the left bound for content copy
+         * @param top the top bound for content copy
+         * @param right the right bound for content copy
+         * @param bottom the bottom bound for content copy
+         */
+        public Builder setSourceBounds(@SourceBound int left, @SourceBound int top,
+                @SourceBound int right, @SourceBound int bottom) {
+            mLeftContentBound = left;
+            mTopContentBound = top;
+            mRightContentBound = right;
+            mBottomContentBound = bottom;
+            return this;
+        }
+
+        /**
          * Builds a {@link Magnifier} instance based on the configuration of this {@link Builder}.
          */
         public @NonNull Magnifier build() {
@@ -1006,6 +1173,38 @@
         }
     }
 
+    /**
+     * A source bound that will extend as much as possible, while remaining within the surface
+     * the content is copied from.
+     */
+
+    public static final int SOURCE_BOUND_MAX_IN_SURFACE = 0;
+    /**
+     * A source bound that will extend as much as possible, while remaining within the
+     * magnified view.
+     */
+
+    public static final int SOURCE_BOUND_MAX_IN_VIEW = 1;
+
+    /**
+     * A source bound that will extend as much as possible, while remaining within the
+     * visible region of the magnified view, as determined by
+     * {@link View#getGlobalVisibleRect(Rect)}.
+     */
+    public static final int SOURCE_BOUND_MAX_VISIBLE = 2;
+
+
+    /**
+     * Used to describe the {@link Surface} rectangle where the magnifier's content is allowed
+     * to be copied from. For more details, see method
+     * {@link Magnifier.Builder#setSourceBounds(int, int, int, int)}
+     *
+     * @hide
+     */
+    @IntDef({SOURCE_BOUND_MAX_IN_SURFACE, SOURCE_BOUND_MAX_IN_VIEW, SOURCE_BOUND_MAX_VISIBLE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SourceBound {}
+
     // The rest of the file consists of test APIs.
 
     /**
diff --git a/core/java/android/widget/MediaControlView2.java b/core/java/android/widget/MediaControlView2.java
deleted file mode 100644
index f52854a..0000000
--- a/core/java/android/widget/MediaControlView2.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2017 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.widget;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.media.SessionToken2;
-import android.media.session.MediaController;
-import android.media.update.ApiLoader;
-import android.media.update.MediaControlView2Provider;
-import android.media.update.ViewGroupHelper;
-import android.util.AttributeSet;
-import android.view.View;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-// TODO: Use link annotation to refer VideoView2 once VideoView2 became unhidden.
-/**
- * @hide
- * A View that contains the controls for MediaPlayer2.
- * It provides a wide range of UI including buttons such as "Play/Pause", "Rewind", "Fast Forward",
- * "Subtitle", "Full Screen", and it is also possible to add multiple custom buttons.
- *
- * <p>
- * <em> MediaControlView2 can be initialized in two different ways: </em>
- * 1) When VideoView2 is initialized, it automatically initializes a MediaControlView2 instance and
- * adds it to the view.
- * 2) Initialize MediaControlView2 programmatically and add it to a ViewGroup instance.
- *
- * In the first option, VideoView2 automatically connects MediaControlView2 to MediaController,
- * which is necessary to communicate with MediaSession2. In the second option, however, the
- * developer needs to manually retrieve a MediaController instance and set it to MediaControlView2
- * by calling setController(MediaController controller).
- *
- * <p>
- * There is no separate method that handles the show/hide behavior for MediaControlView2. Instead,
- * one can directly change the visibility of this view by calling View.setVisibility(int). The
- * values supported are View.VISIBLE and View.GONE.
- * In addition, the following customization is supported:
- * Set focus to the play/pause button by calling requestPlayButtonFocus().
- *
- * <p>
- * It is also possible to add custom buttons with custom icons and actions inside MediaControlView2.
- * Those buttons will be shown when the overflow button is clicked.
- * See VideoView2#setCustomActions for more details on how to add.
- */
-public class MediaControlView2 extends ViewGroupHelper<MediaControlView2Provider> {
-    /** @hide */
-    @IntDef({
-            BUTTON_PLAY_PAUSE,
-            BUTTON_FFWD,
-            BUTTON_REW,
-            BUTTON_NEXT,
-            BUTTON_PREV,
-            BUTTON_SUBTITLE,
-            BUTTON_FULL_SCREEN,
-            BUTTON_OVERFLOW,
-            BUTTON_MUTE,
-            BUTTON_ASPECT_RATIO,
-            BUTTON_SETTINGS
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Button {}
-
-    /**
-     * MediaControlView2 button value for playing and pausing media.
-     * @hide
-     */
-    public static final int BUTTON_PLAY_PAUSE = 1;
-    /**
-     * MediaControlView2 button value for jumping 30 seconds forward.
-     * @hide
-     */
-    public static final int BUTTON_FFWD = 2;
-    /**
-     * MediaControlView2 button value for jumping 10 seconds backward.
-     * @hide
-     */
-    public static final int BUTTON_REW = 3;
-    /**
-     * MediaControlView2 button value for jumping to next media.
-     * @hide
-     */
-    public static final int BUTTON_NEXT = 4;
-    /**
-     * MediaControlView2 button value for jumping to previous media.
-     * @hide
-     */
-    public static final int BUTTON_PREV = 5;
-    /**
-     * MediaControlView2 button value for showing/hiding subtitle track.
-     * @hide
-     */
-    public static final int BUTTON_SUBTITLE = 6;
-    /**
-     * MediaControlView2 button value for toggling full screen.
-     * @hide
-     */
-    public static final int BUTTON_FULL_SCREEN = 7;
-    /**
-     * MediaControlView2 button value for showing/hiding overflow buttons.
-     * @hide
-     */
-    public static final int BUTTON_OVERFLOW = 8;
-    /**
-     * MediaControlView2 button value for muting audio.
-     * @hide
-     */
-    public static final int BUTTON_MUTE = 9;
-    /**
-     * MediaControlView2 button value for adjusting aspect ratio of view.
-     * @hide
-     */
-    public static final int BUTTON_ASPECT_RATIO = 10;
-    /**
-     * MediaControlView2 button value for showing/hiding settings page.
-     * @hide
-     */
-    public static final int BUTTON_SETTINGS = 11;
-
-    public MediaControlView2(@NonNull Context context) {
-        this(context, null);
-    }
-
-    public MediaControlView2(@NonNull Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public MediaControlView2(@NonNull Context context, @Nullable AttributeSet attrs,
-            int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public MediaControlView2(@NonNull Context context, @Nullable AttributeSet attrs,
-            int defStyleAttr, int defStyleRes) {
-        super((instance, superProvider, privateProvider) ->
-                ApiLoader.getProvider().createMediaControlView2(
-                        (MediaControlView2) instance, superProvider, privateProvider,
-                        attrs, defStyleAttr, defStyleRes),
-                context, attrs, defStyleAttr, defStyleRes);
-        mProvider.initialize(attrs, defStyleAttr, defStyleRes);
-    }
-
-    /**
-     * Sets MediaSession2 token to control corresponding MediaSession2.
-     */
-    public void setMediaSessionToken(SessionToken2 token) {
-        mProvider.setMediaSessionToken_impl(token);
-    }
-
-    /**
-     * Registers a callback to be invoked when the fullscreen mode should be changed.
-     * @param l The callback that will be run
-     */
-    public void setOnFullScreenListener(OnFullScreenListener l) {
-        mProvider.setOnFullScreenListener_impl(l);
-    }
-
-    /**
-     * @hide TODO: remove once the implementation is revised
-     */
-    public void setController(MediaController controller) {
-        mProvider.setController_impl(controller);
-    }
-
-    /**
-     * Changes the visibility state of an individual button. Default value is View.Visible.
-     *
-     * @param button the {@code Button} assigned to individual buttons
-     * <ul>
-     * <li>{@link #BUTTON_PLAY_PAUSE}
-     * <li>{@link #BUTTON_FFWD}
-     * <li>{@link #BUTTON_REW}
-     * <li>{@link #BUTTON_NEXT}
-     * <li>{@link #BUTTON_PREV}
-     * <li>{@link #BUTTON_SUBTITLE}
-     * <li>{@link #BUTTON_FULL_SCREEN}
-     * <li>{@link #BUTTON_MUTE}
-     * <li>{@link #BUTTON_OVERFLOW}
-     * <li>{@link #BUTTON_ASPECT_RATIO}
-     * <li>{@link #BUTTON_SETTINGS}
-     * </ul>
-     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
-     * @hide
-     */
-    public void setButtonVisibility(@Button int button, @Visibility int visibility) {
-        mProvider.setButtonVisibility_impl(button, visibility);
-    }
-
-    /**
-     *  Requests focus for the play/pause button.
-     */
-    public void requestPlayButtonFocus() {
-        mProvider.requestPlayButtonFocus_impl();
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        mProvider.onLayout_impl(changed, l, t, r, b);
-    }
-
-    /**
-     * Interface definition of a callback to be invoked to inform the fullscreen mode is changed.
-     * Application should handle the fullscreen mode accordingly.
-     */
-    public interface OnFullScreenListener {
-        /**
-         * Called to indicate a fullscreen mode change.
-         */
-        void onFullScreen(View view, boolean fullScreen);
-    }
-}
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 327a5c1..ab12eac 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.IdRes;
+import android.annotation.NonNull;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -424,10 +425,15 @@
         }
     }
 
+    /** @hide */
     @Override
-    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
-        super.onProvideAutofillStructure(structure, flags);
-        structure.setDataIsSensitive(mCheckedId != mInitialCheckedId);
+    protected void onProvideStructure(@NonNull ViewStructure structure,
+            @ViewStructureType int viewFor, int flags) {
+        super.onProvideStructure(structure, viewFor, flags);
+
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
+            structure.setDataIsSensitive(mCheckedId != mInitialCheckedId);
+        }
     }
 
     @Override
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index a93604f..c0979fe 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -196,12 +196,6 @@
     private boolean mIsRoot = true;
 
     /**
-     * Optional theme resource id applied in inflateView(). When 0, Theme.DeviceDefault will be
-     * used.
-     */
-    private int mApplyThemeResId;
-
-    /**
      * Whether reapply is disallowed on this remoteview. This maybe be true if some actions modify
      * the layout in a way that isn't recoverable, since views are being removed.
      */
@@ -3262,14 +3256,6 @@
     }
 
     /**
-     * Set the theme used in apply() and applyASync().
-     * @hide
-     */
-    public void setApplyTheme(@StyleRes int themeResId) {
-        mApplyThemeResId = themeResId;
-    }
-
-    /**
      * Inflates the view hierarchy represented by this object and applies
      * all of the actions.
      *
@@ -3290,11 +3276,25 @@
 
         View result = inflateView(context, rvToApply, parent);
         rvToApply.performApply(result, parent, handler);
+        return result;
+    }
 
+    /** @hide */
+    public View applyWithTheme(Context context, ViewGroup parent, OnClickHandler handler,
+            @StyleRes int applyThemeResId) {
+        RemoteViews rvToApply = getRemoteViewsToApply(context);
+
+        View result = inflateView(context, rvToApply, parent, applyThemeResId);
+        rvToApply.performApply(result, parent, handler);
         return result;
     }
 
     private View inflateView(Context context, RemoteViews rv, ViewGroup parent) {
+        return inflateView(context, rv, parent, 0);
+    }
+
+    private View inflateView(Context context, RemoteViews rv, ViewGroup parent,
+            @StyleRes int applyThemeResId) {
         // RemoteViews may be built by an application installed in another
         // user. So build a context that loads resources from that user but
         // still returns the current users userId so settings like data / time formats
@@ -3303,8 +3303,8 @@
         Context inflationContext = new RemoteViewsContextWrapper(context, contextForResources);
 
         // If mApplyThemeResId is not given, Theme.DeviceDefault will be used.
-        if (mApplyThemeResId != 0) {
-            inflationContext = new ContextThemeWrapper(inflationContext, mApplyThemeResId);
+        if (applyThemeResId != 0) {
+            inflationContext = new ContextThemeWrapper(inflationContext, applyThemeResId);
         }
         LayoutInflater inflater = (LayoutInflater)
                 context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 8bfc151..d55c09f 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -1422,17 +1422,24 @@
     @Override
     public void onProvideStructure(ViewStructure structure) {
         super.onProvideStructure(structure);
-        onProvideAutoFillStructureForAssistOrAutofill(structure);
+        onProvideStructureForAssistOrAutofillOrViewCapture(structure);
     }
 
     @Override
     public void onProvideAutofillStructure(ViewStructure structure, int flags) {
         super.onProvideAutofillStructure(structure, flags);
-        onProvideAutoFillStructureForAssistOrAutofill(structure);
+        onProvideStructureForAssistOrAutofillOrViewCapture(structure);
     }
 
-    // NOTE: currently there is no difference for Assist or AutoFill, so it doesn't take flags
-    private void onProvideAutoFillStructureForAssistOrAutofill(ViewStructure structure) {
+    @Override
+    public boolean onProvideContentCaptureStructure(ViewStructure structure, int flags) {
+        final boolean notifyManager = super.onProvideContentCaptureStructure(structure, flags);
+        onProvideStructureForAssistOrAutofillOrViewCapture(structure);
+        return notifyManager;
+    }
+
+    // NOTE: currently there is no difference for any type, so it doesn't take flags
+    private void onProvideStructureForAssistOrAutofillOrViewCapture(ViewStructure structure) {
         CharSequence switchText = isChecked() ? mTextOn : mTextOff;
         if (!TextUtils.isEmpty(switchText)) {
             CharSequence oldText = structure.getText();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 572670f..35be766 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -166,6 +166,7 @@
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
+import android.view.intelligence.IntelligenceManager;
 import android.view.textclassifier.TextClassification;
 import android.view.textclassifier.TextClassificationContext;
 import android.view.textclassifier.TextClassificationManager;
@@ -948,6 +949,9 @@
         if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
             setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
         }
+        if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
+            setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
+        }
 
         setTextInternal("");
 
@@ -6072,7 +6076,7 @@
         if (needEditableForNotification) {
             sendAfterTextChanged((Editable) text);
         } else {
-            notifyAutoFillManagerAfterTextChanged();
+            notifyListeningManagersAfterTextChanged();
         }
 
         // SelectionModifierCursorController depends on textCanBeSelected, which depends on text
@@ -10120,24 +10124,37 @@
             }
         }
 
-        // Always notify AutoFillManager - it will return right away if autofill is disabled.
-        notifyAutoFillManagerAfterTextChanged();
+        notifyListeningManagersAfterTextChanged();
 
         hideErrorIfUnchanged();
     }
 
-    private void notifyAutoFillManagerAfterTextChanged() {
-        // It is important to not check whether the view is important for autofill
-        // since the user can trigger autofill manually on not important views.
-        if (!isAutofillable()) {
-            return;
-        }
-        final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
-        if (afm != null) {
-            if (android.view.autofill.Helper.sVerbose) {
-                Log.v(LOG_TAG, "notifyAutoFillManagerAfterTextChanged");
+    /**
+     * Notify managers (such as {@link AutofillManager} and {@link IntelligenceManager}) that are
+     * interested on text changes.
+     */
+    private void notifyListeningManagersAfterTextChanged() {
+
+        // Autofill
+        if (isAutofillable()) {
+            // It is important to not check whether the view is important for autofill
+            // since the user can trigger autofill manually on not important views.
+            final AutofillManager afm = mContext.getSystemService(AutofillManager.class);
+            if (afm != null) {
+                if (android.view.autofill.Helper.sVerbose) {
+                    Log.v(LOG_TAG, "notifyAutoFillManagerAfterTextChanged");
+                }
+                afm.notifyValueChanged(TextView.this);
             }
-            afm.notifyValueChanged(TextView.this);
+        }
+
+        // ContentCapture
+        if (isImportantForContentCapture() && isTextEditable()) {
+            final IntelligenceManager im = mContext.getSystemService(IntelligenceManager.class);
+            if (im != null && im.isContentCaptureEnabled()) {
+                // TODO(b/111276913): pass flags when edited by user / add CTS test
+                im.notifyViewTextChanged(getAutofillId(), getText(), /* flags= */ 0);
+            }
         }
     }
 
@@ -10897,24 +10914,19 @@
         return TextView.class.getName();
     }
 
+    /** @hide */
     @Override
-    public void onProvideStructure(ViewStructure structure) {
-        super.onProvideStructure(structure);
-        onProvideAutoStructureForAssistOrAutofill(structure, false);
-    }
+    protected void onProvideStructure(@NonNull ViewStructure structure,
+            @ViewStructureType int viewFor, int flags) {
+        super.onProvideStructure(structure, viewFor, flags);
 
-    @Override
-    public void onProvideAutofillStructure(ViewStructure structure, int flags) {
-        super.onProvideAutofillStructure(structure, flags);
-        onProvideAutoStructureForAssistOrAutofill(structure, true);
-    }
-
-    private void onProvideAutoStructureForAssistOrAutofill(ViewStructure structure,
-            boolean forAutofill) {
         final boolean isPassword = hasPasswordTransformationMethod()
                 || isPasswordInputType(getInputType());
-        if (forAutofill) {
-            structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId);
+        if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+            if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
+                structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId);
+            }
             if (mTextId != ResourceId.ID_NULL) {
                 try {
                     structure.setTextIdEntry(getResources().getResourceEntryName(mTextId));
@@ -10927,7 +10939,8 @@
             }
         }
 
-        if (!isPassword || forAutofill) {
+        if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+                || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
             if (mLayout == null) {
                 assumeLayout();
             }
@@ -10936,7 +10949,7 @@
             if (lineCount <= 1) {
                 // Simple case: this is a single line.
                 final CharSequence text = getText();
-                if (forAutofill) {
+                if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
                     structure.setText(text);
                 } else {
                     structure.setText(text, getSelectionStart(), getSelectionEnd());
@@ -11000,7 +11013,7 @@
                     text = text.subSequence(expandedTopChar, expandedBottomChar);
                 }
 
-                if (forAutofill) {
+                if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
                     structure.setText(text);
                 } else {
                     structure.setText(text, selStart - expandedTopChar, selEnd - expandedTopChar);
@@ -11016,7 +11029,8 @@
                 }
             }
 
-            if (!forAutofill) {
+            if (viewFor == VIEW_STRUCTURE_FOR_ASSIST
+                    || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
                 // Extract style information that applies to the TextView as a whole.
                 int style = 0;
                 int typefaceStyle = getTypefaceStyle();
@@ -11043,7 +11057,9 @@
                 // of the View (and can be any drawable) or a BackgroundColorSpan inside the text.
                 structure.setTextStyle(getTextSize(), getCurrentTextColor(),
                         AssistStructure.ViewNode.TEXT_COLOR_UNDEFINED /* bgColor */, style);
-            } else {
+            }
+            if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+                    || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
                 structure.setMinTextEms(getMinEms());
                 structure.setMaxTextEms(getMaxEms());
                 int maxLength = -1;
diff --git a/core/java/android/widget/VideoView2.java b/core/java/android/widget/VideoView2.java
deleted file mode 100644
index 0724294a..0000000
--- a/core/java/android/widget/VideoView2.java
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * Copyright 2018 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.widget;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
-import android.content.Context;
-import android.media.AudioAttributes;
-import android.media.AudioManager;
-import android.media.DataSourceDesc;
-import android.media.MediaItem2;
-import android.media.MediaMetadata2;
-import android.media.MediaPlayer2;
-import android.media.SessionToken2;
-import android.media.session.MediaController;
-import android.media.session.PlaybackState;
-import android.media.update.ApiLoader;
-import android.media.update.VideoView2Provider;
-import android.media.update.ViewGroupHelper;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.view.View;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-// TODO: Replace MediaSession wtih MediaSession2 once MediaSession2 is submitted.
-/**
- * @hide
- * Displays a video file.  VideoView2 class is a View class which is wrapping {@link MediaPlayer2}
- * so that developers can easily implement a video rendering application.
- *
- * <p>
- * <em> Data sources that VideoView2 supports : </em>
- * VideoView2 can play video files and audio-only files as
- * well. It can load from various sources such as resources or content providers. The supported
- * media file formats are the same as {@link MediaPlayer2}.
- *
- * <p>
- * <em> View type can be selected : </em>
- * VideoView2 can render videos on top of TextureView as well as
- * SurfaceView selectively. The default is SurfaceView and it can be changed using
- * {@link #setViewType(int)} method. Using SurfaceView is recommended in most cases for saving
- * battery. TextureView might be preferred for supporting various UIs such as animation and
- * translucency.
- *
- * <p>
- * <em> Differences between {@link VideoView} class : </em>
- * VideoView2 covers and inherits the most of
- * VideoView's functionalities. The main differences are
- * <ul>
- * <li> VideoView2 inherits FrameLayout and renders videos using SurfaceView and TextureView
- * selectively while VideoView inherits SurfaceView class.
- * <li> VideoView2 is integrated with MediaControlView2 and a default MediaControlView2 instance is
- * attached to VideoView2 by default. If a developer does not want to use the default
- * MediaControlView2, needs to set enableControlView attribute to false. For instance,
- * <pre>
- * &lt;VideoView2
- *     android:id="@+id/video_view"
- *     xmlns:widget="http://schemas.android.com/apk/com.android.media.update"
- *     widget:enableControlView="false" /&gt;
- * </pre>
- * If a developer wants to attach a customed MediaControlView2, then set enableControlView attribute
- * to false and assign the customed media control widget using {@link #setMediaControlView2}.
- * <li> VideoView2 is integrated with MediaPlayer2 while VideoView is integrated with MediaPlayer.
- * <li> VideoView2 is integrated with MediaSession and so it responses with media key events.
- * A VideoView2 keeps a MediaSession instance internally and connects it to a corresponding
- * MediaControlView2 instance.
- * </p>
- * </ul>
- *
- * <p>
- * <em> Audio focus and audio attributes : </em>
- * By default, VideoView2 requests audio focus with
- * {@link AudioManager#AUDIOFOCUS_GAIN}. Use {@link #setAudioFocusRequest(int)} to change this
- * behavior. The default {@link AudioAttributes} used during playback have a usage of
- * {@link AudioAttributes#USAGE_MEDIA} and a content type of
- * {@link AudioAttributes#CONTENT_TYPE_MOVIE}, use {@link #setAudioAttributes(AudioAttributes)} to
- * modify them.
- *
- * <p>
- * Note: VideoView2 does not retain its full state when going into the background. In particular, it
- * does not restore the current play state, play position, selected tracks. Applications should save
- * and restore these on their own in {@link android.app.Activity#onSaveInstanceState} and
- * {@link android.app.Activity#onRestoreInstanceState}.
- */
-public class VideoView2 extends ViewGroupHelper<VideoView2Provider> {
-    /** @hide */
-    @IntDef({
-            VIEW_TYPE_TEXTUREVIEW,
-            VIEW_TYPE_SURFACEVIEW
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ViewType {}
-
-    /**
-     * Indicates video is rendering on SurfaceView.
-     *
-     * @see #setViewType
-     */
-    public static final int VIEW_TYPE_SURFACEVIEW = 1;
-
-    /**
-     * Indicates video is rendering on TextureView.
-     *
-     * @see #setViewType
-     */
-    public static final int VIEW_TYPE_TEXTUREVIEW = 2;
-
-    public VideoView2(@NonNull Context context) {
-        this(context, null);
-    }
-
-    public VideoView2(@NonNull Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public VideoView2(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public VideoView2(
-            @NonNull Context context, @Nullable AttributeSet attrs,
-            int defStyleAttr, int defStyleRes) {
-        super((instance, superProvider, privateProvider) ->
-                ApiLoader.getProvider().createVideoView2(
-                        (VideoView2) instance, superProvider, privateProvider,
-                        attrs, defStyleAttr, defStyleRes),
-                context, attrs, defStyleAttr, defStyleRes);
-        mProvider.initialize(attrs, defStyleAttr, defStyleRes);
-    }
-
-    /**
-     * Sets MediaControlView2 instance. It will replace the previously assigned MediaControlView2
-     * instance if any.
-     *
-     * @param mediaControlView a media control view2 instance.
-     * @param intervalMs a time interval in milliseconds until VideoView2 hides MediaControlView2.
-     */
-    public void setMediaControlView2(MediaControlView2 mediaControlView, long intervalMs) {
-        mProvider.setMediaControlView2_impl(mediaControlView, intervalMs);
-    }
-
-    /**
-     * Returns MediaControlView2 instance which is currently attached to VideoView2 by default or by
-     * {@link #setMediaControlView2} method.
-     */
-    public MediaControlView2 getMediaControlView2() {
-        return mProvider.getMediaControlView2_impl();
-    }
-
-    /**
-     * Sets MediaMetadata2 instance. It will replace the previously assigned MediaMetadata2 instance
-     * if any.
-     *
-     * @param metadata a MediaMetadata2 instance.
-     * @hide
-     */
-    public void setMediaMetadata(MediaMetadata2 metadata) {
-        mProvider.setMediaMetadata_impl(metadata);
-    }
-
-    /**
-     * Returns MediaMetadata2 instance which is retrieved from MediaPlayer2 inside VideoView2 by
-     * default or by {@link #setMediaMetadata} method.
-     * @hide
-     */
-    public MediaMetadata2 getMediaMetadata() {
-        // TODO: add to Javadoc whether this value can be null or not when integrating with
-        // MediaSession2.
-        return mProvider.getMediaMetadata_impl();
-    }
-
-    /**
-     * Returns MediaController instance which is connected with MediaSession that VideoView2 is
-     * using. This method should be called when VideoView2 is attached to window, or it throws
-     * IllegalStateException, since internal MediaSession instance is not available until
-     * this view is attached to window. Please check {@link android.view.View#isAttachedToWindow}
-     * before calling this method.
-     *
-     * @throws IllegalStateException if interal MediaSession is not created yet.
-     * @hide  TODO: remove
-     */
-    @UnsupportedAppUsage
-    public MediaController getMediaController() {
-        return mProvider.getMediaController_impl();
-    }
-
-    /**
-     * Returns {@link android.media.SessionToken2} so that developers create their own
-     * {@link android.media.MediaController2} instance. This method should be called when VideoView2
-     * is attached to window, or it throws IllegalStateException.
-     *
-     * @throws IllegalStateException if interal MediaSession is not created yet.
-     */
-    public SessionToken2 getMediaSessionToken() {
-        return mProvider.getMediaSessionToken_impl();
-    }
-
-    /**
-     * Shows or hides closed caption or subtitles if there is any.
-     * The first subtitle track will be chosen if there multiple subtitle tracks exist.
-     * Default behavior of VideoView2 is not showing subtitle.
-     * @param enable shows closed caption or subtitles if this value is true, or hides.
-     */
-    public void setSubtitleEnabled(boolean enable) {
-        mProvider.setSubtitleEnabled_impl(enable);
-    }
-
-    /**
-     * Returns true if showing subtitle feature is enabled or returns false.
-     * Although there is no subtitle track or closed caption, it can return true, if the feature
-     * has been enabled by {@link #setSubtitleEnabled}.
-     */
-    public boolean isSubtitleEnabled() {
-        return mProvider.isSubtitleEnabled_impl();
-    }
-
-    /**
-     * Sets playback speed.
-     *
-     * It is expressed as a multiplicative factor, where normal speed is 1.0f. If it is less than
-     * or equal to zero, it will be just ignored and nothing will be changed. If it exceeds the
-     * maximum speed that internal engine supports, system will determine best handling or it will
-     * be reset to the normal speed 1.0f.
-     * @param speed the playback speed. It should be positive.
-     */
-    // TODO: Support this via MediaController2.
-    public void setSpeed(float speed) {
-        mProvider.setSpeed_impl(speed);
-    }
-
-    /**
-     * Sets which type of audio focus will be requested during the playback, or configures playback
-     * to not request audio focus. Valid values for focus requests are
-     * {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
-     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
-     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}. Or use
-     * {@link AudioManager#AUDIOFOCUS_NONE} to express that audio focus should not be
-     * requested when playback starts. You can for instance use this when playing a silent animation
-     * through this class, and you don't want to affect other audio applications playing in the
-     * background.
-     *
-     * @param focusGain the type of audio focus gain that will be requested, or
-     *                  {@link AudioManager#AUDIOFOCUS_NONE} to disable the use audio focus during
-     *                  playback.
-     */
-    public void setAudioFocusRequest(int focusGain) {
-        mProvider.setAudioFocusRequest_impl(focusGain);
-    }
-
-    /**
-     * Sets the {@link AudioAttributes} to be used during the playback of the video.
-     *
-     * @param attributes non-null <code>AudioAttributes</code>.
-     */
-    public void setAudioAttributes(@NonNull AudioAttributes attributes) {
-        mProvider.setAudioAttributes_impl(attributes);
-    }
-
-    /**
-     * Sets video path.
-     *
-     * @param path the path of the video.
-     *
-     * @hide TODO remove
-     */
-    @UnsupportedAppUsage
-    public void setVideoPath(String path) {
-        mProvider.setVideoPath_impl(path);
-    }
-
-    /**
-     * Sets video URI.
-     *
-     * @param uri the URI of the video.
-     *
-     * @hide TODO remove
-     */
-    public void setVideoUri(Uri uri) {
-        mProvider.setVideoUri_impl(uri);
-    }
-
-    /**
-     * Sets video URI using specific headers.
-     *
-     * @param uri     the URI of the video.
-     * @param headers the headers for the URI request.
-     *                Note that the cross domain redirection is allowed by default, but that can be
-     *                changed with key/value pairs through the headers parameter with
-     *                "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value
-     *                to disallow or allow cross domain redirection.
-     *
-     * @hide TODO remove
-     */
-    public void setVideoUri(Uri uri, Map<String, String> headers) {
-        mProvider.setVideoUri_impl(uri, headers);
-    }
-
-    /**
-     * Sets {@link MediaItem2} object to render using VideoView2. Alternative way to set media
-     * object to VideoView2 is {@link #setDataSource}.
-     * @param mediaItem the MediaItem2 to play
-     * @see #setDataSource
-     */
-    public void setMediaItem(@NonNull MediaItem2 mediaItem) {
-        mProvider.setMediaItem_impl(mediaItem);
-    }
-
-    /**
-     * Sets {@link DataSourceDesc} object to render using VideoView2.
-     * @param dataSource the {@link DataSourceDesc} object to play.
-     * @see #setMediaItem
-     */
-    public void setDataSource(@NonNull DataSourceDesc dataSource) {
-        mProvider.setDataSource_impl(dataSource);
-    }
-
-    /**
-     * Selects which view will be used to render video between SurfacView and TextureView.
-     *
-     * @param viewType the view type to render video
-     * <ul>
-     * <li>{@link #VIEW_TYPE_SURFACEVIEW}
-     * <li>{@link #VIEW_TYPE_TEXTUREVIEW}
-     * </ul>
-     */
-    public void setViewType(@ViewType int viewType) {
-        mProvider.setViewType_impl(viewType);
-    }
-
-    /**
-     * Returns view type.
-     *
-     * @return view type. See {@see setViewType}.
-     */
-    @ViewType
-    public int getViewType() {
-        return mProvider.getViewType_impl();
-    }
-
-    /**
-     * Sets custom actions which will be shown as custom buttons in {@link MediaControlView2}.
-     *
-     * @param actionList A list of {@link PlaybackState.CustomAction}. The return value of
-     *                   {@link PlaybackState.CustomAction#getIcon()} will be used to draw buttons
-     *                   in {@link MediaControlView2}.
-     * @param executor executor to run callbacks on.
-     * @param listener A listener to be called when a custom button is clicked.
-     * @hide  TODO remove
-     */
-    public void setCustomActions(List<PlaybackState.CustomAction> actionList,
-            Executor executor, OnCustomActionListener listener) {
-        mProvider.setCustomActions_impl(actionList, executor, listener);
-    }
-
-    /**
-     * Registers a callback to be invoked when a view type change is done.
-     * {@see #setViewType(int)}
-     * @param l The callback that will be run
-     * @hide
-     */
-    @VisibleForTesting
-    @UnsupportedAppUsage
-    public void setOnViewTypeChangedListener(OnViewTypeChangedListener l) {
-        mProvider.setOnViewTypeChangedListener_impl(l);
-    }
-
-    /**
-     * Registers a callback to be invoked when the fullscreen mode should be changed.
-     * @param l The callback that will be run
-     * @hide  TODO remove
-     */
-    public void setFullScreenRequestListener(OnFullScreenRequestListener l) {
-        mProvider.setFullScreenRequestListener_impl(l);
-    }
-
-    /**
-     * Interface definition of a callback to be invoked when the view type has been changed.
-     *
-     * @hide
-     */
-    @VisibleForTesting
-    public interface OnViewTypeChangedListener {
-        /**
-         * Called when the view type has been changed.
-         * @see #setViewType(int)
-         * @param view the View whose view type is changed
-         * @param viewType
-         * <ul>
-         * <li>{@link #VIEW_TYPE_SURFACEVIEW}
-         * <li>{@link #VIEW_TYPE_TEXTUREVIEW}
-         * </ul>
-         */
-        @UnsupportedAppUsage
-        void onViewTypeChanged(View view, @ViewType int viewType);
-    }
-
-    /**
-     * Interface definition of a callback to be invoked to inform the fullscreen mode is changed.
-     * Application should handle the fullscreen mode accordingly.
-     * @hide  TODO remove
-     */
-    public interface OnFullScreenRequestListener {
-        /**
-         * Called to indicate a fullscreen mode change.
-         */
-        void onFullScreenRequest(View view, boolean fullScreen);
-    }
-
-    /**
-     * Interface definition of a callback to be invoked to inform that a custom action is performed.
-     * @hide  TODO remove
-     */
-    public interface OnCustomActionListener {
-        /**
-         * Called to indicate that a custom action is performed.
-         *
-         * @param action The action that was originally sent in the
-         *               {@link PlaybackState.CustomAction}.
-         * @param extras Optional extras.
-         */
-        void onCustomAction(String action, Bundle extras);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        mProvider.onLayout_impl(changed, l, t, r, b);
-    }
-}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index c31f17a..4523d3b 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -16,13 +16,8 @@
 
 package com.android.internal.app;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.annotation.NonNull;
 import android.app.Activity;
 import android.app.ActivityManager;
-import android.app.usage.UsageStatsManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -56,7 +51,6 @@
 import android.service.chooser.IChooserTargetResult;
 import android.service.chooser.IChooserTargetService;
 import android.text.TextUtils;
-import android.util.FloatProperty;
 import android.util.Log;
 import android.util.Slog;
 import android.view.LayoutInflater;
@@ -66,8 +60,6 @@
 import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
 import android.widget.AbsListView;
 import android.widget.BaseAdapter;
 import android.widget.LinearLayout;
@@ -76,10 +68,9 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.app.ResolverActivity;
-import com.android.internal.app.ResolverActivity.TargetInfo;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
 import com.google.android.collect.Lists;
 
 import java.io.File;
@@ -847,7 +838,7 @@
         }
 
         @Override
-        public boolean startAsCaller(Activity activity, Bundle options, int userId) {
+        public boolean startAsCaller(ResolverActivity activity, Bundle options, int userId) {
             final Intent intent = getBaseIntentToSend();
             if (intent == null) {
                 return false;
@@ -866,8 +857,7 @@
             final boolean ignoreTargetSecurity = mSourceInfo != null
                     && mSourceInfo.getResolvedComponentName().getPackageName()
                     .equals(mChooserTarget.getComponentName().getPackageName());
-            activity.startActivityAsCaller(intent, options, ignoreTargetSecurity, userId);
-            return true;
+            return activity.startAsCallerImpl(intent, options, ignoreTargetSecurity, userId);
         }
 
         @Override
diff --git a/core/java/com/android/internal/app/ColorDisplayController.java b/core/java/com/android/internal/app/ColorDisplayController.java
index 7515180..213bb75 100644
--- a/core/java/com/android/internal/app/ColorDisplayController.java
+++ b/core/java/com/android/internal/app/ColorDisplayController.java
@@ -560,13 +560,6 @@
     }
 
     /**
-     * Returns {@code true} if Night display is supported by the device.
-     */
-    public static boolean isAvailable(Context context) {
-        return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
-    }
-
-    /**
      * Callback invoked whenever the Night display settings are changed.
      */
     public interface Callback {
diff --git a/core/java/com/android/internal/app/ISoundTriggerService.aidl b/core/java/com/android/internal/app/ISoundTriggerService.aidl
index c0c689c..764c0cf 100644
--- a/core/java/com/android/internal/app/ISoundTriggerService.aidl
+++ b/core/java/com/android/internal/app/ISoundTriggerService.aidl
@@ -53,5 +53,5 @@
     /** For both ...Intent and ...Service based usage */
     boolean isRecognitionActive(in ParcelUuid parcelUuid);
 
-    SoundTrigger.RecognitionEvent getModelState(in ParcelUuid parcelUuid);
+    int getModelState(in ParcelUuid soundModelId);
 }
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 8cfe1c1..d13bcf2 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -21,7 +21,6 @@
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.ActivityThread;
 import android.app.AppGlobals;
@@ -38,7 +37,9 @@
 import android.os.UserManager;
 import android.util.Slog;
 import android.widget.Toast;
+
 import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
@@ -106,7 +107,7 @@
             final ResolveInfo ri = mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY,
                     targetUserId);
             try {
-                startActivityAsCaller(newIntent, null, false, targetUserId);
+                startActivityAsCaller(newIntent, null, null, false, targetUserId);
             } catch (RuntimeException e) {
                 int launchedFromUid = -1;
                 String launchedFromPackage = "?";
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index fd38917..46c6fa4 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -46,6 +46,7 @@
 import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.PatternMatcher;
 import android.os.RemoteException;
 import android.os.StrictMode;
@@ -92,6 +93,9 @@
 @UiThread
 public class ResolverActivity extends Activity {
 
+    // Temporary flag for new chooser delegate behavior.
+    boolean mEnableChooserDelegate = false;
+
     protected ResolveListAdapter mAdapter;
     private boolean mSafeForwardingMode;
     private AbsListView mAdapterView;
@@ -859,6 +863,37 @@
         }
     }
 
+
+    boolean startAsCallerImpl(Intent intent, Bundle options, boolean ignoreTargetSecurity,
+            int userId) {
+        // Pass intent to delegate chooser activity with permission token.
+        // TODO: This should move to a trampoline Activity in the system when the ChooserActivity
+        // moves into systemui
+        try {
+            // TODO: Once this is a small springboard activity, it can move off the UI process
+            // and we can move the request method to ActivityManagerInternal.
+            IBinder permissionToken = ActivityTaskManager.getService()
+                    .requestStartActivityPermissionToken(getActivityToken());
+            final Intent chooserIntent = new Intent();
+            final ComponentName delegateActivity = ComponentName.unflattenFromString(
+                    Resources.getSystem().getString(R.string.config_chooserActivity));
+            chooserIntent.setClassName(delegateActivity.getPackageName(),
+                    delegateActivity.getClassName());
+            chooserIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken);
+
+            // TODO: These extras will change as chooser activity moves into systemui
+            chooserIntent.putExtra(Intent.EXTRA_INTENT, intent);
+            chooserIntent.putExtra(ActivityTaskManager.EXTRA_OPTIONS, options);
+            chooserIntent.putExtra(ActivityTaskManager.EXTRA_IGNORE_TARGET_SECURITY,
+                    ignoreTargetSecurity);
+            chooserIntent.putExtra(Intent.EXTRA_USER_ID, userId);
+            startActivity(chooserIntent);
+        } catch (RemoteException e) {
+            Log.e(TAG, e.toString());
+        }
+        return true;
+    }
+
     public void onActivityStarted(TargetInfo cti) {
         // Do nothing
     }
@@ -1183,9 +1218,14 @@
         }
 
         @Override
-        public boolean startAsCaller(Activity activity, Bundle options, int userId) {
-            activity.startActivityAsCaller(mResolvedIntent, options, false, userId);
-            return true;
+        public boolean startAsCaller(ResolverActivity activity, Bundle options, int userId) {
+
+            if (mEnableChooserDelegate) {
+                return activity.startAsCallerImpl(mResolvedIntent, options, false, userId);
+            } else {
+                activity.startActivityAsCaller(mResolvedIntent, options, null, false, userId);
+                return true;
+            }
         }
 
         @Override
@@ -1244,7 +1284,7 @@
          * @param userId userId to start as or {@link UserHandle#USER_NULL} for activity's caller
          * @return true if the start completed successfully
          */
-        boolean startAsCaller(Activity activity, Bundle options, int userId);
+        boolean startAsCaller(ResolverActivity activity, Bundle options, int userId);
 
         /**
          * Start the activity referenced by this target as a given user.
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index 81dab2f..8bc90a8 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -389,14 +389,18 @@
      * @param query the search condition used to match file names
      * @param projection projection of the returned cursor
      * @param exclusion absolute file paths to exclude from result
-     * @return cursor containing search result
+     * @param queryArgs the query arguments for search
+     * @return cursor containing search result. Include
+     *         {@link ContentResolver#EXTRA_HONORED_ARGS} in {@link Cursor}
+     *         extras {@link Bundle} when any QUERY_ARG_* value was honored
+     *         during the preparation of the results.
      * @throws FileNotFoundException when root folder doesn't exist or search fails
+     *
+     * @see ContentResolver#EXTRA_HONORED_ARGS
      */
     protected final Cursor querySearchDocuments(
-            File folder, String query, String[] projection, Set<String> exclusion)
+            File folder, String[] projection, Set<String> exclusion, Bundle queryArgs)
             throws FileNotFoundException {
-
-        query = query.toLowerCase();
         final MatrixCursor result = new MatrixCursor(resolveProjection(projection));
         final LinkedList<File> pending = new LinkedList<>();
         pending.add(folder);
@@ -407,11 +411,18 @@
                     pending.add(child);
                 }
             }
-            if (file.getName().toLowerCase().contains(query)
-                    && !exclusion.contains(file.getAbsolutePath())) {
+            if (!exclusion.contains(file.getAbsolutePath()) && matchSearchQueryArguments(file,
+                    queryArgs)) {
                 includeFile(result, null, file);
             }
         }
+
+        final String[] handledQueryArgs = DocumentsContract.getHandledQueryArguments(queryArgs);
+        if (handledQueryArgs.length > 0) {
+            final Bundle extras = new Bundle();
+            extras.putStringArray(ContentResolver.EXTRA_HONORED_ARGS, handledQueryArgs);
+            result.setExtras(extras);
+        }
         return result;
     }
 
@@ -457,6 +468,34 @@
         }
     }
 
+    /**
+     * Test if the file matches the query arguments.
+     *
+     * @param file the file to test
+     * @param queryArgs the query arguments
+     */
+    private boolean matchSearchQueryArguments(File file, Bundle queryArgs) {
+        if (file == null) {
+            return false;
+        }
+
+        final String fileMimeType;
+        final String fileName = file.getName();
+
+        if (file.isDirectory()) {
+            fileMimeType = DocumentsContract.Document.MIME_TYPE_DIR;
+        } else {
+            int dotPos = fileName.lastIndexOf('.');
+            if (dotPos < 0) {
+                return false;
+            }
+            final String extension = fileName.substring(dotPos + 1);
+            fileMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
+        }
+        return DocumentsContract.matchSearchQueryArguments(queryArgs, fileName, fileMimeType,
+                file.lastModified(), file.length());
+    }
+
     private void scanFile(File visibleFile) {
         final Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
         intent.setData(Uri.fromFile(visibleFile));
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/core/java/com/android/internal/inputmethod/IMultiClientInputMethod.aidl
similarity index 60%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to core/java/com/android/internal/inputmethod/IMultiClientInputMethod.aidl
index ede8695..2f782ba 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/core/java/com/android/internal/inputmethod/IMultiClientInputMethod.aidl
@@ -14,8 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package com.android.internal.inputmethod;
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+import android.os.IBinder;
+import com.android.internal.inputmethod.IMultiClientInputMethodPrivilegedOperations;
+
+oneway interface IMultiClientInputMethod {
+    void initialize(in IMultiClientInputMethodPrivilegedOperations privOps);
+    void addClient(int clientId, int uid, int pid, int selfReportedDisplayId);
+    void removeClient(int clientId);
+}
diff --git a/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
new file mode 100644
index 0000000..69d9ccc
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 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.inputmethod;
+
+import android.view.InputChannel;
+import com.android.internal.view.IInputMethodSession;
+import com.android.internal.inputmethod.IMultiClientInputMethodSession;
+
+/**
+ * Defines priviledged operations that only the current MSIMS is allowed to call.
+ * Actual operations are implemented and handled by MultiClientInputMethodManagerService.
+ */
+interface IMultiClientInputMethodPrivilegedOperations {
+    IBinder createInputMethodWindowToken(int displayId);
+    void deleteInputMethodWindowToken(IBinder token);
+    void acceptClient(int clientId, in IInputMethodSession session,
+            in IMultiClientInputMethodSession multiClientSession, in InputChannel writeChannel);
+    void reportImeWindowTarget(int clientId, int targetWindowHandle, in IBinder imeWindowToken);
+    boolean isUidAllowedOnDisplay(int displayId, int uid);
+}
diff --git a/core/java/com/android/internal/inputmethod/IMultiClientInputMethodSession.aidl b/core/java/com/android/internal/inputmethod/IMultiClientInputMethodSession.aidl
new file mode 100644
index 0000000..b40e82c
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/IMultiClientInputMethodSession.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 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.inputmethod;
+
+import android.os.ResultReceiver;
+import android.view.inputmethod.EditorInfo;
+import com.android.internal.view.IInputContext;
+
+oneway interface IMultiClientInputMethodSession {
+    void startInputOrWindowGainedFocus(
+            in IInputContext inputContext, int missingMethods, in EditorInfo attribute,
+            int controlFlags, int softInputMode, int targetWindowHandle);
+    void showSoftInput(int flags, in ResultReceiver resultReceiver);
+    void hideSoftInput(int flags, in ResultReceiver resultReceiver);
+}
diff --git a/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
new file mode 100644
index 0000000..9220117
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2018 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.inputmethod;
+
+import android.annotation.AnyThread;
+import android.annotation.Nullable;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.InputChannel;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.view.IInputMethodSession;
+
+/**
+ * A utility class to take care of boilerplate code around IPCs.
+ *
+ * <p>Note: All public methods are designed to be thread-safe.</p>
+ */
+public class MultiClientInputMethodPrivilegedOperations {
+    private static final String TAG = "MultiClientInputMethodPrivilegedOperations";
+
+    private static final class OpsHolder {
+        @Nullable
+        @GuardedBy("this")
+        private IMultiClientInputMethodPrivilegedOperations mPrivOps;
+
+        /**
+         * Sets {@link IMultiClientInputMethodPrivilegedOperations}.
+         *
+         * <p>This method can be called only once.</p>
+         *
+         * @param privOps Binder interface to be set.
+         */
+        @AnyThread
+        public synchronized void set(IMultiClientInputMethodPrivilegedOperations privOps) {
+            if (mPrivOps != null) {
+                throw new IllegalStateException(
+                        "IMultiClientInputMethodPrivilegedOperations must be set at most once."
+                                + " privOps=" + privOps);
+            }
+            mPrivOps = privOps;
+        }
+
+        /**
+         * A simplified version of {@link android.os.Debug#getCaller()}.
+         *
+         * @return method name of the caller.
+         */
+        @AnyThread
+        private static String getCallerMethodName() {
+            final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
+            if (callStack.length <= 4) {
+                return "<bottom of call stack>";
+            }
+            return callStack[4].getMethodName();
+        }
+
+        @AnyThread
+        public synchronized void dispose() {
+            mPrivOps = null;
+        }
+
+        @AnyThread
+        @Nullable
+        public synchronized IMultiClientInputMethodPrivilegedOperations getAndWarnIfNull() {
+            if (mPrivOps == null) {
+                Log.e(TAG, getCallerMethodName() + " is ignored."
+                        + " Call it within attachToken() and InputMethodService.onDestroy()");
+            }
+            return mPrivOps;
+        }
+    }
+    private final OpsHolder mOps = new OpsHolder();
+
+    /**
+     * Sets {@link IMultiClientInputMethodPrivilegedOperations}.
+     *
+     * <p>This method can be called only once.</p>
+     *
+     * @param privOps Binder interface to be set.
+     */
+    @AnyThread
+    public void set(IMultiClientInputMethodPrivilegedOperations privOps) {
+        mOps.set(privOps);
+    }
+
+    /**
+     * Disposes internal Binder proxy so that the real Binder object can be garbage collected.
+     */
+    @AnyThread
+    public void dispose() {
+        mOps.dispose();
+    }
+
+    /**
+
+     * Calls {@link IMultiClientInputMethodPrivilegedOperations#createInputMethodWindowToken(int)}.
+     *
+     * @param displayId display ID on which the IME window will be shown.
+     * @return Window token to be specified to the IME window.
+     */
+    @AnyThread
+    public IBinder createInputMethodWindowToken(int displayId) {
+        IMultiClientInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return null;
+        }
+        try {
+            return ops.createInputMethodWindowToken(displayId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link
+     * IMultiClientInputMethodPrivilegedOperations#deleteInputMethodWindowToken(IBinder)}.
+     *
+     * @param token Window token that is to be deleted.
+     */
+    @AnyThread
+    public void deleteInputMethodWindowToken(IBinder token) {
+        IMultiClientInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.deleteInputMethodWindowToken(token);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IMultiClientInputMethodPrivilegedOperations#acceptClient(int,
+     * IInputMethodSession, IMultiClientInputMethodSession, InputChannel)}.
+     *
+     * @param clientId client ID to be accepted.
+     * @param session {@link IInputMethodSession} that is also used for traditional IME protocol.
+     * @param multiClientSession {@link IMultiClientInputMethodSession} that defines new callbacks
+     *                           for multi-client scenarios.
+     * @param writeChannel {@link InputChannel} that is also used for traditional IME protocol.
+     */
+    @AnyThread
+    public void acceptClient(int clientId, IInputMethodSession session,
+            IMultiClientInputMethodSession multiClientSession, InputChannel writeChannel) {
+        final IMultiClientInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.acceptClient(clientId, session, multiClientSession, writeChannel);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IMultiClientInputMethodPrivilegedOperations#reportImeWindowTarget(int, int,
+     * IBinder)}.
+     *
+     * @param clientId client ID about which new IME target window is reported.
+     * @param targetWindowHandle integer handle of the target window.
+     * @param imeWindowToken {@link IBinder} window token of the IME window.
+     */
+    @AnyThread
+    public void reportImeWindowTarget(int clientId, int targetWindowHandle,
+            IBinder imeWindowToken) {
+        final IMultiClientInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.reportImeWindowTarget(clientId, targetWindowHandle, imeWindowToken);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Calls {@link IMultiClientInputMethodPrivilegedOperations#isUidAllowedOnDisplay(int, int)}.
+     *
+     * @param displayId display ID to be verified.
+     * @param uid UID to be verified.
+     * @return {@code true} when {@code uid} is allowed to access to {@code displayId}.
+     */
+    @AnyThread
+    public boolean isUidAllowedOnDisplay(int displayId, int uid) {
+        final IMultiClientInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return false;
+        }
+        try {
+            return ops.isUidAllowedOnDisplay(displayId, uid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+}
diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java
index 0baf73c..02c9542 100644
--- a/core/java/com/android/internal/os/BatterySipper.java
+++ b/core/java/com/android/internal/os/BatterySipper.java
@@ -130,6 +130,10 @@
     public double wakeLockPowerMah;
     public double wifiPowerMah;
 
+    //                           ****************
+    // This list must be kept current with atoms.proto (frameworks/base/cmds/statsd/src/atoms.proto)
+    // so the ordinal values (and therefore the order) must never change.
+    //                           ****************
     public enum DrainType {
         AMBIENT_DISPLAY,
         @UnsupportedAppUsage
diff --git a/core/java/com/android/internal/os/KernelCpuProcStringReader.java b/core/java/com/android/internal/os/KernelCpuProcStringReader.java
new file mode 100644
index 0000000..22435ae
--- /dev/null
+++ b/core/java/com/android/internal/os/KernelCpuProcStringReader.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2018 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.os;
+
+import android.os.StrictMode;
+import android.os.SystemClock;
+import android.util.Slog;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.CharBuffer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * Reads human-readable cpu time proc files.
+ *
+ * It is implemented as singletons for built-in kernel proc files. Get___Instance() method will
+ * return corresponding reader instance. In order to prevent frequent GC, it reuses the same char[]
+ * to store data read from proc files.
+ *
+ * A KernelCpuProcStringReader instance keeps an error counter. When the number of read errors
+ * within that instance accumulates to 5, this instance will reject all further read requests.
+ *
+ * Data fetched within last 500ms is considered fresh, since the reading lifecycle can take up to
+ * 100ms. KernelCpuProcStringReader always tries to use cache if it is fresh and valid, but it can
+ * be disabled through a parameter.
+ *
+ * A KernelCpuProcReader instance is thread-safe. It acquires a write lock when reading the proc
+ * file, releases it right after, then acquires a read lock before returning a ProcFileIterator.
+ * Caller is responsible for closing ProcFileIterator (also auto-closable) after reading, otherwise
+ * deadlock will occur.
+ */
+public class KernelCpuProcStringReader {
+    private static final String TAG = KernelCpuProcStringReader.class.getSimpleName();
+    private static final int ERROR_THRESHOLD = 5;
+    // Data read within the last 500ms is considered fresh.
+    private static final long FRESHNESS = 500L;
+    private static final int MAX_BUFFER_SIZE = 1024 * 1024;
+
+    private static final String PROC_UID_FREQ_TIME = "/proc/uid_time_in_state";
+    private static final String PROC_UID_ACTIVE_TIME = "/proc/uid_concurrent_active_time";
+    private static final String PROC_UID_CLUSTER_TIME = "/proc/uid_concurrent_policy_time";
+
+    private static final KernelCpuProcStringReader FREQ_TIME_READER =
+            new KernelCpuProcStringReader(PROC_UID_FREQ_TIME);
+    private static final KernelCpuProcStringReader ACTIVE_TIME_READER =
+            new KernelCpuProcStringReader(PROC_UID_ACTIVE_TIME);
+    private static final KernelCpuProcStringReader CLUSTER_TIME_READER =
+            new KernelCpuProcStringReader(PROC_UID_CLUSTER_TIME);
+
+    public static KernelCpuProcStringReader getFreqTimeReaderInstance() {
+        return FREQ_TIME_READER;
+    }
+
+    public static KernelCpuProcStringReader getActiveTimeReaderInstance() {
+        return ACTIVE_TIME_READER;
+    }
+
+    public static KernelCpuProcStringReader getClusterTimeReaderInstance() {
+        return CLUSTER_TIME_READER;
+    }
+
+    private int mErrors = 0;
+    private final Path mFile;
+    private char[] mBuf;
+    private int mSize;
+    private long mLastReadTime = 0;
+    private final ReentrantReadWriteLock mLock = new ReentrantReadWriteLock();
+    private final ReentrantReadWriteLock.ReadLock mReadLock = mLock.readLock();
+    private final ReentrantReadWriteLock.WriteLock mWriteLock = mLock.writeLock();
+
+    public KernelCpuProcStringReader(String file) {
+        mFile = Paths.get(file);
+    }
+
+    /**
+     * @see #open(boolean) Default behavior is trying to use cache.
+     */
+    public ProcFileIterator open() {
+        return open(false);
+    }
+
+    /**
+     * Opens the proc file and buffers all its content, which can be traversed through a
+     * ProcFileIterator.
+     *
+     * This method will tolerate at most 5 errors. After that, it will always return null. This is
+     * to save resources and to prevent log spam.
+     *
+     * This method is thread-safe. It first checks if there are other threads holding read/write
+     * lock. If there are, it assumes data is fresh and reuses the data.
+     *
+     * A read lock is automatically acquired when a valid ProcFileIterator is returned. Caller MUST
+     * call {@link ProcFileIterator#close()} when it is done to release the lock.
+     *
+     * @param ignoreCache If true, ignores the cache and refreshes the data anyway.
+     * @return A {@link ProcFileIterator} to iterate through the file content, or null if there is
+     * error.
+     */
+    public ProcFileIterator open(boolean ignoreCache) {
+        if (mErrors >= ERROR_THRESHOLD) {
+            return null;
+        }
+
+        if (ignoreCache) {
+            mWriteLock.lock();
+        } else {
+            mReadLock.lock();
+            if (dataValid()) {
+                return new ProcFileIterator(mSize);
+            }
+            mReadLock.unlock();
+            mWriteLock.lock();
+            if (dataValid()) {
+                // Recheck because another thread might have written data just before we did.
+                mReadLock.lock();
+                mWriteLock.unlock();
+                return new ProcFileIterator(mSize);
+            }
+        }
+
+        // At this point, write lock is held and data is invalid.
+        int total = 0;
+        int curr;
+        mSize = 0;
+        final int oldMask = StrictMode.allowThreadDiskReadsMask();
+        try (BufferedReader r = Files.newBufferedReader(mFile)) {
+            if (mBuf == null) {
+                mBuf = new char[1024];
+            }
+            while ((curr = r.read(mBuf, total, mBuf.length - total)) >= 0) {
+                total += curr;
+                if (total == mBuf.length) {
+                    // Hit the limit. Resize buffer.
+                    if (mBuf.length == MAX_BUFFER_SIZE) {
+                        mErrors++;
+                        Slog.e(TAG, "Proc file too large: " + mFile);
+                        return null;
+                    }
+                    mBuf = Arrays.copyOf(mBuf, Math.min(mBuf.length << 1, MAX_BUFFER_SIZE));
+                }
+            }
+            mSize = total;
+            mLastReadTime = SystemClock.elapsedRealtime();
+            // ReentrantReadWriteLock allows lock downgrading.
+            mReadLock.lock();
+            return new ProcFileIterator(total);
+        } catch (FileNotFoundException e) {
+            mErrors++;
+            Slog.w(TAG, "File not found. It's normal if not implemented: " + mFile);
+        } catch (IOException e) {
+            mErrors++;
+            Slog.e(TAG, "Error reading: " + mFile, e);
+        } finally {
+            StrictMode.setThreadPolicyMask(oldMask);
+            mWriteLock.unlock();
+        }
+        return null;
+    }
+
+    private boolean dataValid() {
+        return mSize > 0 && (SystemClock.elapsedRealtime() - mLastReadTime < FRESHNESS);
+    }
+
+    /**
+     * An autoCloseable iterator to iterate through a string proc file line by line. User must call
+     * close() when finish using to prevent deadlock.
+     */
+    public class ProcFileIterator implements AutoCloseable {
+        private final int mSize;
+        private int mPos;
+
+        public ProcFileIterator(int size) {
+            mSize = size;
+        }
+
+        /**
+         * Fetches the next line. Note that all subsequent return values share the same char[]
+         * under the hood.
+         *
+         * @return A {@link java.nio.CharBuffer} containing the next line without the new line
+         * symbol.
+         */
+        public CharBuffer nextLine() {
+            if (mPos >= mSize) {
+                return null;
+            }
+            int i = mPos;
+            // Move i to the next new line symbol, which is always '\n' in Android.
+            while (i < mSize && mBuf[i] != '\n') {
+                i++;
+            }
+            int start = mPos;
+            mPos = i + 1;
+            return CharBuffer.wrap(mBuf, start, i - start);
+        }
+
+        /**
+         * Fetches the next line, converts all numbers into long, and puts into the given long[].
+         * To avoid GC, caller should try to use the same array for all calls. All non-numeric
+         * chars are treated as delimiters. All numbers are non-negative.
+         *
+         * @param array An array to store the parsed numbers.
+         * @return The number of elements written to the given array. -1 if there is no more line.
+         */
+        public int nextLineAsArray(long[] array) {
+            CharBuffer buf = nextLine();
+            if (buf == null) {
+                return -1;
+            }
+            int count = 0;
+            long num = -1;
+            char c;
+
+            while (buf.remaining() > 0 && count < array.length) {
+                c = buf.get();
+                if (num < 0) {
+                    if (isNumber(c)) {
+                        num = c - '0';
+                    }
+                } else {
+                    if (isNumber(c)) {
+                        num = num * 10 + c - '0';
+                    } else {
+                        array[count++] = num;
+                        num = -1;
+                    }
+                }
+            }
+            if (num >= 0) {
+                array[count++] = num;
+            }
+            return count;
+        }
+
+        /** Total size of the proc file in chars. */
+        public int size() {
+            return mSize;
+        }
+
+        /** Must call close at the end to release the read lock! Or use try-with-resources. */
+        public void close() {
+            mReadLock.unlock();
+        }
+
+        private boolean isNumber(char c) {
+            return c >= '0' && c <= '9';
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/KernelCpuThreadReader.java b/core/java/com/android/internal/os/KernelCpuThreadReader.java
index 6b277a0..7c82a7e 100644
--- a/core/java/com/android/internal/os/KernelCpuThreadReader.java
+++ b/core/java/com/android/internal/os/KernelCpuThreadReader.java
@@ -173,7 +173,7 @@
                 }
             }
         } catch (IOException e) {
-            Slog.w(TAG, "Failed to iterate over thread paths", e);
+            // Expected when a process finishes
             return null;
         }
 
diff --git a/core/java/com/android/internal/os/ProcStatsUtil.java b/core/java/com/android/internal/os/ProcStatsUtil.java
index 3d4df89..0002447f 100644
--- a/core/java/com/android/internal/os/ProcStatsUtil.java
+++ b/core/java/com/android/internal/os/ProcStatsUtil.java
@@ -32,6 +32,8 @@
 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
 public final class ProcStatsUtil {
 
+    private static final boolean DEBUG = false;
+
     private static final String TAG = "ProcStatsUtil";
 
     /**
@@ -141,7 +143,9 @@
             }
             return byteStream.toString();
         } catch (IOException e) {
-            Slog.w(TAG, "Failed to open proc file", e);
+            if (DEBUG) {
+                Slog.d(TAG, "Failed to open proc file", e);
+            }
             return null;
         } finally {
             StrictMode.setThreadPolicy(savedPolicy);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 8f87f91..8bdb000 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -173,12 +173,13 @@
     }
 
     native private static void nativePreloadAppProcessHALs();
+    native private static void nativePreloadOpenGL();
 
     private static void preloadOpenGL() {
         String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
         if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false) &&
                 (driverPackageName == null || driverPackageName.isEmpty())) {
-            EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+            nativePreloadOpenGL();
         }
     }
 
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index aa7bdb6..e2c23de 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1001,7 +1001,7 @@
                         insets.getSystemWindowInsetRight(), 0);
             }
         }
-        mFrameOffsets.set(insets.getSystemWindowInsets());
+        mFrameOffsets.set(insets.getSystemWindowInsetsAsRect());
         insets = updateColorViews(insets, true /* animate */);
         insets = updateStatusGuard(insets);
         if (getForeground() != null) {
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 9b8f120..604537f 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -142,7 +142,7 @@
 
     // Used to show the dialog when BiometricService starts authentication
     void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation);
+            boolean requireConfirmation, int userId);
     // Used to hide the dialog when a biometric is authenticated
     void onBiometricAuthenticated();
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 90f2002..9a7094a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -92,7 +92,7 @@
 
     // Used to show the dialog when BiometricService starts authentication
     void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation);
+            boolean requireConfirmation, int userId);
     // Used to hide the dialog when a biometric is authenticated
     void onBiometricAuthenticated();
     // Used to set a temporary message, e.g. fingerprint not recognized, finger moved too fast, etc
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/core/java/com/android/internal/util/function/HeptConsumer.java
similarity index 71%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to core/java/com/android/internal/util/function/HeptConsumer.java
index ede8695..171b0f2 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/core/java/com/android/internal/util/function/HeptConsumer.java
@@ -14,8 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package com.android.internal.util.function;
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+import java.util.function.Consumer;
+
+/**
+ * A 7-argument {@link Consumer}
+ *
+ * @hide
+ */
+public interface HeptConsumer<A, B, C, D, E, F, G> {
+    void accept(A a, B b, C c, D d, E e, F f, G g);
+}
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/core/java/com/android/internal/util/function/HeptFunction.java
similarity index 71%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to core/java/com/android/internal/util/function/HeptFunction.java
index ede8695..7aa4345 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/core/java/com/android/internal/util/function/HeptFunction.java
@@ -14,8 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package com.android.internal.util.function;
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+import java.util.function.Function;
+
+/**
+ * A 7-argument {@link Function}
+ *
+ * @hide
+ */
+public interface HeptFunction<A, B, C, D, E, F, G, R> {
+    R apply(A a, B b, C c, D d, E e, F f, G g);
+}
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/core/java/com/android/internal/util/function/HeptPredicate.java
similarity index 71%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to core/java/com/android/internal/util/function/HeptPredicate.java
index ede8695..531e53a 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/core/java/com/android/internal/util/function/HeptPredicate.java
@@ -14,8 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package com.android.internal.util.function;
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+import java.util.function.Predicate;
+
+/**
+ * A 7-argument {@link Predicate}
+ *
+ * @hide
+ */
+public interface HeptPredicate<A, B, C, D, E, F, G> {
+    boolean test(A a, B b, C c, D d, E e, F f, G g);
+}
diff --git a/core/java/com/android/internal/util/function/pooled/OmniFunction.java b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
index 9378869..4ffe441 100755
--- a/core/java/com/android/internal/util/function/pooled/OmniFunction.java
+++ b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
@@ -18,6 +18,8 @@
 
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
+import com.android.internal.util.function.HeptConsumer;
+import com.android.internal.util.function.HeptFunction;
 import com.android.internal.util.function.HexConsumer;
 import com.android.internal.util.function.HexFunction;
 import com.android.internal.util.function.QuadConsumer;
@@ -37,59 +39,61 @@
  *
  * @hide
  */
-abstract class OmniFunction<A, B, C, D, E, F, R> implements
+abstract class OmniFunction<A, B, C, D, E, F, G, R> implements
         PooledFunction<A, R>, BiFunction<A, B, R>, TriFunction<A, B, C, R>,
         QuadFunction<A, B, C, D, R>, QuintFunction<A, B, C, D, E, R>,
-        HexFunction<A, B, C, D, E, F, R>, PooledConsumer<A>, BiConsumer<A, B>,
-        TriConsumer<A, B, C>, QuadConsumer<A, B, C, D>, QuintConsumer<A, B, C, D, E>,
-        HexConsumer<A, B, C, D, E, F>, PooledPredicate<A>, BiPredicate<A, B>,
+        HexFunction<A, B, C, D, E, F, R>, HeptFunction<A, B, C, D, E, F, G, R>,
+        PooledConsumer<A>, BiConsumer<A, B>, TriConsumer<A, B, C>, QuadConsumer<A, B, C, D>,
+        QuintConsumer<A, B, C, D, E>, HexConsumer<A, B, C, D, E, F>,
+        HeptConsumer<A, B, C, D, E, F, G>,
+        PooledPredicate<A>, BiPredicate<A, B>,
         PooledSupplier<R>, PooledRunnable, ThrowingRunnable, ThrowingSupplier<R>,
         PooledSupplier.OfInt, PooledSupplier.OfLong, PooledSupplier.OfDouble {
 
-    abstract R invoke(A a, B b, C c, D d, E e, F f);
+    abstract R invoke(A a, B b, C c, D d, E e, F f, G g);
 
     @Override
     public R apply(A o, B o2) {
-        return invoke(o, o2, null, null, null, null);
+        return invoke(o, o2, null, null, null, null, null);
     }
 
     @Override
     public R apply(A o) {
-        return invoke(o, null, null, null, null, null);
+        return invoke(o, null, null, null, null, null, null);
     }
 
-    abstract public <V> OmniFunction<A, B, C, D, E, F, V> andThen(
+    public abstract <V> OmniFunction<A, B, C, D, E, F, G, V> andThen(
             Function<? super R, ? extends V> after);
-    abstract public OmniFunction<A, B, C, D, E, F, R> negate();
+    public abstract OmniFunction<A, B, C, D, E, F, G, R> negate();
 
     @Override
     public void accept(A o, B o2) {
-        invoke(o, o2, null, null, null, null);
+        invoke(o, o2, null, null, null, null, null);
     }
 
     @Override
     public void accept(A o) {
-        invoke(o, null, null, null, null, null);
+        invoke(o, null, null, null, null, null, null);
     }
 
     @Override
     public void run() {
-        invoke(null, null, null, null, null, null);
+        invoke(null, null, null, null, null, null, null);
     }
 
     @Override
     public R get() {
-        return invoke(null, null, null, null, null, null);
+        return invoke(null, null, null, null, null, null, null);
     }
 
     @Override
     public boolean test(A o, B o2) {
-        return (Boolean) invoke(o, o2, null, null, null, null);
+        return (Boolean) invoke(o, o2, null, null, null, null, null);
     }
 
     @Override
     public boolean test(A o) {
-        return (Boolean) invoke(o, null, null, null, null, null);
+        return (Boolean) invoke(o, null, null, null, null, null, null);
     }
 
     @Override
@@ -104,42 +108,52 @@
 
     @Override
     public R apply(A a, B b, C c) {
-        return invoke(a, b, c, null, null, null);
+        return invoke(a, b, c, null, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c) {
-        invoke(a, b, c, null, null, null);
+        invoke(a, b, c, null, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d) {
-        return invoke(a, b, c, d, null, null);
+        return invoke(a, b, c, d, null, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e) {
-        return invoke(a, b, c, d, e, null);
+        return invoke(a, b, c, d, e, null, null);
     }
 
     @Override
     public R apply(A a, B b, C c, D d, E e, F f) {
-        return invoke(a, b, c, d, e, f);
+        return invoke(a, b, c, d, e, f, null);
+    }
+
+    @Override
+    public R apply(A a, B b, C c, D d, E e, F f, G g) {
+        return invoke(a, b, c, d, e, f, g);
     }
 
     @Override
     public void accept(A a, B b, C c, D d) {
-        invoke(a, b, c, d, null, null);
+        invoke(a, b, c, d, null, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e) {
-        invoke(a, b, c, d, e, null);
+        invoke(a, b, c, d, e, null, null);
     }
 
     @Override
     public void accept(A a, B b, C c, D d, E e, F f) {
-        invoke(a, b, c, d, e, f);
+        invoke(a, b, c, d, e, f, null);
+    }
+
+    @Override
+    public void accept(A a, B b, C c, D d, E e, F f, G g) {
+        invoke(a, b, c, d, e, f, g);
     }
 
     @Override
@@ -153,5 +167,5 @@
     }
 
     @Override
-    abstract public OmniFunction<A, B, C, D, E, F, R> recycleOnUse();
+    public abstract OmniFunction<A, B, C, D, E, F, G, R> recycleOnUse();
 }
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambda.java b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
index 15698cc..af3c752 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambda.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
@@ -21,6 +21,8 @@
 
 import android.os.Message;
 
+import com.android.internal.util.function.HeptConsumer;
+import com.android.internal.util.function.HeptFunction;
 import com.android.internal.util.function.HexConsumer;
 import com.android.internal.util.function.HexFunction;
 import com.android.internal.util.function.QuadConsumer;
@@ -174,7 +176,7 @@
             Consumer<? super A> function,
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null);
+                function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null);
     }
 
     /**
@@ -190,7 +192,7 @@
             Predicate<? super A> function,
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null);
+                function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null, null);
     }
 
     /**
@@ -206,7 +208,7 @@
             Function<? super A, ? extends R> function,
             A arg1) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null);
+                function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null, null);
     }
 
     /**
@@ -236,7 +238,7 @@
             A arg1) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null);
+                    function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -255,7 +257,7 @@
             BiConsumer<? super A, ? super B> function,
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null);
+                function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
     }
 
     /**
@@ -272,7 +274,7 @@
             BiPredicate<? super A, ? super B> function,
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null);
+                function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null);
     }
 
     /**
@@ -289,7 +291,7 @@
             BiFunction<? super A, ? super B, ? extends R> function,
             A arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null);
+                function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null);
     }
 
     /**
@@ -306,7 +308,7 @@
             BiConsumer<? super A, ? super B> function,
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null);
+                function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
     }
 
     /**
@@ -323,7 +325,7 @@
             BiPredicate<? super A, ? super B> function,
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null);
+                function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null);
     }
 
     /**
@@ -340,7 +342,7 @@
             BiFunction<? super A, ? super B, ? extends R> function,
             ArgumentPlaceholder<A> arg1, B arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null);
+                function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null);
     }
 
     /**
@@ -357,7 +359,7 @@
             BiConsumer<? super A, ? super B> function,
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null);
+                function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
     }
 
     /**
@@ -374,7 +376,7 @@
             BiPredicate<? super A, ? super B> function,
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null);
+                function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null);
     }
 
     /**
@@ -391,7 +393,7 @@
             BiFunction<? super A, ? super B, ? extends R> function,
             A arg1, ArgumentPlaceholder<B> arg2) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null);
+                function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null);
     }
 
     /**
@@ -422,7 +424,7 @@
             A arg1, B arg2) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null);
+                    function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -442,7 +444,7 @@
             TriConsumer<? super A, ? super B, ? super C> function,
             A arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
+                function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
     }
 
     /**
@@ -460,7 +462,7 @@
             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
             A arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null);
+                function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
     }
 
     /**
@@ -478,7 +480,7 @@
             TriConsumer<? super A, ? super B, ? super C> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
+                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
     }
 
     /**
@@ -496,7 +498,7 @@
             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null);
+                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
     }
 
     /**
@@ -514,7 +516,7 @@
             TriConsumer<? super A, ? super B, ? super C> function,
             A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
+                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
     }
 
     /**
@@ -532,7 +534,7 @@
             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
             A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null);
+                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
     }
 
     /**
@@ -550,7 +552,7 @@
             TriConsumer<? super A, ? super B, ? super C> function,
             A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
+                function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
     }
 
     /**
@@ -568,7 +570,7 @@
             TriFunction<? super A, ? super B, ? super C, ? extends R> function,
             A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null);
+                function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
     }
 
     /**
@@ -600,7 +602,7 @@
             A arg1, B arg2, C arg3) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null);
+                    function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -621,7 +623,7 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             A arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
+                function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
     }
 
     /**
@@ -640,7 +642,7 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             A arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
+                function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
     }
 
     /**
@@ -659,7 +661,7 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
+                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
     }
 
     /**
@@ -678,7 +680,7 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
+                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
     }
 
     /**
@@ -697,7 +699,7 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
+                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
     }
 
     /**
@@ -716,7 +718,7 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
+                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
     }
 
     /**
@@ -735,7 +737,7 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
+                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
     }
 
     /**
@@ -754,7 +756,7 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
+                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
     }
 
     /**
@@ -773,7 +775,7 @@
             QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
             A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
+                function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
     }
 
     /**
@@ -792,7 +794,7 @@
             QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
             A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null);
+                function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
     }
 
     /**
@@ -825,7 +827,7 @@
             A arg1, B arg2, C arg3, D arg4) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null);
+                    function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -847,7 +849,7 @@
             QuintConsumer<? super A, ? super B, ? super C, ? super D, ? super E> function,
             A arg1, B arg2, C arg3, D arg4, E arg5) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null);
+                function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null);
     }
 
     /**
@@ -867,7 +869,7 @@
             QuintFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? extends R>
                     function, A arg1, B arg2, C arg3, D arg4, E arg5) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null);
+                function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null, null);
     }
 
     /**
@@ -902,7 +904,7 @@
             A arg1, B arg2, C arg3, D arg4, E arg5) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null);
+                    function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
@@ -925,7 +927,7 @@
             HexConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F> function,
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6);
+                function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null);
     }
 
     /**
@@ -946,7 +948,7 @@
             HexFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
                     ? extends R> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
         return acquire(PooledLambdaImpl.sPool,
-                function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6);
+                function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, null);
     }
 
     /**
@@ -982,7 +984,91 @@
             A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
         synchronized (Message.sPoolSync) {
             PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
-                    function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6);
+                    function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null);
+            return Message.obtain().setCallback(callback.recycleOnUse());
+        }
+    }
+
+    /**
+     * {@link PooledRunnable} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @return a {@link PooledRunnable}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7) }
+     */
+    static <A, B, C, D, E, F, G> PooledRunnable obtainRunnable(
+            HeptConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    }
+
+    /**
+     * {@link PooledSupplier} factory
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @return a {@link PooledSupplier}, equivalent to lambda:
+     *         {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7) }
+     */
+    static <A, B, C, D, E, F, G, R> PooledSupplier<R> obtainSupplier(
+            HeptFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G, ? extends R> function,
+            A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
+        return acquire(PooledLambdaImpl.sPool,
+                function, 7, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+    }
+
+    /**
+     * Factory of {@link Message}s that contain an
+     * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+     * {@link Message#getCallback internal callback}.
+     *
+     * The callback is equivalent to one obtainable via
+     * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+     *
+     * Note that using this method with {@link android.os.Handler#handleMessage}
+     * is more efficient than the alternative of {@link android.os.Handler#post}
+     * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+     * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+     *
+     * You may optionally set a {@link Message#what} for the message if you want to be
+     * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+     * there's no need to do so
+     *
+     * @param function non-capturing lambda(typically an unbounded method reference)
+     *                 to be invoked on call
+     * @param arg1 parameter supplied to {@code function} on call
+     * @param arg2 parameter supplied to {@code function} on call
+     * @param arg3 parameter supplied to {@code function} on call
+     * @param arg4 parameter supplied to {@code function} on call
+     * @param arg5 parameter supplied to {@code function} on call
+     * @param arg6 parameter supplied to {@code function} on call
+     * @param arg7 parameter supplied to {@code function} on call
+     * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6,
+     * arg7) } when handled
+     */
+    static <A, B, C, D, E, F, G> Message obtainMessage(
+            HeptConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+                    ? super G> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
+        synchronized (Message.sPoolSync) {
+            PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+                    function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
             return Message.obtain().setCallback(callback.recycleOnUse());
         }
     }
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
index 565ae11..eea1e5f 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
@@ -24,6 +24,9 @@
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.BitUtils;
+import com.android.internal.util.function.HeptConsumer;
+import com.android.internal.util.function.HeptFunction;
+import com.android.internal.util.function.HeptPredicate;
 import com.android.internal.util.function.HexConsumer;
 import com.android.internal.util.function.HexFunction;
 import com.android.internal.util.function.HexPredicate;
@@ -51,12 +54,12 @@
  * @hide
  */
 final class PooledLambdaImpl<R> extends OmniFunction<Object,
-        Object, Object, Object, Object, Object, R> {
+        Object, Object, Object, Object, Object, Object, R> {
 
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "PooledLambdaImpl";
 
-    private static final int MAX_ARGS = 5;
+    private static final int MAX_ARGS = 7;
 
     private static final int MAX_POOL_SIZE = 50;
 
@@ -122,7 +125,7 @@
 
     /**
      * Bit schema:
-     * AAAABCDEEEEEEFFFFFF
+     * AAAAAAABCDEEEEEEFFFFFF
      *
      * Where:
      * A - whether {@link #mArgs arg} at corresponding index was specified at
@@ -158,17 +161,17 @@
     }
 
     @Override
-    R invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) {
+    R invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) {
         checkNotRecycled();
         if (DEBUG) {
             Log.i(LOG_TAG, this + ".invoke("
                     + commaSeparateFirstN(
-                            new Object[] { a1, a2, a3, a4, a5, a6 },
+                            new Object[] { a1, a2, a3, a4, a5, a6, a7 },
                             LambdaType.decodeArgCount(getFlags(MASK_EXPOSED_AS)))
                     + ")");
         }
         final boolean notUsed = fillInArg(a1) && fillInArg(a2) && fillInArg(a3)
-                && fillInArg(a4) && fillInArg(a5) && fillInArg(a6);
+                && fillInArg(a4) && fillInArg(a5) && fillInArg(a6) && fillInArg(a7);
         int argCount = LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE));
         if (argCount != LambdaType.MASK_ARG_COUNT) {
             for (int i = 0; i < argCount; i++) {
@@ -333,6 +336,27 @@
                     }
                 }
             }
+
+            case 7: {
+                switch (returnType) {
+                    case LambdaType.ReturnType.VOID: {
+                        ((HeptConsumer) mFunc).accept(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4),
+                                popArg(5), popArg(6));
+                        return null;
+                    }
+                    case LambdaType.ReturnType.BOOLEAN: {
+                        return (R) (Object) ((HeptPredicate) mFunc).test(popArg(0),
+                                popArg(1), popArg(2), popArg(3),
+                                popArg(4), popArg(5), popArg(6));
+                    }
+                    case LambdaType.ReturnType.OBJECT: {
+                        return (R) ((HeptFunction) mFunc).apply(popArg(0), popArg(1),
+                                popArg(2), popArg(3), popArg(4),
+                                popArg(5), popArg(6));
+                    }
+                }
+            }
         }
         throw new IllegalStateException("Unknown function type: " + LambdaType.toString(funcType));
     }
@@ -396,7 +420,7 @@
      */
     static <E extends PooledLambda> E acquire(Pool pool, Object func,
             int fNumArgs, int numPlaceholders, int fReturnType,
-            Object a, Object b, Object c, Object d, Object e, Object f) {
+            Object a, Object b, Object c, Object d, Object e, Object f, Object g) {
         PooledLambdaImpl r = acquire(pool);
         if (DEBUG) {
             Log.i(LOG_TAG,
@@ -411,6 +435,7 @@
                             + ", d = " + d
                             + ", e = " + e
                             + ", f = " + f
+                            + ", g = " + g
                             + ")");
         }
         r.mFunc = func;
@@ -423,6 +448,7 @@
         setIfInBounds(r.mArgs, 3, d);
         setIfInBounds(r.mArgs, 4, e);
         setIfInBounds(r.mArgs, 5, f);
+        setIfInBounds(r.mArgs, 6, g);
         return (E) r;
     }
 
@@ -448,12 +474,12 @@
     }
 
     @Override
-    public OmniFunction<Object, Object, Object, Object, Object, Object, R> negate() {
+    public OmniFunction<Object, Object, Object, Object, Object, Object, Object, R> negate() {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public <V> OmniFunction<Object, Object, Object, Object, Object, Object, V> andThen(
+    public <V> OmniFunction<Object, Object, Object, Object, Object, Object, Object, V> andThen(
             Function<? super R, ? extends V> after) {
         throw new UnsupportedOperationException();
     }
@@ -474,7 +500,7 @@
     }
 
     @Override
-    public OmniFunction<Object, Object, Object, Object, Object, Object, R> recycleOnUse() {
+    public OmniFunction<Object, Object, Object, Object, Object, Object, Object, R> recycleOnUse() {
         if (DEBUG) Log.i(LOG_TAG, this + ".recycleOnUse()");
         mFlags |= FLAG_RECYCLE_ON_USE;
         return this;
@@ -519,10 +545,10 @@
      * Contract for encoding a supported lambda type in {@link #MASK_BIT_COUNT} bits
      */
     static class LambdaType {
-        public static final int MASK_ARG_COUNT = 0b111;
-        public static final int MASK_RETURN_TYPE = 0b111000;
+        public static final int MASK_ARG_COUNT = 0b1111;
+        public static final int MASK_RETURN_TYPE = 0b1110000;
         public static final int MASK = MASK_ARG_COUNT | MASK_RETURN_TYPE;
-        public static final int MASK_BIT_COUNT = 6;
+        public static final int MASK_BIT_COUNT = 7;
 
         static int encode(int argCount, int returnType) {
             return mask(MASK_ARG_COUNT, argCount) | mask(MASK_RETURN_TYPE, returnType);
@@ -557,6 +583,7 @@
                 case 4: return "Quad";
                 case 5: return "Quint";
                 case 6: return "Hex";
+                case 7: return "Hept";
                 default: throw new IllegalArgumentException("" + argCount);
             }
         }
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index e3490f1..137ca7f 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.view;
 
-import android.annotation.UnsupportedAppUsage;
 import android.graphics.Rect;
 import android.hardware.input.InputManager;
 import android.os.Bundle;
@@ -66,7 +65,7 @@
     }
 
     @Override
-    public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
+    public void windowFocusChanged(boolean hasFocus, boolean touchEnabled, boolean reportToClient) {
     }
 
     @Override
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
index ec8e8da..901cfe3 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -54,6 +54,7 @@
             ResultCode.ERROR_NO_EDITOR,
             ResultCode.ERROR_DISPLAY_ID_MISMATCH,
             ResultCode.ERROR_INVALID_DISPLAY_ID,
+            ResultCode.ERROR_INVALID_CLIENT,
     })
     public @interface ResultCode {
         /**
@@ -158,6 +159,10 @@
          * display.
          */
         int ERROR_INVALID_DISPLAY_ID = 14;
+        /**
+         * Indicates that the client is not recognized by the system.
+         */
+        int ERROR_INVALID_CLIENT = 15;
     }
 
     @ResultCode
@@ -287,6 +292,8 @@
                 return "ERROR_DISPLAY_ID_MISMATCH";
             case ResultCode.ERROR_INVALID_DISPLAY_ID:
                 return "ERROR_INVALID_DISPLAY_ID";
+            case ResultCode.ERROR_INVALID_CLIENT:
+                return "ERROR_INVALID_CLIENT";
             default:
                 return "Unknown(" + result + ")";
         }
@@ -343,4 +350,9 @@
      */
     public static final InputBindResult INVALID_DISPLAY_ID =
             error(ResultCode.ERROR_INVALID_DISPLAY_ID);
+
+    /**
+     * Predefined error object for {@link ResultCode#ERROR_INVALID_CLIENT}.
+     */
+    public static final InputBindResult INVALID_CLIENT = error(ResultCode.ERROR_INVALID_CLIENT);
 }
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index 4a1c955..ba0ff01 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -313,8 +313,7 @@
         pullChildren();
 
         final int vis = getWindowSystemUiVisibility();
-        final boolean stable = (vis & SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0;
-        final Rect systemInsets = insets.getSystemWindowInsets();
+        final Rect systemInsets = insets.getSystemWindowInsetsAsRect();
 
         // The top and bottom action bars are always within the content area.
         boolean changed = applyInsets(mActionBarTop, systemInsets, true, true, false, true);
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index b799728..25a5a07 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -69,7 +69,7 @@
     private static final int ASPECT_LOCK_HEIGHT = 2; // Fixed height; width will be minimum of (w,h)
 
     private static final boolean PROFILE_DRAWING = false;
-    private static final float LINE_FADE_ALPHA_MULTIPLIER = 3.5f;
+    private static final float LINE_FADE_ALPHA_MULTIPLIER = 1.5f;
     private final CellState[][] mCellStates;
 
     private final int mDotSize;
diff --git a/core/java/com/android/internal/widget/SubtitleView.java b/core/java/com/android/internal/widget/SubtitleView.java
index 1107828..21e63c5 100644
--- a/core/java/com/android/internal/widget/SubtitleView.java
+++ b/core/java/com/android/internal/widget/SubtitleView.java
@@ -58,7 +58,7 @@
     /** Reusable spannable string builder used for holding text. */
     private final SpannableStringBuilder mText = new SpannableStringBuilder();
 
-    private Alignment mAlignment;
+    private Alignment mAlignment = Alignment.ALIGN_CENTER;
     private TextPaint mTextPaint;
     private Paint mPaint;
 
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index c96aaba..bdd5f83 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -240,7 +240,7 @@
     ],
 
     shared_libs: [
-        "libbpf",
+        "libbpf_android",
         "libnetdbpf",
         "libnetdutils",
         "libmemtrack",
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index e07a208..2e7501f 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -83,7 +83,8 @@
         return 0;
     }
     std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>(
-            builder->langId, builder->variant, std::move(builder->fonts));
+            builder->langId, builder->variant, std::move(builder->fonts),
+            true /* isCustomFallback */);
     if (family->getCoverage().length() == 0) {
         return 0;
     }
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index d391de7..a8b0640 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -28,6 +28,7 @@
 
 #include "SkBlurDrawLooper.h"
 #include "SkColorFilter.h"
+#include "SkFontTypes.h"
 #include "SkMaskFilter.h"
 #include "SkPath.h"
 #include "SkPathEffect.h"
@@ -684,13 +685,13 @@
     }
 
     static jint getHinting(jlong paintHandle) {
-        return reinterpret_cast<Paint*>(paintHandle)->getHinting()
-                == Paint::kNo_Hinting ? 0 : 1;
+        return (SkFontHinting)reinterpret_cast<Paint*>(paintHandle)->getHinting()
+                == kNo_SkFontHinting ? 0 : 1;
     }
 
     static void setHinting(jlong paintHandle, jint mode) {
         reinterpret_cast<Paint*>(paintHandle)->setHinting(
-                mode == 0 ? Paint::kNo_Hinting : Paint::kNormal_Hinting);
+                mode == 0 ? kNo_SkFontHinting : kNormal_SkFontHinting);
     }
 
     static void setAntiAlias(jlong paintHandle, jboolean aa) {
diff --git a/core/jni/android/graphics/fonts/FontFamily.cpp b/core/jni/android/graphics/fonts/FontFamily.cpp
index 767e068..249e4f3 100644
--- a/core/jni/android/graphics/fonts/FontFamily.cpp
+++ b/core/jni/android/graphics/fonts/FontFamily.cpp
@@ -57,7 +57,7 @@
 
 // Regular JNI
 static jlong FontFamily_Builder_build(JNIEnv* env, jobject clazz, jlong builderPtr,
-            jstring langTags, jint variant) {
+            jstring langTags, jint variant, jboolean isCustomFallback) {
     std::unique_ptr<NativeFamilyBuilder> builder(toBuilder(builderPtr));
     uint32_t localeId;
     if (langTags == nullptr) {
@@ -67,7 +67,8 @@
         localeId = minikin::registerLocaleList(str.c_str());
     }
     std::shared_ptr<minikin::FontFamily> family = std::make_shared<minikin::FontFamily>(
-            localeId, static_cast<minikin::FamilyVariant>(variant), std::move(builder->fonts));
+            localeId, static_cast<minikin::FamilyVariant>(variant), std::move(builder->fonts),
+            isCustomFallback);
     if (family->getCoverage().length() == 0) {
         // No coverage means minikin rejected given font for some reasons.
         jniThrowException(env, "java/lang/IllegalArgumentException",
@@ -87,7 +88,7 @@
 static const JNINativeMethod gFontFamilyBuilderMethods[] = {
     { "nInitBuilder", "()J", (void*) FontFamily_Builder_initBuilder },
     { "nAddFont", "(JJ)V", (void*) FontFamily_Builder_addFont },
-    { "nBuild", "(JLjava/lang/String;I)J", (void*) FontFamily_Builder_build },
+    { "nBuild", "(JLjava/lang/String;IZ)J", (void*) FontFamily_Builder_build },
 
     { "nGetReleaseNativeFamily", "()J", (void*) FontFamily_Builder_GetReleaseFunc },
 };
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index b417a56..98bc735 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -788,61 +788,18 @@
     return status;
 }
 
-static jobject
+static jint
 android_hardware_SoundTrigger_getModelState(JNIEnv *env, jobject thiz,
                                             jint jHandle)
 {
+    jint status = SOUNDTRIGGER_STATUS_OK;
     ALOGV("getModelState");
     sp<SoundTrigger> module = getSoundTrigger(env, thiz);
     if (module == NULL) {
-        return NULL;
+        return SOUNDTRIGGER_STATUS_ERROR;
     }
-    sp<IMemory> memory;
-    jint status = module->getModelState(jHandle, memory);
-    if (status != 0 || memory == NULL) {
-        ALOGW("getModelState, failed to get model state, status: %d", status);
-        return NULL;
-    }
-    struct sound_trigger_recognition_event* event =
-        (struct sound_trigger_recognition_event *)memory->pointer();
-    if (event == NULL) {
-        return NULL;
-    }
-    if (event->type != SOUND_MODEL_TYPE_GENERIC) {
-        ALOGW("getModelState, unsupported model type: %d", event->type);
-        return NULL;
-    }
-
-    jbyteArray jData = NULL;
-    if (event->data_size) {
-        jData = env->NewByteArray(event->data_size);
-        jbyte *nData = env->GetByteArrayElements(jData, NULL);
-        memcpy(nData, (char *)event + event->data_offset, event->data_size);
-        env->ReleaseByteArrayElements(jData, nData, 0);
-    }
-
-    jobject jAudioFormat = NULL;
-    if (event->trigger_in_data || event->capture_available) {
-        jAudioFormat = env->NewObject(gAudioFormatClass,
-                                      gAudioFormatCstor,
-                                      audioFormatFromNative(event->audio_config.format),
-                                      event->audio_config.sample_rate,
-                                      inChannelMaskFromNative(event->audio_config.channel_mask));
-
-    }
-    jobject jEvent = NULL;
-    jEvent = env->NewObject(gGenericRecognitionEventClass, gGenericRecognitionEventCstor,
-                            event->status, event->model, event->capture_available,
-                            event->capture_session, event->capture_delay_ms,
-                            event->capture_preamble_ms, event->trigger_in_data,
-                            jAudioFormat, jData);
-    if (jAudioFormat != NULL) {
-        env->DeleteLocalRef(jAudioFormat);
-    }
-    if (jData != NULL) {
-        env->DeleteLocalRef(jData);
-    }
-    return jEvent;
+    status = module->getModelState(jHandle);
+    return status;
 }
 
 static const JNINativeMethod gMethods[] = {
@@ -875,7 +832,7 @@
         "(I)I",
         (void *)android_hardware_SoundTrigger_stopRecognition},
     {"getModelState",
-        "(I)Landroid/hardware/soundtrigger/SoundTrigger$RecognitionEvent;",
+        "(I)I",
         (void *)android_hardware_SoundTrigger_getModelState},
 };
 
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index c977437..29051f1 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -892,6 +892,13 @@
             cfaOut[3] = 0;
             break;
         }
+        // MONO and NIR are degenerate case of RGGB pattern: only Red channel
+        // will be used.
+        case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO:
+        case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR: {
+            cfaOut[0] = 0;
+            break;
+        }
         default: {
             return BAD_VALUE;
         }
@@ -1063,6 +1070,8 @@
 
     uint32_t preWidth = 0;
     uint32_t preHeight = 0;
+    uint8_t colorFilter = 0;
+    bool isBayer = true;
     {
         // Check dimensions
         camera_metadata_entry entry =
@@ -1083,10 +1092,25 @@
                     "either the preCorrectionActiveArraySize or the pixelArraySize.");
             return nullptr;
         }
+
+        camera_metadata_entry colorFilterEntry =
+                characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
+        colorFilter = colorFilterEntry.data.u8[0];
+        camera_metadata_entry capabilitiesEntry =
+                characteristics.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
+        size_t capsCount = capabilitiesEntry.count;
+        uint8_t* caps = capabilitiesEntry.data.u8;
+        if (std::find(caps, caps+capsCount, ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME)
+                != caps+capsCount) {
+            isBayer = false;
+        } else if (colorFilter == ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_MONO ||
+                colorFilter == ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_NIR) {
+            jniThrowException(env, "java/lang/AssertionError",
+                    "A camera device with MONO/NIR color filter must have MONOCHROME capability.");
+            return nullptr;
+        }
     }
 
-
-
     writer->addIfd(TIFF_IFD_0);
 
     status_t err = OK;
@@ -1094,9 +1118,12 @@
     const uint32_t samplesPerPixel = 1;
     const uint32_t bitsPerSample = BITS_PER_SAMPLE;
 
-    OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
+    OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_NONE;
     uint8_t cfaPlaneColor[3] = {0, 1, 2};
-    uint8_t cfaEnum = -1;
+    camera_metadata_entry cfaEntry =
+            characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
+    BAIL_IF_EMPTY_RET_NULL_SP(cfaEntry, env, TAG_CFAPATTERN, writer);
+    uint8_t cfaEnum = cfaEntry.data.u8[0];
 
     // TODO: Greensplit.
     // TODO: Add remaining non-essential tags
@@ -1141,12 +1168,20 @@
 
     {
         // Set photometric interpretation
-        uint16_t interpretation = 32803; // CFA
+        uint16_t interpretation = isBayer ? 32803 /* CFA */ :
+                34892; /* Linear Raw */;
         BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_PHOTOMETRICINTERPRETATION, 1,
                 &interpretation, TIFF_IFD_0), env, TAG_PHOTOMETRICINTERPRETATION, writer);
     }
 
     {
+        uint16_t repeatDim[2] = {2, 2};
+        if (!isBayer) {
+            repeatDim[0] = repeatDim[1] = 1;
+        }
+        BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVELREPEATDIM, 2, repeatDim,
+                TIFF_IFD_0), env, TAG_BLACKLEVELREPEATDIM, writer);
+
         // Set blacklevel tags, using dynamic black level if available
         camera_metadata_entry entry =
                 results.find(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL);
@@ -1165,14 +1200,9 @@
                 blackLevelRational[i * 2] = static_cast<uint32_t>(entry.data.i32[i]);
                 blackLevelRational[i * 2 + 1] = 1;
             }
-
         }
-        BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVEL, 4, blackLevelRational,
-                TIFF_IFD_0), env, TAG_BLACKLEVEL, writer);
-
-        uint16_t repeatDim[2] = {2, 2};
-        BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVELREPEATDIM, 2, repeatDim,
-                TIFF_IFD_0), env, TAG_BLACKLEVELREPEATDIM, writer);
+        BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_BLACKLEVEL, repeatDim[0]*repeatDim[1],
+                blackLevelRational, TIFF_IFD_0), env, TAG_BLACKLEVEL, writer);
     }
 
     {
@@ -1189,21 +1219,15 @@
                 TIFF_IFD_0), env, TAG_PLANARCONFIGURATION, writer);
     }
 
-    {
+    // All CFA pattern tags are not necessary for monochrome cameras.
+    if (isBayer) {
         // Set CFA pattern dimensions
         uint16_t repeatDim[2] = {2, 2};
         BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_CFAREPEATPATTERNDIM, 2, repeatDim,
                 TIFF_IFD_0), env, TAG_CFAREPEATPATTERNDIM, writer);
-    }
 
-    {
         // Set CFA pattern
-        camera_metadata_entry entry =
-                        characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
-        BAIL_IF_EMPTY_RET_NULL_SP(entry, env, TAG_CFAPATTERN, writer);
-
         const int cfaLength = 4;
-        cfaEnum = entry.data.u8[0];
         uint8_t cfa[cfaLength];
         if ((err = convertCFA(cfaEnum, /*out*/cfa)) != OK) {
             jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
@@ -1214,15 +1238,11 @@
                 env, TAG_CFAPATTERN, writer);
 
         opcodeCfaLayout = convertCFAEnumToOpcodeLayout(cfaEnum);
-    }
 
-    {
         // Set CFA plane color
         BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_CFAPLANECOLOR, 3, cfaPlaneColor,
                 TIFF_IFD_0), env, TAG_CFAPLANECOLOR, writer);
-    }
 
-    {
         // Set CFA layout
         uint16_t cfaLayout = 1;
         BAIL_IF_INVALID_RET_NULL_SP(writer->addEntry(TAG_CFALAYOUT, 1, &cfaLayout, TIFF_IFD_0),
@@ -1442,7 +1462,7 @@
     }
 
     bool singleIlluminant = false;
-    {
+    if (isBayer) {
         // Set calibration illuminants
         camera_metadata_entry entry1 =
             characteristics.find(ANDROID_SENSOR_REFERENCE_ILLUMINANT1);
@@ -1464,7 +1484,7 @@
         }
     }
 
-    {
+    if (isBayer) {
         // Set color transforms
         camera_metadata_entry entry1 =
             characteristics.find(ANDROID_SENSOR_COLOR_TRANSFORM1);
@@ -1497,7 +1517,7 @@
         }
     }
 
-    {
+    if (isBayer) {
         // Set calibration transforms
         camera_metadata_entry entry1 =
             characteristics.find(ANDROID_SENSOR_CALIBRATION_TRANSFORM1);
@@ -1531,7 +1551,7 @@
         }
     }
 
-    {
+    if (isBayer) {
         // Set forward transforms
         camera_metadata_entry entry1 =
             characteristics.find(ANDROID_SENSOR_FORWARD_MATRIX1);
@@ -1565,7 +1585,7 @@
         }
     }
 
-    {
+    if (isBayer) {
         // Set camera neutral
         camera_metadata_entry entry =
             results.find(ANDROID_SENSOR_NEUTRAL_COLOR_POINT);
@@ -1632,8 +1652,8 @@
         camera_metadata_entry entry =
             results.find(ANDROID_SENSOR_NOISE_PROFILE);
 
-        const status_t numPlaneColors = 3;
-        const status_t numCfaChannels = 4;
+        const status_t numPlaneColors = isBayer ? 3 : 1;
+        const status_t numCfaChannels = isBayer ? 4 : 1;
 
         uint8_t cfaOut[numCfaChannels];
         if ((err = convertCFA(cfaEnum, /*out*/cfaOut)) != OK) {
@@ -1710,42 +1730,44 @@
             }
         }
 
+        // Hot pixel map is specific to bayer camera per DNG spec.
+        if (isBayer) {
+            // Set up bad pixel correction list
+            camera_metadata_entry entry3 = characteristics.find(ANDROID_STATISTICS_HOT_PIXEL_MAP);
 
-        // Set up bad pixel correction list
-        camera_metadata_entry entry3 = characteristics.find(ANDROID_STATISTICS_HOT_PIXEL_MAP);
-
-        if ((entry3.count % 2) != 0) {
-            ALOGE("%s: Hot pixel map contains odd number of values, cannot map to pairs!",
-                    __FUNCTION__);
-            jniThrowRuntimeException(env, "failed to add hotpixel map.");
-            return nullptr;
-        }
-
-        // Adjust the bad pixel coordinates to be relative to the origin of the active area DNG tag
-        std::vector<uint32_t> v;
-        for (size_t i = 0; i < entry3.count; i += 2) {
-            int32_t x = entry3.data.i32[i];
-            int32_t y = entry3.data.i32[i + 1];
-            x -= static_cast<int32_t>(xmin);
-            y -= static_cast<int32_t>(ymin);
-            if (x < 0 || y < 0 || static_cast<uint32_t>(x) >= width ||
-                    static_cast<uint32_t>(y) >= height) {
-                continue;
-            }
-            v.push_back(x);
-            v.push_back(y);
-        }
-        const uint32_t* badPixels = &v[0];
-        uint32_t badPixelCount = v.size();
-
-        if (badPixelCount > 0) {
-            err = builder.addBadPixelListForMetadata(badPixels, badPixelCount, opcodeCfaLayout);
-
-            if (err != OK) {
-                ALOGE("%s: Could not add hotpixel map.", __FUNCTION__);
+            if ((entry3.count % 2) != 0) {
+                ALOGE("%s: Hot pixel map contains odd number of values, cannot map to pairs!",
+                        __FUNCTION__);
                 jniThrowRuntimeException(env, "failed to add hotpixel map.");
                 return nullptr;
             }
+
+            // Adjust the bad pixel coordinates to be relative to the origin of the active area DNG tag
+            std::vector<uint32_t> v;
+            for (size_t i = 0; i < entry3.count; i += 2) {
+                int32_t x = entry3.data.i32[i];
+                int32_t y = entry3.data.i32[i + 1];
+                x -= static_cast<int32_t>(xmin);
+                y -= static_cast<int32_t>(ymin);
+                if (x < 0 || y < 0 || static_cast<uint32_t>(x) >= width ||
+                        static_cast<uint32_t>(y) >= height) {
+                    continue;
+                }
+                v.push_back(x);
+                v.push_back(y);
+            }
+            const uint32_t* badPixels = &v[0];
+            uint32_t badPixelCount = v.size();
+
+            if (badPixelCount > 0) {
+                err = builder.addBadPixelListForMetadata(badPixels, badPixelCount, opcodeCfaLayout);
+
+                if (err != OK) {
+                    ALOGE("%s: Could not add hotpixel map.", __FUNCTION__);
+                    jniThrowRuntimeException(env, "failed to add hotpixel map.");
+                    return nullptr;
+                }
+            }
         }
 
         if (builder.getCount() > 0) {
@@ -1960,10 +1982,12 @@
         tagsToMove.add(TAG_BLACKLEVELREPEATDIM);
         tagsToMove.add(TAG_SAMPLESPERPIXEL);
         tagsToMove.add(TAG_PLANARCONFIGURATION);
-        tagsToMove.add(TAG_CFAREPEATPATTERNDIM);
-        tagsToMove.add(TAG_CFAPATTERN);
-        tagsToMove.add(TAG_CFAPLANECOLOR);
-        tagsToMove.add(TAG_CFALAYOUT);
+        if (isBayer) {
+            tagsToMove.add(TAG_CFAREPEATPATTERNDIM);
+            tagsToMove.add(TAG_CFAPATTERN);
+            tagsToMove.add(TAG_CFAPLANECOLOR);
+            tagsToMove.add(TAG_CFALAYOUT);
+        }
         tagsToMove.add(TAG_XRESOLUTION);
         tagsToMove.add(TAG_YRESOLUTION);
         tagsToMove.add(TAG_RESOLUTIONUNIT);
diff --git a/core/jni/android_hardware_input_InputApplicationHandle.cpp b/core/jni/android_hardware_input_InputApplicationHandle.cpp
index 8ace8da..5887fa7 100644
--- a/core/jni/android_hardware_input_InputApplicationHandle.cpp
+++ b/core/jni/android_hardware_input_InputApplicationHandle.cpp
@@ -135,13 +135,13 @@
         LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
 
 int register_android_server_InputApplicationHandle(JNIEnv* env) {
-    int res = jniRegisterNativeMethods(env, "com/android/server/input/InputApplicationHandle",
+    int res = jniRegisterNativeMethods(env, "android/view/InputApplicationHandle",
             gInputApplicationHandleMethods, NELEM(gInputApplicationHandleMethods));
     (void) res;  // Faked use when LOG_NDEBUG.
     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
 
     jclass clazz;
-    FIND_CLASS(clazz, "com/android/server/input/InputApplicationHandle");
+    FIND_CLASS(clazz, "android/view/InputApplicationHandle");
 
     GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, clazz,
             "ptr", "J");
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index f4829ad..6ecb5de 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -80,51 +80,47 @@
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     jobject obj = env->NewLocalRef(mObjWeak);
     if (!obj) {
-        releaseInfo();
+        releaseChannel();
         return false;
     }
 
-    if (!mInfo) {
-        mInfo = new InputWindowInfo();
-    } else {
-        mInfo->touchableRegion.clear();
-    }
+    mInfo.touchableRegion.clear();
 
     jobject inputChannelObj = env->GetObjectField(obj,
             gInputWindowHandleClassInfo.inputChannel);
     if (inputChannelObj) {
-        mInfo->inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj);
+        mInfo.inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj);
         env->DeleteLocalRef(inputChannelObj);
     } else {
-        mInfo->inputChannel.clear();
+        mInfo.inputChannel.clear();
     }
 
     jstring nameObj = jstring(env->GetObjectField(obj,
             gInputWindowHandleClassInfo.name));
     if (nameObj) {
         const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
-        mInfo->name = nameStr;
+        mInfo.name = nameStr;
         env->ReleaseStringUTFChars(nameObj, nameStr);
         env->DeleteLocalRef(nameObj);
     } else {
-        mInfo->name = "<null>";
+        mInfo.name = "<null>";
     }
 
-    mInfo->layoutParamsFlags = env->GetIntField(obj,
+    mInfo.layoutParamsFlags = env->GetIntField(obj,
             gInputWindowHandleClassInfo.layoutParamsFlags);
-    mInfo->layoutParamsType = env->GetIntField(obj,
+    mInfo.layoutParamsType = env->GetIntField(obj,
             gInputWindowHandleClassInfo.layoutParamsType);
-    mInfo->dispatchingTimeout = env->GetLongField(obj,
+    mInfo.dispatchingTimeout = env->GetLongField(obj,
             gInputWindowHandleClassInfo.dispatchingTimeoutNanos);
-    mInfo->frameLeft = env->GetIntField(obj,
+    mInfo.frameLeft = env->GetIntField(obj,
             gInputWindowHandleClassInfo.frameLeft);
-    mInfo->frameTop = env->GetIntField(obj,
+    mInfo.frameTop = env->GetIntField(obj,
             gInputWindowHandleClassInfo.frameTop);
-    mInfo->frameRight = env->GetIntField(obj,
+    mInfo.frameRight = env->GetIntField(obj,
             gInputWindowHandleClassInfo.frameRight);
-    mInfo->frameBottom = env->GetIntField(obj,
+    mInfo.frameBottom = env->GetIntField(obj,
             gInputWindowHandleClassInfo.frameBottom);
-    mInfo->scaleFactor = env->GetFloatField(obj,
+    mInfo.scaleFactor = env->GetFloatField(obj,
             gInputWindowHandleClassInfo.scaleFactor);
 
     jobject regionObj = env->GetObjectField(obj,
@@ -133,30 +129,30 @@
         SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
         for (SkRegion::Iterator it(*region); !it.done(); it.next()) {
             const SkIRect& rect = it.rect();
-            mInfo->addTouchableRegion(Rect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom));
+            mInfo.addTouchableRegion(Rect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom));
         }
         env->DeleteLocalRef(regionObj);
     }
 
-    mInfo->visible = env->GetBooleanField(obj,
+    mInfo.visible = env->GetBooleanField(obj,
             gInputWindowHandleClassInfo.visible);
-    mInfo->canReceiveKeys = env->GetBooleanField(obj,
+    mInfo.canReceiveKeys = env->GetBooleanField(obj,
             gInputWindowHandleClassInfo.canReceiveKeys);
-    mInfo->hasFocus = env->GetBooleanField(obj,
+    mInfo.hasFocus = env->GetBooleanField(obj,
             gInputWindowHandleClassInfo.hasFocus);
-    mInfo->hasWallpaper = env->GetBooleanField(obj,
+    mInfo.hasWallpaper = env->GetBooleanField(obj,
             gInputWindowHandleClassInfo.hasWallpaper);
-    mInfo->paused = env->GetBooleanField(obj,
+    mInfo.paused = env->GetBooleanField(obj,
             gInputWindowHandleClassInfo.paused);
-    mInfo->layer = env->GetIntField(obj,
+    mInfo.layer = env->GetIntField(obj,
             gInputWindowHandleClassInfo.layer);
-    mInfo->ownerPid = env->GetIntField(obj,
+    mInfo.ownerPid = env->GetIntField(obj,
             gInputWindowHandleClassInfo.ownerPid);
-    mInfo->ownerUid = env->GetIntField(obj,
+    mInfo.ownerUid = env->GetIntField(obj,
             gInputWindowHandleClassInfo.ownerUid);
-    mInfo->inputFeatures = env->GetIntField(obj,
+    mInfo.inputFeatures = env->GetIntField(obj,
             gInputWindowHandleClassInfo.inputFeatures);
-    mInfo->displayId = env->GetIntField(obj,
+    mInfo.displayId = env->GetIntField(obj,
             gInputWindowHandleClassInfo.displayId);
 
     env->DeleteLocalRef(obj);
@@ -225,20 +221,20 @@
         LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
 
 int register_android_server_InputWindowHandle(JNIEnv* env) {
-    int res = jniRegisterNativeMethods(env, "com/android/server/input/InputWindowHandle",
+    int res = jniRegisterNativeMethods(env, "android/view/InputWindowHandle",
             gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods));
     (void) res;  // Faked use when LOG_NDEBUG.
     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
 
     jclass clazz;
-    FIND_CLASS(clazz, "com/android/server/input/InputWindowHandle");
+    FIND_CLASS(clazz, "android/view/InputWindowHandle");
 
     GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, clazz,
             "ptr", "J");
 
     GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle,
             clazz,
-            "inputApplicationHandle", "Lcom/android/server/input/InputApplicationHandle;");
+            "inputApplicationHandle", "Landroid/view/InputApplicationHandle;");
 
     GET_FIELD_ID(gInputWindowHandleClassInfo.inputChannel, clazz,
             "inputChannel", "Landroid/view/InputChannel;");
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 80572f3..b1a9866 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -32,16 +32,15 @@
     android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str());
 }
 
-void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring appPref, jboolean devOptIn,
+void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jboolean devOptIn,
                          jobject rulesFd, jlong rulesOffset, jlong rulesLength) {
     ScopedUtfChars pathChars(env, path);
     ScopedUtfChars appNameChars(env, appName);
-    ScopedUtfChars appPrefChars(env, appPref);
 
     int rulesFd_native = jniGetFDFromFileDescriptor(env, rulesFd);
 
     android::GraphicsEnv::getInstance().setAngleInfo(pathChars.c_str(), appNameChars.c_str(),
-            appPrefChars.c_str(), devOptIn, rulesFd_native, rulesOffset, rulesLength);
+            devOptIn, rulesFd_native, rulesOffset, rulesLength);
 }
 
 void setLayerPaths_native(JNIEnv* env, jobject clazz, jobject classLoader, jstring layerPaths) {
@@ -68,7 +67,7 @@
 const JNINativeMethod g_methods[] = {
     { "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
     { "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
-    { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLjava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
+    { "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;ZLjava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
     { "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
     { "setDebugLayers", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayers_native) },
     { "setDebugLayersGLES", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDebugLayersGLES_native) },
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index b2d44e7..7b564ae 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -24,9 +24,13 @@
 #include <sys/system_properties.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <unistd.h>
 
 #include <private/android_filesystem_config.h> // for AID_SYSTEM
 
+#include <sstream>
+#include <string>
+
 #include "android-base/logging.h"
 #include "android-base/properties.h"
 #include "android-base/stringprintf.h"
@@ -38,6 +42,7 @@
 #include "androidfw/AssetManager2.h"
 #include "androidfw/AttributeResolution.h"
 #include "androidfw/MutexGuard.h"
+#include "androidfw/PosixUtils.h"
 #include "androidfw/ResourceTypes.h"
 #include "core_jni_helpers.h"
 #include "jni.h"
@@ -54,6 +59,7 @@
 extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
 
 using ::android::base::StringPrintf;
+using ::android::util::ExecuteBinary;
 
 namespace android {
 
@@ -161,18 +167,20 @@
       argv[argc++] = AssetManager::IDMAP_DIR;
 
       // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
-      // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
+      // use VENDOR_OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in
+      // addition to VENDOR_OVERLAY_DIR.
       std::string overlay_theme_path = base::GetProperty(AssetManager::OVERLAY_THEME_DIR_PROPERTY,
                                                          "");
       if (!overlay_theme_path.empty()) {
-        overlay_theme_path = std::string(AssetManager::OVERLAY_DIR) + "/" + overlay_theme_path;
+        overlay_theme_path =
+          std::string(AssetManager::VENDOR_OVERLAY_DIR) + "/" + overlay_theme_path;
         if (stat(overlay_theme_path.c_str(), &st) == 0) {
           argv[argc++] = overlay_theme_path.c_str();
         }
       }
 
-      if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
-        argv[argc++] = AssetManager::OVERLAY_DIR;
+      if (stat(AssetManager::VENDOR_OVERLAY_DIR, &st) == 0) {
+        argv[argc++] = AssetManager::VENDOR_OVERLAY_DIR;
       }
 
       if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
@@ -200,6 +208,75 @@
   }
 }
 
+static jobjectArray NativeCreateIdmapsForStaticOverlaysTargetingAndroid(JNIEnv* env,
+                                                                        jclass /*clazz*/) {
+  // --input-directory can be given multiple times, but idmap2 expects the directory to exist
+  std::vector<std::string> input_dirs;
+  struct stat st;
+  if (stat(AssetManager::VENDOR_OVERLAY_DIR, &st) == 0) {
+    input_dirs.push_back(AssetManager::VENDOR_OVERLAY_DIR);
+  }
+
+  if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
+    input_dirs.push_back(AssetManager::PRODUCT_OVERLAY_DIR);
+  }
+
+  if (stat(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR, &st) == 0) {
+    input_dirs.push_back(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR);
+  }
+
+  if (input_dirs.empty()) {
+    LOG(WARNING) << "no directories for idmap2 to scan";
+    return env->NewObjectArray(0, g_stringClass, nullptr);
+  }
+
+  std::vector<std::string> argv{"/system/bin/idmap2",
+    "scan",
+    "--recursive",
+    "--target-package-name", "android",
+    "--target-apk-path", "/system/framework/framework-res.apk",
+    "--output-directory", "/data/resource-cache"};
+
+  for (const auto& dir : input_dirs) {
+    argv.push_back("--input-directory");
+    argv.push_back(dir);
+  }
+
+  const auto result = ExecuteBinary(argv);
+
+  if (!result) {
+      LOG(ERROR) << "failed to execute idmap2";
+      return nullptr;
+  }
+
+  if (result->status != 0) {
+    LOG(ERROR) << "idmap2: " << result->stderr;
+    return nullptr;
+  }
+
+  std::vector<std::string> idmap_paths;
+  std::istringstream input(result->stdout);
+  std::string path;
+  while (std::getline(input, path)) {
+    idmap_paths.push_back(path);
+  }
+
+  jobjectArray array = env->NewObjectArray(idmap_paths.size(), g_stringClass, nullptr);
+  if (array == nullptr) {
+    return nullptr;
+  }
+  for (size_t i = 0; i < idmap_paths.size(); i++) {
+    const std::string path = idmap_paths[i];
+    jstring java_string = env->NewStringUTF(path.c_str());
+    if (env->ExceptionCheck()) {
+      return nullptr;
+    }
+    env->SetObjectArrayElement(array, i, java_string);
+    env->DeleteLocalRef(java_string);
+  }
+  return array;
+}
+
 static jint CopyValue(JNIEnv* env, ApkAssetsCookie cookie, const Res_value& value, uint32_t ref,
                       uint32_t type_spec_flags, ResTable_config* config, jobject out_typed_value) {
   env->SetIntField(out_typed_value, gTypedValueOffsets.mType, value.dataType);
@@ -1405,6 +1482,8 @@
 
     // System/idmap related methods.
     {"nativeVerifySystemIdmaps", "()V", (void*)NativeVerifySystemIdmaps},
+    {"nativeCreateIdmapsForStaticOverlaysTargetingAndroid", "()[Ljava/lang/String;",
+     (void*)NativeCreateIdmapsForStaticOverlaysTargetingAndroid},
 
     // Global management/debug methods.
     {"getGlobalAssetCount", "()I", (void*)NativeGetGlobalAssetCount},
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index 2f17907..fb6be6b 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -249,6 +249,24 @@
     }
 }
 
+static jobject android_view_InputChannel_nativeGetToken(JNIEnv* env, jobject obj) {
+    NativeInputChannel* nativeInputChannel =
+        android_view_InputChannel_getNativeInputChannel(env, obj);
+    if (nativeInputChannel) {
+        return javaObjectForIBinder(env, nativeInputChannel->getInputChannel()->getToken());
+    }
+    return 0;
+}
+
+static void android_view_InputChannel_nativeSetToken(JNIEnv* env, jobject obj, jobject tokenObj) {
+    NativeInputChannel* nativeInputChannel =
+        android_view_InputChannel_getNativeInputChannel(env, obj);
+    sp<IBinder> token = ibinderForJavaObject(env, tokenObj);
+    if (nativeInputChannel != nullptr) {
+        nativeInputChannel->getInputChannel()->setToken(token);
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gInputChannelMethods[] = {
@@ -267,6 +285,10 @@
             (void*)android_view_InputChannel_nativeGetName },
     { "nativeDup", "(Landroid/view/InputChannel;)V",
             (void*)android_view_InputChannel_nativeDup },
+    { "nativeGetToken", "()Landroid/os/IBinder;",
+            (void*)android_view_InputChannel_nativeGetToken },
+    { "nativeSetToken", "(Landroid/os/IBinder;)V",
+            (void*)android_view_InputChannel_nativeSetToken }
 };
 
 int register_android_view_InputChannel(JNIEnv* env) {
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index f512ce4..b8139a7 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -556,18 +556,18 @@
         proxy->setWideGamut(true);
     }
     proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
-    proxy->initialize(surface);
+    proxy->setSurface(surface);
     // Shadows can't be used via this interface, so just set the light source
     // to all 0s.
-    proxy->setup(0, 0, 0);
-    proxy->setLightCenter((Vector3){0, 0, 0});
+    proxy->setLightAlpha(0, 0);
+    proxy->setLightGeometry((Vector3){0, 0, 0}, 0);
     return (jlong) proxy;
 }
 
 static void setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfacePtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
     sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
-    proxy->updateSurface(surface);
+    proxy->setSurface(surface);
 }
 
 static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 4eda3ab..ec9c860 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -19,6 +19,7 @@
 
 #include "android_os_Parcel.h"
 #include "android_util_Binder.h"
+#include "android_hardware_input_InputWindowHandle.h"
 #include "android/graphics/Bitmap.h"
 #include "android/graphics/GraphicsJNI.h"
 #include "android/graphics/Region.h"
@@ -324,6 +325,18 @@
     transaction->setAlpha(ctrl, alpha);
 }
 
+static void nativeSetInputWindowInfo(JNIEnv* env, jclass clazz, jlong transactionObj,
+        jlong nativeObject, jobject inputWindow) {
+    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
+    sp<NativeInputWindowHandle> handle = android_server_InputWindowHandle_getHandle(
+            env, inputWindow);
+    handle->updateInfo();
+
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    transaction->setInputWindowInfo(ctrl, *handle->getInfo());
+}
+
 static void nativeSetColor(JNIEnv* env, jclass clazz, jlong transactionObj,
         jlong nativeObject, jfloatArray fColor) {
     auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -930,6 +943,8 @@
             (void*)nativeScreenshot },
     {"nativeCaptureLayers", "(Landroid/os/IBinder;Landroid/graphics/Rect;F)Landroid/graphics/GraphicBuffer;",
             (void*)nativeCaptureLayers },
+    {"nativeSetInputWindowInfo", "(JJLandroid/view/InputWindowHandle;)V",
+     (void*)nativeSetInputWindowInfo },
 };
 
 int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 7a5b604..702741e 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -686,31 +686,20 @@
     env->ReleaseStringUTFChars(jname, name);
 }
 
-static void android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jobject jsurface) {
-    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
-    proxy->initialize(surface);
-}
-
-static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_setSurface(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jobject jsurface) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
     sp<Surface> surface;
     if (jsurface) {
         surface = android_view_Surface_getSurface(env, jsurface);
     }
-    proxy->updateSurface(surface);
+    proxy->setSurface(surface);
 }
 
-static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jobject jsurface) {
+static jboolean android_view_ThreadedRenderer_pause(JNIEnv* env, jobject clazz,
+        jlong proxyPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<Surface> surface;
-    if (jsurface) {
-        surface = android_view_Surface_getSurface(env, jsurface);
-    }
-    return proxy->pauseSurface(surface);
+    return proxy->pause();
 }
 
 static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
@@ -719,16 +708,16 @@
     proxy->setStopped(stopped);
 }
 
-static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
-        jfloat lightRadius, jint ambientShadowAlpha, jint spotShadowAlpha) {
+static void android_view_ThreadedRenderer_setLightAlpha(JNIEnv* env, jobject clazz, jlong proxyPtr,
+        jfloat ambientShadowAlpha, jfloat spotShadowAlpha) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha);
+    proxy->setLightAlpha((uint8_t) (255 * ambientShadowAlpha), (uint8_t) (255 * spotShadowAlpha));
 }
 
-static void android_view_ThreadedRenderer_setLightCenter(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ) {
+static void android_view_ThreadedRenderer_setLightGeometry(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->setLightCenter((Vector3){lightX, lightY, lightZ});
+    proxy->setLightGeometry((Vector3){lightX, lightY, lightZ}, lightRadius);
 }
 
 static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
@@ -990,13 +979,12 @@
     {
         ContextFactory factory;
         RenderProxy proxy{true, renderNode, &factory};
-        proxy.loadSystemProperties();
         proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
-        proxy.initialize(surface);
+        proxy.setSurface(surface);
         // Shadows can't be used via this interface, so just set the light source
         // to all 0s.
-        proxy.setup(0, 0, 0);
-        proxy.setLightCenter((Vector3){0, 0, 0});
+        proxy.setLightAlpha(0, 0);
+        proxy.setLightGeometry((Vector3){0, 0, 0}, 0);
         nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
         UiFrameInfoBuilder(proxy.frameInfo())
                 .setVsync(vsync, vsync)
@@ -1058,10 +1046,9 @@
 }
 
 static void android_view_ThreadedRenderer_allocateBuffers(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jobject jsurface) {
+        jlong proxyPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    sp<Surface> surface = android_view_Surface_getSurface(env, jsurface);
-    proxy->allocateBuffers(surface);
+    proxy->allocateBuffers();
 }
 
 static void android_view_ThreadedRenderer_setForceDark(JNIEnv* env, jobject clazz,
@@ -1118,7 +1105,7 @@
 // JNI Glue
 // ----------------------------------------------------------------------------
 
-const char* const kClassPathName = "android/view/ThreadedRenderer";
+const char* const kClassPathName = "android/graphics/HardwareRenderer";
 
 static const JNINativeMethod gMethods[] = {
     { "nRotateProcessStatsBuffer", "()V", (void*) android_view_ThreadedRenderer_rotateProcessStatsBuffer },
@@ -1129,12 +1116,11 @@
     { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
     { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
     { "nSetName", "(JLjava/lang/String;)V", (void*) android_view_ThreadedRenderer_setName },
-    { "nInitialize", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_initialize },
-    { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
-    { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
+    { "nSetSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_setSurface },
+    { "nPause", "(J)Z", (void*) android_view_ThreadedRenderer_pause },
     { "nSetStopped", "(JZ)V", (void*) android_view_ThreadedRenderer_setStopped },
-    { "nSetup", "(JFII)V", (void*) android_view_ThreadedRenderer_setup },
-    { "nSetLightCenter", "(JFFF)V", (void*) android_view_ThreadedRenderer_setLightCenter },
+    { "nSetLightAlpha", "(JFF)V", (void*) android_view_ThreadedRenderer_setLightAlpha },
+    { "nSetLightGeometry", "(JFFFF)V", (void*) android_view_ThreadedRenderer_setLightGeometry },
     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
     { "nSetWideGamut", "(JZ)V", (void*) android_view_ThreadedRenderer_setWideGamut },
     { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
@@ -1161,9 +1147,9 @@
     { "nRemoveRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_removeRenderNode},
     { "nDrawRenderNode", "(JJ)V", (void*) android_view_ThreadedRendererd_drawRenderNode},
     { "nSetContentDrawBounds", "(JIIII)V", (void*)android_view_ThreadedRenderer_setContentDrawBounds},
-    { "nSetFrameCallback", "(JLandroid/view/ThreadedRenderer$FrameDrawingCallback;)V",
+    { "nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
             (void*)android_view_ThreadedRenderer_setFrameCallback},
-    { "nSetFrameCompleteCallback", "(JLandroid/view/ThreadedRenderer$FrameCompleteCallback;)V",
+    { "nSetFrameCompleteCallback", "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
             (void*)android_view_ThreadedRenderer_setFrameCompleteCallback },
     { "nAddFrameMetricsObserver",
             "(JLandroid/view/FrameMetricsObserver;)J",
@@ -1182,7 +1168,7 @@
     { "nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled },
     { "nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess },
     { "nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority },
-    { "nAllocateBuffers", "(JLandroid/view/Surface;)V", (void*)android_view_ThreadedRenderer_allocateBuffers },
+    { "nAllocateBuffers", "(J)V", (void*)android_view_ThreadedRenderer_allocateBuffers },
     { "nSetForceDark", "(JZ)V", (void*)android_view_ThreadedRenderer_setForceDark },
 };
 
@@ -1215,12 +1201,12 @@
             env, metricsClass, "mTimingData", "[J");
 
     jclass frameCallbackClass = FindClassOrDie(env,
-            "android/view/ThreadedRenderer$FrameDrawingCallback");
+            "android/graphics/HardwareRenderer$FrameDrawingCallback");
     gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass,
             "onFrameDraw", "(J)V");
 
     jclass frameCompleteClass = FindClassOrDie(env,
-            "android/view/ThreadedRenderer$FrameCompleteCallback");
+            "android/graphics/HardwareRenderer$FrameCompleteCallback");
     gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass,
             "onFrameComplete", "(J)V");
 
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index b3ff4db..b708735 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -175,7 +175,7 @@
             }
         }
         s.tag = rawTag >> 32;
-        if (limitTag != -1 && s.tag != limitTag) {
+        if (limitTag != -1 && s.tag != static_cast<uint32_t>(limitTag)) {
             //ALOGI("skipping due to tag: %s", buffer);
             continue;
         }
@@ -188,7 +188,7 @@
         if (sscanf(pos, "%u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64,
                 &s.uid, &s.set, &s.rxBytes, &s.rxPackets,
                 &s.txBytes, &s.txPackets) == 6) {
-            if (limitUid != -1 && limitUid != s.uid) {
+            if (limitUid != -1 && static_cast<uint32_t>(limitUid) != s.uid) {
                 //ALOGI("skipping due to uid: %s", buffer);
                 continue;
             }
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 4e20e29..8e9a0bf 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -20,7 +20,9 @@
 #include <sys/mount.h>
 #include <linux/fs.h>
 
+#include <functional>
 #include <list>
+#include <optional>
 #include <sstream>
 #include <string>
 
@@ -70,6 +72,8 @@
 
 namespace {
 
+using namespace std::placeholders;
+
 using android::String8;
 using android::base::StringAppendF;
 using android::base::StringPrintf;
@@ -651,12 +655,12 @@
 static FileDescriptorTable* gOpenFdTable = NULL;
 
 static bool FillFileDescriptorVector(JNIEnv* env,
-                                     jintArray java_fds,
+                                     jintArray managed_fds,
                                      std::vector<int>* fds,
                                      std::string* error_msg) {
   CHECK(fds != nullptr);
-  if (java_fds != nullptr) {
-    ScopedIntArrayRO ar(env, java_fds);
+  if (managed_fds != nullptr) {
+    ScopedIntArrayRO ar(env, managed_fds);
     if (ar.get() == nullptr) {
       *error_msg = "Bad fd array";
       return false;
@@ -669,246 +673,46 @@
   return true;
 }
 
-// Utility routine to specialize a zygote child process.
-static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
-                             jint runtime_flags, jobjectArray javaRlimits,
-                             jlong permittedCapabilities, jlong effectiveCapabilities,
-                             jint mount_external, jstring java_se_info, jstring java_se_name,
-                             bool is_system_server, bool is_child_zygote, jstring instructionSet,
-                             jstring dataDir, jstring packageName, jobjectArray packagesForUid,
-                             jobjectArray visibleVolIds) {
-  std::string error_msg;
-
-  auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg)
-      __attribute__ ((noreturn)) {
-    const char* se_name_c_str = nullptr;
-    std::unique_ptr<ScopedUtfChars> se_name;
-    if (java_se_name != nullptr) {
-      se_name.reset(new ScopedUtfChars(env, java_se_name));
-      se_name_c_str = se_name->c_str();
-    }
-    if (se_name_c_str == nullptr && is_system_server) {
-      se_name_c_str = "system_server";
-    }
-    const std::string& error_msg = (se_name_c_str == nullptr)
-        ? msg
-        : StringPrintf("(%s) %s", se_name_c_str, msg.c_str());
-    env->FatalError(error_msg.c_str());
-    __builtin_unreachable();
-  };
-
-  // Keep capabilities across UID change, unless we're staying root.
-  if (uid != 0) {
-    if (!EnableKeepCapabilities(&error_msg)) {
-      fail_fn(error_msg);
+[[noreturn]]
+static void ZygoteFailure(JNIEnv* env,
+                          const char* process_name,
+                          jstring managed_process_name,
+                          const std::string& msg) {
+  std::unique_ptr<ScopedUtfChars> scoped_managed_process_name_ptr = nullptr;
+  if (managed_process_name != nullptr) {
+    scoped_managed_process_name_ptr.reset(new ScopedUtfChars(env, managed_process_name));
+    if (scoped_managed_process_name_ptr->c_str() != nullptr) {
+      process_name = scoped_managed_process_name_ptr->c_str();
     }
   }
 
-  if (!SetInheritable(permittedCapabilities, &error_msg)) {
-    fail_fn(error_msg);
-  }
-  if (!DropCapabilitiesBoundingSet(&error_msg)) {
-    fail_fn(error_msg);
-  }
+  const std::string& error_msg =
+      (process_name == nullptr) ? msg : StringPrintf("(%s) %s", process_name, msg.c_str());
 
-  bool use_native_bridge = !is_system_server && (instructionSet != NULL)
-      && android::NativeBridgeAvailable();
-  if (use_native_bridge) {
-    ScopedUtfChars isa_string(env, instructionSet);
-    use_native_bridge = android::NeedsNativeBridge(isa_string.c_str());
-  }
-  if (use_native_bridge && dataDir == NULL) {
-    // dataDir should never be null if we need to use a native bridge.
-    // In general, dataDir will never be null for normal applications. It can only happen in
-    // special cases (for isolated processes which are not associated with any app). These are
-    // launched by the framework and should not be emulated anyway.
-    use_native_bridge = false;
-    ALOGW("Native bridge will not be used because dataDir == NULL.");
-  }
+  env->FatalError(error_msg.c_str());
+  __builtin_unreachable();
+}
 
-  std::string package_name_str("");
-  if (packageName != nullptr) {
-    ScopedUtfChars package(env, packageName);
-    package_name_str = package.c_str();
-  } else if (is_system_server) {
-    package_name_str = "android";
-  }
-  std::vector<std::string> packages_for_uid;
-  if (packagesForUid != nullptr) {
-    jsize count = env->GetArrayLength(packagesForUid);
-    for (jsize i = 0; i < count; ++i) {
-      jstring package_for_uid = (jstring) env->GetObjectArrayElement(packagesForUid, i);
-      ScopedUtfChars package(env, package_for_uid);
-      packages_for_uid.push_back(package.c_str());
-    }
-  }
-  std::vector<std::string> visible_vol_ids;
-  if (visibleVolIds != nullptr) {
-    jsize count = env->GetArrayLength(visibleVolIds);
-    for (jsize i = 0; i < count; ++i) {
-      jstring visible_vol_id = (jstring) env->GetObjectArrayElement(visibleVolIds, i);
-      ScopedUtfChars vol(env, visible_vol_id);
-      visible_vol_ids.push_back(vol.c_str());
-    }
-  }
-  bool success = MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg,
-      package_name_str, packages_for_uid, visible_vol_ids);
-  if (!success) {
-    ALOGW("Failed to mount emulated storage: %s (%s)", error_msg.c_str(), strerror(errno));
-    if (errno == ENOTCONN || errno == EROFS) {
-      // When device is actively encrypting, we get ENOTCONN here
-      // since FUSE was mounted before the framework restarted.
-      // When encrypted device is booting, we get EROFS since
-      // FUSE hasn't been created yet by init.
-      // In either case, continue without external storage.
+static std::optional<std::string> ExtractJString(JNIEnv* env,
+                                                 const char* process_name,
+                                                 jstring managed_process_name,
+                                                 jstring managed_string) {
+  if (managed_string == nullptr) {
+    return std::optional<std::string>();
+  } else {
+    ScopedUtfChars scoped_string_chars(env, managed_string);
+
+    if (scoped_string_chars.c_str() != nullptr) {
+      return std::optional<std::string>(scoped_string_chars.c_str());
     } else {
-      fail_fn(error_msg);
+      ZygoteFailure(env, process_name, managed_process_name, "Failed to extract JString.");
     }
   }
-
-  // If this zygote isn't root, it won't be able to create a process group,
-  // since the directory is owned by root.
-  if (!is_system_server && getuid() == 0) {
-      int rc = createProcessGroup(uid, getpid());
-      if (rc != 0) {
-          if (rc == -EROFS) {
-              ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
-          } else {
-              ALOGE("createProcessGroup(%d, %d) failed: %s", uid, 0/*pid*/, strerror(-rc));
-          }
-      }
-  }
-
-  if (!SetGids(env, javaGids, &error_msg)) {
-    fail_fn(error_msg);
-  }
-
-  if (!SetRLimits(env, javaRlimits, &error_msg)) {
-    fail_fn(error_msg);
-  }
-
-  if (use_native_bridge) {
-    ScopedUtfChars isa_string(env, instructionSet);
-    ScopedUtfChars data_dir(env, dataDir);
-    android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str());
-  }
-
-  int rc = setresgid(gid, gid, gid);
-  if (rc == -1) {
-    fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno)));
-  }
-
-  // Must be called when the new process still has CAP_SYS_ADMIN, in this case, before changing
-  // uid from 0, which clears capabilities.  The other alternative is to call
-  // prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that breaks SELinux domain transition (see
-  // b/71859146).  As the result, privileged syscalls used below still need to be accessible in
-  // app process.
-  SetUpSeccompFilter(uid);
-
-  rc = setresuid(uid, uid, uid);
-  if (rc == -1) {
-    fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno)));
-  }
-
-  // The "dumpable" flag of a process, which controls core dump generation, is
-  // overwritten by the value in /proc/sys/fs/suid_dumpable when the effective
-  // user or group ID changes. See proc(5) for possible values. In most cases,
-  // the value is 0, so core dumps are disabled for zygote children. However,
-  // when running in a Chrome OS container, the value is already set to 2,
-  // which allows the external crash reporter to collect all core dumps. Since
-  // only system crashes are interested, core dump is disabled for app
-  // processes. This also ensures compliance with CTS.
-  int dumpable = prctl(PR_GET_DUMPABLE);
-  if (dumpable == -1) {
-      ALOGE("prctl(PR_GET_DUMPABLE) failed: %s", strerror(errno));
-      RuntimeAbort(env, __LINE__, "prctl(PR_GET_DUMPABLE) failed");
-  }
-  if (dumpable == 2 && uid >= AID_APP) {
-    if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) {
-      ALOGE("prctl(PR_SET_DUMPABLE, 0) failed: %s", strerror(errno));
-      RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 0) failed");
-    }
-  }
-
-  if (NeedsNoRandomizeWorkaround()) {
-      // Work around ARM kernel ASLR lossage (http://b/5817320).
-      int old_personality = personality(0xffffffff);
-      int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
-      if (new_personality == -1) {
-          ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
-      }
-  }
-
-  if (!SetCapabilities(permittedCapabilities, effectiveCapabilities, permittedCapabilities,
-                       &error_msg)) {
-    fail_fn(error_msg);
-  }
-
-  if (!SetSchedulerPolicy(&error_msg)) {
-    fail_fn(error_msg);
-  }
-
-  const char* se_info_c_str = NULL;
-  ScopedUtfChars* se_info = NULL;
-  if (java_se_info != NULL) {
-      se_info = new ScopedUtfChars(env, java_se_info);
-      se_info_c_str = se_info->c_str();
-      if (se_info_c_str == NULL) {
-        fail_fn("se_info_c_str == NULL");
-      }
-  }
-  const char* se_name_c_str = NULL;
-  ScopedUtfChars* se_name = NULL;
-  if (java_se_name != NULL) {
-      se_name = new ScopedUtfChars(env, java_se_name);
-      se_name_c_str = se_name->c_str();
-      if (se_name_c_str == NULL) {
-        fail_fn("se_name_c_str == NULL");
-      }
-  }
-  rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
-  if (rc == -1) {
-    fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
-          is_system_server, se_info_c_str, se_name_c_str));
-  }
-
-  // Make it easier to debug audit logs by setting the main thread's name to the
-  // nice name rather than "app_process".
-  if (se_name_c_str == NULL && is_system_server) {
-    se_name_c_str = "system_server";
-  }
-  if (se_name_c_str != NULL) {
-    SetThreadName(se_name_c_str);
-  }
-
-  delete se_info;
-  delete se_name;
-
-  // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
-  UnsetChldSignalHandler();
-
-  if (is_system_server) {
-    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks);
-    if (env->ExceptionCheck()) {
-      fail_fn("Error calling post fork system server hooks.");
-    }
-    // TODO(oth): Remove hardcoded label here (b/117874058).
-    static const char* kSystemServerLabel = "u:r:system_server:s0";
-    if (selinux_android_setcon(kSystemServerLabel) != 0) {
-      fail_fn(CREATE_ERROR("selinux_android_setcon(%s)", kSystemServerLabel));
-    }
-  }
-
-  env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
-                            is_system_server, is_child_zygote, instructionSet);
-  if (env->ExceptionCheck()) {
-    fail_fn("Error calling post fork hooks.");
-  }
 }
 
-// Utility routine to fork zygote and specialize the child process.
-static pid_t ForkCommon(JNIEnv* env, jstring java_se_name, bool is_system_server,
-                        jintArray fdsToClose, jintArray fdsToIgnore) {
+// Utility routine to fork a zygote.
+static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
+                        jintArray managed_fds_to_close, jintArray managed_fds_to_ignore) {
   SetSignalHandlers();
 
   // Block SIGCHLD prior to fork.
@@ -916,23 +720,9 @@
   sigemptyset(&sigchld);
   sigaddset(&sigchld, SIGCHLD);
 
-  auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg)
-      __attribute__ ((noreturn)) {
-    const char* se_name_c_str = nullptr;
-    std::unique_ptr<ScopedUtfChars> se_name;
-    if (java_se_name != nullptr) {
-      se_name.reset(new ScopedUtfChars(env, java_se_name));
-      se_name_c_str = se_name->c_str();
-    }
-    if (se_name_c_str == nullptr && is_system_server) {
-      se_name_c_str = "system_server";
-    }
-    const std::string& error_msg = (se_name_c_str == nullptr)
-        ? msg
-        : StringPrintf("(%s) %s", se_name_c_str, msg.c_str());
-    env->FatalError(error_msg.c_str());
-    __builtin_unreachable();
-  };
+  // Curry a failure function.
+  auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote",
+                           nullptr, _1);
 
   // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
   // log, which would result in the logging FDs we close being reopened.
@@ -948,18 +738,18 @@
   __android_log_close();
   stats_log_close();
 
+  // If this is the first fork for this zygote, create the open FD table.  If
+  // it isn't, we just need to check whether the list of open files has changed
+  // (and it shouldn't in the normal case).
   std::string error_msg;
-
-  // If this is the first fork for this zygote, create the open FD table.
-  // If it isn't, we just need to check whether the list of open files has
-  // changed (and it shouldn't in the normal case).
   std::vector<int> fds_to_ignore;
-  if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) {
+  if (!FillFileDescriptorVector(env, managed_fds_to_ignore, &fds_to_ignore, &error_msg)) {
     fail_fn(error_msg);
   }
-  if (gOpenFdTable == NULL) {
+
+  if (gOpenFdTable == nullptr) {
     gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg);
-    if (gOpenFdTable == NULL) {
+    if (gOpenFdTable == nullptr) {
       fail_fn(error_msg);
     }
   } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) {
@@ -975,7 +765,7 @@
     PreApplicationInit();
 
     // Clean up any descriptors which must be closed immediately
-    if (!DetachDescriptors(env, fdsToClose, &error_msg)) {
+    if (!DetachDescriptors(env, managed_fds_to_close, &error_msg)) {
       fail_fn(error_msg);
     }
 
@@ -993,9 +783,236 @@
   if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
     fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
   }
+
   return pid;
 }
 
+// Utility routine to specialize a zygote child process.
+static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
+                             jint runtime_flags, jobjectArray rlimits,
+                             jlong permitted_capabilities, jlong effective_capabilities,
+                             jint mount_external, jstring managed_se_info,
+                             jstring managed_nice_name, bool is_system_server,
+                             bool is_child_zygote, jstring managed_instruction_set,
+                             jstring managed_app_data_dir, jstring managed_package_name,
+                             jobjectArray managed_pacakges_for_uid,
+                             jobjectArray managed_visible_vol_ids) {
+  auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote",
+                           managed_nice_name, _1);
+  auto extract_fn = std::bind(ExtractJString, env, is_system_server ? "system_server" : "zygote",
+                              managed_nice_name, _1);
+
+  auto se_info = extract_fn(managed_se_info);
+  auto nice_name = extract_fn(managed_nice_name);
+  auto instruction_set = extract_fn(managed_instruction_set);
+  auto app_data_dir = extract_fn(managed_app_data_dir);
+  auto package_name = extract_fn(managed_package_name);
+
+  std::string error_msg;
+
+  // Keep capabilities across UID change, unless we're staying root.
+  if (uid != 0) {
+    if (!EnableKeepCapabilities(&error_msg)) {
+      fail_fn(error_msg);
+    }
+  }
+
+  if (!SetInheritable(permitted_capabilities, &error_msg)) {
+    fail_fn(error_msg);
+  }
+
+  if (!DropCapabilitiesBoundingSet(&error_msg)) {
+    fail_fn(error_msg);
+  }
+
+  bool use_native_bridge = !is_system_server &&
+                           instruction_set.has_value() &&
+                           android::NativeBridgeAvailable() &&
+                           android::NeedsNativeBridge(instruction_set.value().c_str());
+
+  if (use_native_bridge && !app_data_dir.has_value()) {
+    // The app_data_dir variable should never be empty if we need to use a
+    // native bridge.  In general, app_data_dir will never be empty for normal
+    // applications.  It can only happen in special cases (for isolated
+    // processes which are not associated with any app).  These are launched by
+    // the framework and should not be emulated anyway.
+    use_native_bridge = false;
+    ALOGW("Native bridge will not be used because managed_app_data_dir == nullptr.");
+  }
+
+  if (!package_name.has_value()) {
+    if (is_system_server) {
+      package_name.emplace("android");
+    } else {
+      package_name.emplace("");
+    }
+  }
+
+  std::vector<std::string> packages_for_uid;
+  if (managed_pacakges_for_uid != nullptr) {
+    jsize count = env->GetArrayLength(managed_pacakges_for_uid);
+    for (jsize package_index = 0; package_index < count; ++package_index) {
+      jstring managed_package_for_uid =
+          (jstring) env->GetObjectArrayElement(managed_pacakges_for_uid, package_index);
+
+      auto package_for_uid = extract_fn(managed_package_for_uid);
+      if (LIKELY(package_for_uid.has_value())) {
+        packages_for_uid.emplace_back(std::move(package_for_uid.value()));
+      } else {
+        fail_fn("Null string found in managed packages_for_uid.");
+      }
+    }
+  }
+
+  std::vector<std::string> visible_vol_ids;
+  if (managed_visible_vol_ids != nullptr) {
+    jsize count = env->GetArrayLength(managed_visible_vol_ids);
+    for (jsize vol_id_index = 0; vol_id_index < count; ++vol_id_index) {
+      jstring managed_visible_vol_id =
+          (jstring) env->GetObjectArrayElement(managed_visible_vol_ids, vol_id_index);
+
+      auto visible_vol_id = extract_fn(managed_visible_vol_id);
+      if (LIKELY(visible_vol_id.has_value())) {
+        visible_vol_ids.emplace_back(std::move(visible_vol_id.value()));
+      } else {
+        fail_fn("Null string found in managed visible_vol_ids.");
+      }
+    }
+  }
+
+  if (!MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg,
+                            package_name.value(), packages_for_uid, visible_vol_ids)) {
+    ALOGW("Failed to mount emulated storage: %s (%s)", error_msg.c_str(), strerror(errno));
+    if (errno == ENOTCONN || errno == EROFS) {
+      // When device is actively encrypting, we get ENOTCONN here
+      // since FUSE was mounted before the framework restarted.
+      // When encrypted device is booting, we get EROFS since
+      // FUSE hasn't been created yet by init.
+      // In either case, continue without external storage.
+    } else {
+      fail_fn(error_msg);
+    }
+  }
+
+  // If this zygote isn't root, it won't be able to create a process group,
+  // since the directory is owned by root.
+  if (!is_system_server && getuid() == 0) {
+    int rc = createProcessGroup(uid, getpid());
+    if (rc == -EROFS) {
+      ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
+    } else if (rc != 0) {
+      ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc));
+    }
+  }
+
+  if (!SetGids(env, gids, &error_msg)) {
+    fail_fn(error_msg);
+  }
+
+  if (!SetRLimits(env, rlimits, &error_msg)) {
+    fail_fn(error_msg);
+  }
+
+  if (use_native_bridge) {
+    // Due to the logic behind use_native_bridge we know that both app_data_dir
+    // and instruction_set contain values.
+    android::PreInitializeNativeBridge(app_data_dir.value().c_str(),
+                                       instruction_set.value().c_str());
+  }
+
+  if (setresgid(gid, gid, gid) == -1) {
+    fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno)));
+  }
+
+  // Must be called when the new process still has CAP_SYS_ADMIN, in this case,
+  // before changing uid from 0, which clears capabilities.  The other
+  // alternative is to call prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that
+  // breaks SELinux domain transition (see b/71859146).  As the result,
+  // privileged syscalls used below still need to be accessible in app process.
+  SetUpSeccompFilter(uid);
+
+  if (setresuid(uid, uid, uid) == -1) {
+    fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno)));
+  }
+
+  // The "dumpable" flag of a process, which controls core dump generation, is
+  // overwritten by the value in /proc/sys/fs/suid_dumpable when the effective
+  // user or group ID changes. See proc(5) for possible values. In most cases,
+  // the value is 0, so core dumps are disabled for zygote children. However,
+  // when running in a Chrome OS container, the value is already set to 2,
+  // which allows the external crash reporter to collect all core dumps. Since
+  // only system crashes are interested, core dump is disabled for app
+  // processes. This also ensures compliance with CTS.
+  int dumpable = prctl(PR_GET_DUMPABLE);
+  if (dumpable == -1) {
+    ALOGE("prctl(PR_GET_DUMPABLE) failed: %s", strerror(errno));
+    RuntimeAbort(env, __LINE__, "prctl(PR_GET_DUMPABLE) failed");
+  }
+
+  if (dumpable == 2 && uid >= AID_APP) {
+    if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) {
+      ALOGE("prctl(PR_SET_DUMPABLE, 0) failed: %s", strerror(errno));
+      RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 0) failed");
+    }
+  }
+
+  if (NeedsNoRandomizeWorkaround()) {
+    // Work around ARM kernel ASLR lossage (http://b/5817320).
+    int old_personality = personality(0xffffffff);
+    int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
+    if (new_personality == -1) {
+      ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
+    }
+  }
+
+  if (!SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities,
+                       &error_msg)) {
+    fail_fn(error_msg);
+  }
+
+  if (!SetSchedulerPolicy(&error_msg)) {
+    fail_fn(error_msg);
+  }
+
+  const char* se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr;
+  const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr;
+
+  if (selinux_android_setcontext(uid, is_system_server, se_info_ptr, nice_name_ptr) == -1) {
+    fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed",
+                         uid, is_system_server, se_info_ptr, nice_name_ptr));
+  }
+
+  // Make it easier to debug audit logs by setting the main thread's name to the
+  // nice name rather than "app_process".
+  if (nice_name.has_value()) {
+    SetThreadName(nice_name.value().c_str());
+  } else if (is_system_server) {
+    SetThreadName("system_server");
+  }
+
+  // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
+  UnsetChldSignalHandler();
+
+  if (is_system_server) {
+    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks);
+    if (env->ExceptionCheck()) {
+      fail_fn("Error calling post fork system server hooks.");
+    }
+    // TODO(oth): Remove hardcoded label here (b/117874058).
+    static const char* kSystemServerLabel = "u:r:system_server:s0";
+    if (selinux_android_setcon(kSystemServerLabel) != 0) {
+      fail_fn(CREATE_ERROR("selinux_android_setcon(%s)", kSystemServerLabel));
+    }
+  }
+
+  env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
+                            is_system_server, is_child_zygote, managed_instruction_set);
+
+  if (env->ExceptionCheck()) {
+    fail_fn("Error calling post fork hooks.");
+  }
+}
+
 static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) {
     __user_cap_header_struct capheader;
     memset(&capheader, 0, sizeof(capheader));
@@ -1008,16 +1025,82 @@
         RuntimeAbort(env, __LINE__, "capget failed");
     }
 
-    return capdata[0].effective |
-           (static_cast<uint64_t>(capdata[1].effective) << 32);
+    return capdata[0].effective | (static_cast<uint64_t>(capdata[1].effective) << 32);
+}
+
+static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gids,
+                                   bool is_child_zygote) {
+  jlong capabilities = 0;
+
+  /*
+   *  Grant the following capabilities to the Bluetooth user:
+   *    - CAP_WAKE_ALARM
+   *    - CAP_NET_RAW
+   *    - CAP_NET_BIND_SERVICE (for DHCP client functionality)
+   *    - CAP_SYS_NICE (for setting RT priority for audio-related threads)
+   */
+
+  if (multiuser_get_app_id(uid) == AID_BLUETOOTH) {
+    capabilities |= (1LL << CAP_WAKE_ALARM);
+    capabilities |= (1LL << CAP_NET_RAW);
+    capabilities |= (1LL << CAP_NET_BIND_SERVICE);
+    capabilities |= (1LL << CAP_SYS_NICE);
+  }
+
+  /*
+   * Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock"
+   */
+
+  bool gid_wakelock_found = false;
+  if (gid == AID_WAKELOCK) {
+    gid_wakelock_found = true;
+  } else if (gids != nullptr) {
+    jsize gids_num = env->GetArrayLength(gids);
+    ScopedIntArrayRO native_gid_proxy(env, gids);
+
+    if (native_gid_proxy.get() == nullptr) {
+      RuntimeAbort(env, __LINE__, "Bad gids array");
+    }
+
+    for (int gid_index = gids_num; --gids_num >= 0;) {
+      if (native_gid_proxy[gid_index] == AID_WAKELOCK) {
+        gid_wakelock_found = true;
+        break;
+      }
+    }
+  }
+
+  if (gid_wakelock_found) {
+    capabilities |= (1LL << CAP_BLOCK_SUSPEND);
+  }
+
+  /*
+   * Grant child Zygote processes the following capabilities:
+   *   - CAP_SETUID (change UID of child processes)
+   *   - CAP_SETGID (change GID of child processes)
+   *   - CAP_SETPCAP (change capabilities of child processes)
+   */
+
+  if (is_child_zygote) {
+    capabilities |= (1LL << CAP_SETUID);
+    capabilities |= (1LL << CAP_SETGID);
+    capabilities |= (1LL << CAP_SETPCAP);
+  }
+
+  /*
+   * Containers run without some capabilities, so drop any caps that are not
+   * available.
+   */
+
+  return capabilities & GetEffectiveCapabilityMask(env);
 }
 }  // anonymous namespace
 
 namespace android {
 
 static void com_android_internal_os_Zygote_nativeSecurityInit(JNIEnv*, jclass) {
-  // security_getenforce is not allowed on app process. Initialize and cache the value before
-  // zygote forks.
+  // security_getenforce is not allowed on app process. Initialize and cache
+  // the value before zygote forks.
   g_is_security_enforced = security_getenforce();
 }
 
@@ -1028,78 +1111,35 @@
 static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
         JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
         jint runtime_flags, jobjectArray rlimits,
-        jint mount_external, jstring se_info, jstring se_name,
-        jintArray fdsToClose, jintArray fdsToIgnore, jboolean is_child_zygote,
-        jstring instructionSet, jstring appDataDir, jstring packageName,
-        jobjectArray packagesForUid, jobjectArray visibleVolIds) {
-    jlong capabilities = 0;
+        jint mount_external, jstring se_info, jstring nice_name,
+        jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote,
+        jstring instruction_set, jstring app_data_dir, jstring package_name,
+        jobjectArray packages_for_uid, jobjectArray visible_vol_ids) {
+    jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
 
-    // Grant CAP_WAKE_ALARM to the Bluetooth process.
-    // Additionally, allow bluetooth to open packet sockets so it can start the DHCP client.
-    // Grant CAP_SYS_NICE to allow Bluetooth to set RT priority for
-    // audio-related threads.
-    // TODO: consider making such functionality an RPC to netd.
-    if (multiuser_get_app_id(uid) == AID_BLUETOOTH) {
-      capabilities |= (1LL << CAP_WAKE_ALARM);
-      capabilities |= (1LL << CAP_NET_RAW);
-      capabilities |= (1LL << CAP_NET_BIND_SERVICE);
-      capabilities |= (1LL << CAP_SYS_NICE);
-    }
-
-    // Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock"
-    bool gid_wakelock_found = false;
-    if (gid == AID_WAKELOCK) {
-      gid_wakelock_found = true;
-    } else if (gids != NULL) {
-      jsize gids_num = env->GetArrayLength(gids);
-      ScopedIntArrayRO ar(env, gids);
-      if (ar.get() == NULL) {
-        RuntimeAbort(env, __LINE__, "Bad gids array");
-      }
-      for (int i = 0; i < gids_num; i++) {
-        if (ar[i] == AID_WAKELOCK) {
-          gid_wakelock_found = true;
-          break;
-        }
-      }
-    }
-    if (gid_wakelock_found) {
-      capabilities |= (1LL << CAP_BLOCK_SUSPEND);
-    }
-
-    // If forking a child zygote process, that zygote will need to be able to change
-    // the UID and GID of processes it forks, as well as drop those capabilities.
-    if (is_child_zygote) {
-      capabilities |= (1LL << CAP_SETUID);
-      capabilities |= (1LL << CAP_SETGID);
-      capabilities |= (1LL << CAP_SETPCAP);
-    }
-
-    // Containers run without some capabilities, so drop any caps that are not
-    // available.
-    capabilities &= GetEffectiveCapabilityMask(env);
-
-    pid_t pid = ForkCommon(env, se_name, false, fdsToClose, fdsToIgnore);
+    pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore);
     if (pid == 0) {
       SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                        capabilities, capabilities,
-                       mount_external, se_info, se_name, false,
-                       is_child_zygote == JNI_TRUE, instructionSet, appDataDir, packageName,
-                       packagesForUid, visibleVolIds);
+                       mount_external, se_info, nice_name, false,
+                       is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
+                       package_name, packages_for_uid, visible_vol_ids);
     }
     return pid;
 }
 
 static jint com_android_internal_os_Zygote_nativeForkSystemServer(
         JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
-        jint runtime_flags, jobjectArray rlimits, jlong permittedCapabilities,
-        jlong effectiveCapabilities) {
-  pid_t pid = ForkCommon(env, NULL, true, NULL, NULL);
+        jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,
+        jlong effective_capabilities) {
+  pid_t pid = ForkCommon(env, true,
+                         /* managed_fds_to_close= */ nullptr,
+                         /* managed_fds_to_ignore= */ nullptr);
   if (pid == 0) {
       SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
-                       permittedCapabilities, effectiveCapabilities,
-                       MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true,
-                       false, NULL, NULL, nullptr, nullptr, nullptr);
+                       permitted_capabilities, effective_capabilities,
+                       MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
+                       false, nullptr, nullptr, nullptr, nullptr, nullptr);
   } else if (pid > 0) {
       // The zygote process checks whether the child process has died or not.
       ALOGI("System server process %d has been created", pid);
@@ -1133,7 +1173,7 @@
     ScopedUtfChars path_native(env, path);
     const char* path_cstr = path_native.c_str();
     if (!path_cstr) {
-        RuntimeAbort(env, __LINE__, "path_cstr == NULL");
+        RuntimeAbort(env, __LINE__, "path_cstr == nullptr");
     }
     FileDescriptorWhitelist::Get()->Allow(path_cstr);
 }
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index 258a55c..ac0e600 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -16,21 +16,58 @@
 
 #define LOG_TAG "Zygote"
 
+#include <EGL/egl.h>
 #include <ui/GraphicBufferMapper.h>
 
 #include "core_jni_helpers.h"
 
 namespace {
 
+// Shadow call stack (SCS) is a security mitigation that uses a separate stack
+// (the SCS) for return addresses. In versions of Android newer than P, the
+// compiler cooperates with the system to ensure that the SCS address is always
+// stored in register x18, as long as the app was compiled with a new enough
+// compiler and does not use features that rely on SP-HALs (this restriction is
+// because the SP-HALs might not preserve x18 due to potentially having been
+// compiled with an old compiler as a consequence of Treble; it generally means
+// that the app must be a system app without a UI). This struct is used to
+// temporarily store the address on the stack while preloading the SP-HALs, so
+// that such apps can use the same zygote as everything else.
+struct ScopedSCSExit {
+#ifdef __aarch64__
+    void* scs;
+
+    ScopedSCSExit() {
+        __asm__ __volatile__("str x18, [%0]" ::"r"(&scs));
+    }
+
+    ~ScopedSCSExit() {
+        __asm__ __volatile__("ldr x18, [%0]; str xzr, [%0]" ::"r"(&scs));
+    }
+#else
+    // Silence unused variable warnings in non-SCS builds.
+    ScopedSCSExit() {}
+    ~ScopedSCSExit() {}
+#endif
+};
+
 void android_internal_os_ZygoteInit_nativePreloadAppProcessHALs(JNIEnv* env, jclass) {
+    ScopedSCSExit x;
     android::GraphicBufferMapper::preloadHal();
     // Add preloading here for other HALs that are (a) always passthrough, and
     // (b) loaded by most app processes.
 }
 
+void android_internal_os_ZygoteInit_nativePreloadOpenGL(JNIEnv* env, jclass) {
+    ScopedSCSExit x;
+    eglGetDisplay(EGL_DEFAULT_DISPLAY);
+}
+
 const JNINativeMethod gMethods[] = {
     { "nativePreloadAppProcessHALs", "()V",
       (void*)android_internal_os_ZygoteInit_nativePreloadAppProcessHALs },
+    { "nativePreloadOpenGL", "()V",
+      (void*)android_internal_os_ZygoteInit_nativePreloadOpenGL },
 };
 
 }  // anonymous namespace
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 2465759..a398e49 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -85,7 +85,7 @@
   // See AssetManager.cpp for more details on overlay-subdir.
   static const char* kOverlayDir = "/system/vendor/overlay/";
   static const char* kVendorOverlayDir = "/vendor/overlay";
-  static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
+  static const char* kVendorOverlaySubdir = "/system/vendor/overlay-subdir/";
   static const char* kSystemProductOverlayDir = "/system/product/overlay/";
   static const char* kProductOverlayDir = "/product/overlay";
   static const char* kSystemProductServicesOverlayDir = "/system/product_services/overlay/";
@@ -93,7 +93,7 @@
   static const char* kApkSuffix = ".apk";
 
   if ((android::base::StartsWith(path, kOverlayDir)
-       || android::base::StartsWith(path, kOverlaySubdir)
+       || android::base::StartsWith(path, kVendorOverlaySubdir)
        || android::base::StartsWith(path, kVendorOverlayDir)
        || android::base::StartsWith(path, kSystemProductOverlayDir)
        || android::base::StartsWith(path, kProductOverlayDir)
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index 2ace1ac..480b1ea 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -11,6 +11,9 @@
 yaochen@google.com
 yro@google.com
 
+# Settings UI
+per-file settings_enums.proto=zhfan@google.com
+
 # Frameworks
 ogunwale@google.com
 jjaggi@google.com
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 5433393..3a908dc 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -64,5 +64,8 @@
 
     // OPEN: Biometric Enrollment (android.settings.BIOMETRIC_ENROLL action intent)
     BIOMETRIC_ENROLL_ACTIVITY = 1586;
+
+    // OPEN: Settings > Privacy
+    TOP_LEVEL_PRIVACY = 1587;
 }
 
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 8f28970..0b9e347 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -26,6 +26,7 @@
 import "frameworks/base/core/proto/android/os/pagetypeinfo.proto";
 import "frameworks/base/core/proto/android/os/procrank.proto";
 import "frameworks/base/core/proto/android/os/ps.proto";
+import "frameworks/base/core/proto/android/os/statsdata.proto";
 import "frameworks/base/core/proto/android/os/system_properties.proto";
 import "frameworks/base/core/proto/android/providers/settings.proto";
 import "frameworks/base/core/proto/android/server/activitymanagerservice.proto";
@@ -301,6 +302,12 @@
         (section).userdebug_and_eng_only = true
     ];
 
+    optional android.os.StatsDataDumpProto stats_data = 3023 [
+        (section).type = SECTION_DUMPSYS,
+        (section).args = "stats --proto",
+        (section).userdebug_and_eng_only = true
+    ];
+
     // Reserved for OEMs.
     extensions 50000 to 100000;
 }
diff --git a/core/proto/android/os/statsdata.proto b/core/proto/android/os/statsdata.proto
new file mode 100644
index 0000000..25d76b8
--- /dev/null
+++ b/core/proto/android/os/statsdata.proto
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+option java_multiple_files = true;
+
+package android.os;
+
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+// Dump of statsd report data (dumpsys stats --proto).
+message StatsDataDumpProto {
+    option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    // The following is an android.os.statsd.ConfigMetricsReportList, which is defined
+    // in frameworks/base/cmds/statsd/src/stats_log.proto. It should not be imported (even weakly)
+    // in AOSP because it would drag with it atoms.proto, which is enormous and awkward.
+    repeated bytes config_metrics_report_list = 1;
+
+}
\ No newline at end of file
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 3072977..7de8020 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -270,6 +270,7 @@
         optional SettingProto enable_freeform_windows_support = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto force_rtl = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
         optional SettingProto emulate_display_cutout = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        optional SettingProto force_desktop_mode_on_external_displays = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
     }
     optional Development development = 39;
 
@@ -331,6 +332,18 @@
     }
     optional Dropbox dropbox = 46;
 
+    message DynamicPowerSavings {
+        option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+        // When to auto disable interventions that were triggered due to
+        // {@link #DYNAMIC_POWER_SAVINGS_ENABLED}. Value is a percentage indicating
+        // a battery level.
+        optional SettingProto disable_threshold = 1 [ (android.privacy).dest = DEST_AUTOMATIC];
+        // Whether dynamic power savings based behaviors should be running or not.
+        optional SettingProto enabled = 2 [ (android.privacy).dest = DEST_AUTOMATIC];
+    }
+    optional DynamicPowerSavings dynamic_power_savings = 143;
+
     message Emergency {
         option (android.msg_privacy).dest = DEST_EXPLICIT;
 
@@ -404,6 +417,9 @@
         // Ordered GPU debug layer list for GLES
         // i.e. <layer1>:<layer2>:...:<layerN>
         optional SettingProto debug_layers_gles = 5;
+        // App opt in to load updated graphics driver instead of
+        // native graphcis driver through developer options.
+        optional SettingProto updated_gfx_driver_dev_opt_in_app = 6;
     }
     optional Gpu gpu = 59;
 
@@ -487,6 +503,9 @@
         // The max value for {@link #LOW_POWER_MODE_TRIGGER_LEVEL}. If this setting
         // is not set or the value is 0, the default max will be used.
         optional SettingProto trigger_level_max = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+        // Whether automatic battery saver mode is controlled via percentage,
+        // {@link #DYNAMIC_POWER_SAVINGS_ENABLED} or disabled.
+        optional SettingProto automatic_power_saver_mode = 4 [ (android.privacy).dest = DEST_AUTOMATIC];
     }
     optional LowPowerMode low_power_mode = 70;
 
@@ -725,8 +744,10 @@
     optional SettingProto set_install_location = 103 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto shortcut_manager_constants = 104;
     optional SettingProto show_first_crash_dialog = 105 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_hidden_launcher_icon_apps_enabled = 141 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto show_restart_in_crash_dialog = 106 [ (android.privacy).dest = DEST_AUTOMATIC ];
     optional SettingProto show_mute_in_crash_dialog = 107 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    optional SettingProto show_new_app_installed_notification_enabled = 142 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
     message SmartSelection {
         option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -966,5 +987,5 @@
 
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 141;
+    // Next tag = 144;
 }
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 3ead633..6e661e1 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -72,9 +72,6 @@
         // List of the accessibility services to which the user has granted
         // permission to put the device into touch exploration mode.
         optional SettingProto touch_exploration_granted_accessibility_services = 31;
-        optional SettingProto minimum_ui_timeout_enabled = 32 [ (android.privacy).dest = DEST_AUTOMATIC ];
-        optional SettingProto minimum_ui_timeout_ms = 33 [ (android.privacy).dest = DEST_AUTOMATIC ];
-
     }
     optional Accessibility accessibility = 2;
 
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 54f0934..e83a2bf 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -609,6 +609,17 @@
     repeated Constraint unsatisfied_constraints = 9;
     optional bool is_doze_whitelisted = 10;
 
+    message ImplicitConstraints {
+        // The device isn't Dozing or this job will be in the foreground. This
+        // implicit constraint must be satisfied for the job to run.
+        optional bool is_not_dozing = 1;
+        // The job is not restricted from running in the background (due to
+        // Battery Saver). This implicit constraint must be satisfied for the
+        // job to run.
+        optional bool is_not_restricted_in_bg = 2;
+    }
+    optional ImplicitConstraints implicit_constraints = 25;
+
     enum TrackingController {
         TRACKING_BATTERY = 0;
         TRACKING_CONNECTIVITY = 1;
@@ -662,4 +673,6 @@
     optional int64 last_failed_run_time = 23;
 
     optional int64 internal_flags = 24;
+
+    // Next tag: 26
 }
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/core/proto/android/server/location/enums.proto
similarity index 60%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to core/proto/android/server/location/enums.proto
index ede8695..b6dc589 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/core/proto/android/server/location/enums.proto
@@ -14,8 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+syntax = "proto2";
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+package android.server.location;
+
+option java_outer_classname = "ServerLocationProtoEnums";
+option java_multiple_files = true;
+
+// GPS Signal Quality levels,
+// primarily used by location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+enum GpsSignalQualityEnum {
+    GPS_SIGNAL_QUALITY_UNKNOWN = -1;
+    GPS_SIGNAL_QUALITY_POOR = 0;
+    GPS_SIGNAL_QUALITY_GOOD = 1;
+}
diff --git a/core/proto/android/server/usagestatsservice.proto b/core/proto/android/server/usagestatsservice.proto
index 941c81f..3d60a86 100644
--- a/core/proto/android/server/usagestatsservice.proto
+++ b/core/proto/android/server/usagestatsservice.proto
@@ -45,11 +45,15 @@
     optional string package = 1;
     // package_index contains the index + 1 of the package name in the string pool
     optional int32 package_index = 2;
+    // Time attributes stored as an offset of the IntervalStats's beginTime.
     optional int64 last_time_active_ms = 3;
     optional int64 total_time_active_ms = 4;
     optional int32 last_event = 5;
     optional int32 app_launch_count = 6;
     repeated ChooserAction chooser_actions = 7;
+    // Time attributes stored as an offset of the IntervalStats's beginTime.
+    optional int64 last_time_service_used_ms = 8;
+    optional int64 total_time_service_used_ms = 9;
   }
 
   // Stores the relevant information an IntervalStats will have about a Configuration
@@ -86,6 +90,8 @@
   // stringpool contains all the package and class names used by UsageStats and Event
   // They will hold a number that is equal to the index + 1 of their string in the pool
   optional StringPool stringpool = 2;
+  optional int32 major_version = 3;
+  optional int32 minor_version = 4;
 
   // The following fields contain aggregated usage stats data
   optional CountAndTime interactive = 10;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 093a860..5f4bc7f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -359,6 +359,7 @@
     <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST" />
     <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION" />
     <protected-broadcast android:name="android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW" />
+    <protected-broadcast android:name="android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION" />
     <protected-broadcast android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
     <protected-broadcast android:name="android.net.wifi.supplicant.STATE_CHANGE" />
     <protected-broadcast android:name="android.net.wifi.p2p.STATE_CHANGED" />
@@ -642,7 +643,6 @@
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CONTACTS"
-        android:permissionGroup="android.permission-group.CONTACTS"
         android:label="@string/permlab_readContacts"
         android:description="@string/permdesc_readContacts"
         android:protectionLevel="dangerous" />
@@ -651,7 +651,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_CONTACTS"
-        android:permissionGroup="android.permission-group.CONTACTS"
         android:label="@string/permlab_writeContacts"
         android:description="@string/permdesc_writeContacts"
         android:protectionLevel="dangerous" />
@@ -673,7 +672,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CALENDAR"
-        android:permissionGroup="android.permission-group.CALENDAR"
         android:label="@string/permlab_readCalendar"
         android:description="@string/permdesc_readCalendar"
         android:protectionLevel="dangerous" />
@@ -682,7 +680,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_CALENDAR"
-        android:permissionGroup="android.permission-group.CALENDAR"
         android:label="@string/permlab_writeCalendar"
         android:description="@string/permdesc_writeCalendar"
         android:protectionLevel="dangerous" />
@@ -704,7 +701,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.SEND_SMS"
-        android:permissionGroup="android.permission-group.SMS"
         android:label="@string/permlab_sendSms"
         android:description="@string/permdesc_sendSms"
         android:permissionFlags="costsMoney"
@@ -714,7 +710,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECEIVE_SMS"
-        android:permissionGroup="android.permission-group.SMS"
         android:label="@string/permlab_receiveSms"
         android:description="@string/permdesc_receiveSms"
         android:protectionLevel="dangerous"/>
@@ -723,7 +718,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_SMS"
-        android:permissionGroup="android.permission-group.SMS"
         android:label="@string/permlab_readSms"
         android:description="@string/permdesc_readSms"
         android:protectionLevel="dangerous" />
@@ -732,7 +726,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECEIVE_WAP_PUSH"
-        android:permissionGroup="android.permission-group.SMS"
         android:label="@string/permlab_receiveWapPush"
         android:description="@string/permdesc_receiveWapPush"
         android:protectionLevel="dangerous" />
@@ -741,12 +734,11 @@
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECEIVE_MMS"
-        android:permissionGroup="android.permission-group.SMS"
         android:label="@string/permlab_receiveMms"
         android:description="@string/permdesc_receiveMms"
         android:protectionLevel="dangerous" />
 
-    <!-- @TestApi Allows an application to read previously received cell broadcast
+    <!-- @SystemApi @TestApi Allows an application to read previously received cell broadcast
          messages and to register a content observer to get notifications when
          a cell broadcast has been received and added to the database. For
          emergency alerts, the database is updated immediately after the
@@ -759,7 +751,6 @@
          <p>Protection level: dangerous
          @hide Pending API council approval -->
     <permission android:name="android.permission.READ_CELL_BROADCASTS"
-        android:permissionGroup="android.permission-group.SMS"
         android:label="@string/permlab_readCellBroadcasts"
         android:description="@string/permdesc_readCellBroadcasts"
         android:protectionLevel="dangerous" />
@@ -801,7 +792,6 @@
      @deprecated replaced by new strongly-typed permission groups in Q.
      -->
     <permission android:name="android.permission.READ_EXTERNAL_STORAGE"
-        android:permissionGroup="android.permission-group.STORAGE"
         android:label="@string/permlab_sdcardRead"
         android:description="@string/permdesc_sdcardRead"
         android:protectionLevel="normal" />
@@ -822,7 +812,6 @@
          @deprecated replaced by new strongly-typed permission groups in Q.
     -->
     <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
-        android:permissionGroup="android.permission-group.STORAGE"
         android:label="@string/permlab_sdcardWrite"
         android:description="@string/permdesc_sdcardWrite"
         android:protectionLevel="normal" />
@@ -838,14 +827,12 @@
 
     <!-- Allows an application to read the user's shared audio collection. -->
     <permission android:name="android.permission.READ_MEDIA_AUDIO"
-        android:permissionGroup="android.permission-group.MEDIA_AURAL"
         android:label="@string/permlab_audioRead"
         android:description="@string/permdesc_audioRead"
         android:protectionLevel="dangerous" />
 
     <!-- Allows an application to modify the user's shared audio collection. -->
     <permission android:name="android.permission.WRITE_MEDIA_AUDIO"
-        android:permissionGroup="android.permission-group.MEDIA_AURAL"
         android:label="@string/permlab_audioWrite"
         android:description="@string/permdesc_audioWrite"
         android:protectionLevel="dangerous" />
@@ -861,28 +848,24 @@
 
     <!-- Allows an application to read the user's shared images collection. -->
     <permission android:name="android.permission.READ_MEDIA_IMAGES"
-        android:permissionGroup="android.permission-group.MEDIA_VISUAL"
         android:label="@string/permlab_imagesRead"
         android:description="@string/permdesc_imagesRead"
         android:protectionLevel="dangerous" />
 
     <!-- Allows an application to modify the user's shared images collection. -->
     <permission android:name="android.permission.WRITE_MEDIA_IMAGES"
-        android:permissionGroup="android.permission-group.MEDIA_VISUAL"
         android:label="@string/permlab_imagesWrite"
         android:description="@string/permdesc_imagesWrite"
         android:protectionLevel="dangerous" />
 
     <!-- Allows an application to read the user's shared video collection. -->
     <permission android:name="android.permission.READ_MEDIA_VIDEO"
-        android:permissionGroup="android.permission-group.MEDIA_VISUAL"
         android:label="@string/permlab_videoRead"
         android:description="@string/permdesc_videoRead"
         android:protectionLevel="dangerous" />
 
     <!-- Allows an application to modify the user's shared video collection. -->
     <permission android:name="android.permission.WRITE_MEDIA_VIDEO"
-        android:permissionGroup="android.permission-group.MEDIA_VISUAL"
         android:label="@string/permlab_videoWrite"
         android:description="@string/permdesc_videoWrite"
         android:protectionLevel="dangerous" />
@@ -890,7 +873,6 @@
     <!-- Allows an application to access any geographic locations persisted in the
          user's shared collection. -->
     <permission android:name="android.permission.ACCESS_MEDIA_LOCATION"
-        android:permissionGroup="android.permission-group.MEDIA_VISUAL"
         android:label="@string/permlab_mediaLocation"
         android:description="@string/permdesc_mediaLocation"
         android:protectionLevel="dangerous" />
@@ -921,7 +903,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_FINE_LOCATION"
-        android:permissionGroup="android.permission-group.LOCATION"
         android:label="@string/permlab_accessFineLocation"
         android:description="@string/permdesc_accessFineLocation"
         android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION"
@@ -932,7 +913,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_COARSE_LOCATION"
-        android:permissionGroup="android.permission-group.LOCATION"
         android:label="@string/permlab_accessCoarseLocation"
         android:description="@string/permdesc_accessCoarseLocation"
         android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION"
@@ -945,7 +925,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
-        android:permissionGroup="android.permission-group.LOCATION"
         android:label="@string/permlab_accessBackgroundLocation"
         android:description="@string/permdesc_accessBackgroundLocation"
         android:protectionLevel="dangerous|instant" />
@@ -986,7 +965,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_CALL_LOG"
-        android:permissionGroup="android.permission-group.CALL_LOG"
         android:label="@string/permlab_readCallLog"
         android:description="@string/permdesc_readCallLog"
         android:protectionLevel="dangerous" />
@@ -1005,7 +983,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.WRITE_CALL_LOG"
-        android:permissionGroup="android.permission-group.CALL_LOG"
         android:label="@string/permlab_writeCallLog"
         android:description="@string/permdesc_writeCallLog"
         android:protectionLevel="dangerous" />
@@ -1016,7 +993,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
-        android:permissionGroup="android.permission-group.CALL_LOG"
         android:label="@string/permlab_processOutgoingCalls"
         android:description="@string/permdesc_processOutgoingCalls"
         android:protectionLevel="dangerous" />
@@ -1048,7 +1024,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.READ_PHONE_STATE"
-        android:permissionGroup="android.permission-group.PHONE"
         android:label="@string/permlab_readPhoneState"
         android:description="@string/permdesc_readPhoneState"
         android:protectionLevel="dangerous" />
@@ -1057,7 +1032,6 @@
          granted by {@link #READ_PHONE_STATE} but is exposed to instant applications.
          <p>Protection level: dangerous-->
     <permission android:name="android.permission.READ_PHONE_NUMBERS"
-        android:permissionGroup="android.permission-group.PHONE"
         android:label="@string/permlab_readPhoneNumbers"
         android:description="@string/permdesc_readPhoneNumbers"
         android:protectionLevel="dangerous|instant" />
@@ -1067,7 +1041,6 @@
         <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.CALL_PHONE"
-        android:permissionGroup="android.permission-group.PHONE"
         android:permissionFlags="costsMoney"
         android:label="@string/permlab_callPhone"
         android:description="@string/permdesc_callPhone"
@@ -1077,7 +1050,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"
-        android:permissionGroup="android.permission-group.PHONE"
         android:label="@string/permlab_addVoicemail"
         android:description="@string/permdesc_addVoicemail"
         android:protectionLevel="dangerous" />
@@ -1086,7 +1058,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.USE_SIP"
-        android:permissionGroup="android.permission-group.PHONE"
         android:description="@string/permdesc_use_sip"
         android:label="@string/permlab_use_sip"
         android:protectionLevel="dangerous"/>
@@ -1095,7 +1066,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ANSWER_PHONE_CALLS"
-        android:permissionGroup="android.permission-group.PHONE"
         android:label="@string/permlab_answerPhoneCalls"
         android:description="@string/permdesc_answerPhoneCalls"
         android:protectionLevel="dangerous|runtime" />
@@ -1123,7 +1093,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACCEPT_HANDOVER"
-                android:permissionGroup="android.permission-group.PHONE"
                 android.label="@string/permlab_acceptHandover"
                 android:description="@string/permdesc_acceptHandovers"
                 android:protectionLevel="dangerous" />
@@ -1147,7 +1116,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.RECORD_AUDIO"
-        android:permissionGroup="android.permission-group.MICROPHONE"
         android:label="@string/permlab_recordAudio"
         android:description="@string/permdesc_recordAudio"
         android:protectionLevel="dangerous|instant"/>
@@ -1169,7 +1137,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.ACTIVITY_RECOGNITION"
-        android:permissionGroup="android.permission-group.ACTIVITY_RECOGNITION"
         android:label="@string/permlab_activityRecognition"
         android:description="@string/permdesc_activityRecognition"
         android:protectionLevel="dangerous|instant" />
@@ -1218,7 +1185,6 @@
          <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.CAMERA"
-        android:permissionGroup="android.permission-group.CAMERA"
         android:label="@string/permlab_camera"
         android:description="@string/permdesc_camera"
         android:protectionLevel="dangerous|instant" />
@@ -1242,7 +1208,6 @@
          measure what is happening inside his/her body, such as heart rate.
          <p>Protection level: dangerous -->
     <permission android:name="android.permission.BODY_SENSORS"
-        android:permissionGroup="android.permission-group.SENSORS"
         android:label="@string/permlab_bodySensors"
         android:description="@string/permdesc_bodySensors"
         android:protectionLevel="dangerous" />
@@ -1721,7 +1686,6 @@
     <p>Protection level: dangerous
     -->
     <permission android:name="android.permission.GET_ACCOUNTS"
-        android:permissionGroup="android.permission-group.CONTACTS"
         android:protectionLevel="dangerous"
         android:description="@string/permdesc_getAccounts"
         android:label="@string/permlab_getAccounts" />
@@ -2211,6 +2175,12 @@
                 android:protectionLevel="signature" />
     <uses-permission android:name="android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS" />
 
+    <!-- Allows an application to start an activity as another app, provided that app has been
+         granted a permissionToken from the ActivityManagerService.
+         @hide -->
+    <permission android:name="android.permission.START_ACTIVITY_AS_CALLER"
+        android:protectionLevel="signature" />
+
     <!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
         API is no longer supported. -->
     <permission android:name="android.permission.RESTART_PACKAGES"
diff --git a/core/res/TEST_MAPPING b/core/res/TEST_MAPPING
new file mode 100644
index 0000000..1d22d782
--- /dev/null
+++ b/core/res/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+    "presubmit": [
+        {
+            "name": "CtsPermission2TestCases",
+            "options": [
+                {
+                    "include-filter": "android.permission2.cts.PermissionPolicyTest#testPlatformPermissionPolicyUnaltered"
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_notifications_alerted.xml b/core/res/res/drawable/ic_notifications_alerted.xml
new file mode 100644
index 0000000..4bfac37
--- /dev/null
+++ b/core/res/res/drawable/ic_notifications_alerted.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2018 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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M7.58 4.08L6.15 2.65C3.75 4.48 2.17 7.3 2.03 10.5h2c.15-2.65 1.51-4.97 3.55-6.42zm12.39 6.42h2c-.15-3.2-1.73-6.02-4.12-7.85l-1.42 1.43c2.02 1.45 3.39 3.77 3.54 6.42zM18 11c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2v-5zm-6 11c.14 0 .27-.01.4-.04.65-.14 1.18-.58 1.44-1.18.1-.24.15-.5.15-.78h-4c.01 1.1.9 2 2.01 2z"
+        android:fillColor="#FF000000" />
+</vector>
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 8b1f28b..433ae39 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -116,6 +116,19 @@
         android:contentDescription="@string/expand_button_content_description_collapsed"
         />
     <ImageView
+        android:id="@+id/alerted_icon"
+        android:layout_width="@dimen/notification_alerted_size"
+        android:layout_height="@dimen/notification_alerted_size"
+        android:layout_gravity="center"
+        android:layout_marginStart="4dp"
+        android:paddingTop="1dp"
+        android:scaleType="fitCenter"
+        android:visibility="gone"
+        android:contentDescription="@string/notification_alerted_content_description"
+        android:src="@drawable/ic_notifications_alerted"
+        android:tint="@color/notification_secondary_text_color_light"
+    />
+    <ImageView
         android:id="@+id/profile_badge"
         android:layout_width="@dimen/notification_badge_size"
         android:layout_height="@dimen/notification_badge_size"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 9ba991b..8afbf66 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g>-Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi-oproepe | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g>-VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Af"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Verkies Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Verkies mobiel"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Gee die program toegang tot ekstra liggingverskaffer-bevele. Dit kan die program dalk toelaat om in te meng met die werking van die GPS of ander liggingbronne."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"kry net op die voorgrond toegang tot presiese ligging"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Hierdie program kan jou presiese ligging kry net wanneer dit op die voorgrond is. Hierdie liggingdienste moet aangeskakel wees en op jou foon beskikbaar wees sodat die program hulle kan gebruik. Dit kan veroorsaak dat meer batterykrag gebruik word."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"verkry toegang tot benaderde ligging (netwerkgegrond)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Hierdie program kan jou ligging kry op grond van jou netwerkhulpbronne soos selfoontorings en Wi-Fi-netwerke. Hierdie liggingdienste moet aangeskakel en op jou tablet beskikbaar wees sodat die program hulle kan gebruik."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Hierdie program kan jou ligging kry op grond van jou netwerkhulpbronne soos selfoontorings en Wi-Fi-netwerke. Hierdie liggingdienste moet aangeskakel en op jou TV beskikbaar wees sodat die program hulle kan gebruik."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Hierdie program kan jou ligging kry op grond van jou netwerkhulpbronne soos selfoontorings en Wi-Fi-netwerke. Hierdie liggingdienste moet aangeskakel en op jou foon beskikbaar wees sodat die program hulle kan gebruik."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"kry benaderde ligging (netwerkgegrond) net op die voorgrond"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Hierdie program kan jou ligging kry op grond van netwerkhulpbronne soos selfoontorings en Wi-Fi-netwerke, maar net wanneer die program op die voorgrond is. Die program kan hierdie liggingdienste net gebruik as hulle aangeskakel is en op jou tablet beskikbaar is."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Hierdie program kan jou ligging kry op grond van netwerkhulpbronne soos selfoontorings en Wi-Fi-netwerke, maar net wanneer die program op die voorgrond is. Die program kan hierdie liggingdienste net gebruik as hulle aangeskakel is en op jou TV beskikbaar is."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Hierdie program kan jou ligging kry op grond van netwerkhulpbronne soos selfoontorings en Wi-Fi-netwerke, maar net wanneer die program op die voorgrond is. Die program kan hierdie liggingdienste net gebruik as hulle aangeskakel is en op jou foon beskikbaar is."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"kry ligging op die agtergrond"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"As dit bo en behalwe toegang tot die benaderde of presiese ligging verleen word, kan die program die ligging kry terwyl dit op die agtergrond werk."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"verander jou klankinstellings"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS-versoek is na USSD-versoek toe verander"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Na nuwe SS-versoek toe verander"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Werkprofiel"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Vou uit"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Vou in"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"wissel uitvou-aksie"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 5b2286b..b9be6af 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"የWiFi ጥሪ አደራረግ | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ጠፍቷል"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi ተመርጧል"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"የተንቀሳቃሽ ስልክ ተመራጭ ነው"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"መተግበሪያው ተጨማሪ የአካባቢ አቅራቢ ትእዛዞችን እንዲደርስ ይፈቅድለታል። ይሄ መተግበሪያው በጂፒኤስ ወይም ሌላ የአካባቢ ምንጮች ስራ ላይ ጣልቃ እንዲገባ ሊፈቅድለት ይችላል።"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"መዳረሻ ከፊት ለፊት ብቻ ትክክለኛ ነው"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"ይህ መተግበሪያ ከፊት ላይ ሆኖ ሲበራ ብቻ ትክክለኛውን መገኛ አካባቢ ማግኘት ይችላል። እነዚህ የመገኛ አካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ ስልክ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ግምታዊ አካባቢን መድረስ (በአውታረ መረብ ላይ የተመሰረተ)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ይህ መተግበሪያ እንደ የሕዋስ ማማዎች እና የWi-Fi አውታረ መረቦች ከመሳሰሉ የአውታረ መረብ ምንጮች ላይ በመመርኮዝ የእርስዎን መገኛ አካባቢ ማግኘት ይችላል። እነዚህ የመገኛ አካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ ጡባዊ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ይህ መተግበሪያ እንደ የሕዋስ ማማዎች እና የWi-Fi አውታረ መረቦች ከመሳሰሉ የአውታረ መረብ ምንጮች ላይ በመመርኮዝ የእርስዎን መገኛ አካባቢ ማግኘት ይችላል። እነዚህ የመገኛ አካባቢ አገልግሎቶች እርስዎ መጠቀም እንዲችሉ ሊበሩ እና በእርስዎ ቴሌቪዥን ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ይህ መተግበሪያ እንደ የሕዋስ ማማዎች እና የWi-Fi አውታረ መረቦች ከመሳሰሉ የአውታረ መረብ ምንጮች ላይ በመመርኮዝ የእርስዎን መገኛ አካባቢ ማግኘት ይችላል። እነዚህ የመገኛ አካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ ስልክ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"ግምታዊ አካባቢ (በአውታረ መረብ ላይ የተመሠረተ) ከፊት ላይ ሲሆን ብቻ መድረስ"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"ይህ መተግበሪያ እንደ የሕዋስ ማማዎች እና የWi-Fi አውታረ መረቦች ባሉ የአውታረ መረብ ምንጮች ላይ በመመስረት የእርስዎን አካባቢ ማግኘት ይችላል፣ ነገር ግን መተግበሪያው ከፊት ሲሆን ብቻ። እነዚህ የአካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ ጡባዊ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"ይህ መተግበሪያ እንደ የሕዋስ ማማዎች እና የWi-Fi አውታረ መረቦች ባሉ የአውታረ መረብ ምንጮች ላይ በመመስረት የእርስዎን አካባቢ ማግኘት ይችላል፣ ነገር ግን መተግበሪያው ከፊት ሲሆን ብቻ። እነዚህ የአካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ ቴሌቪዥን ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"ይህ መተግበሪያ እንደ የሕዋስ ማማዎች እና የWi-Fi አውታረ መረቦች ባሉ የአውታረ መረብ ምንጮች ላይ በመመስረት የእርስዎን አካባቢ ማግኘት ይችላል፣ ነገር ግን መተግበሪያው ከፊት ሲሆን ብቻ። እነዚህ የአካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ ስልክ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"አካባቢን በበስተጀርባ ድረስ"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ይህ ከግምታዊ ወይም ትክክለኛ አካባቢ በተጨማሪ ከተሰጠ መተግበሪያው በበስተጀርባ እያሄደ ሳለ አካባቢውን መድረስ ይችላል።"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"የድምፅ ቅንብሮችን ለውጥ"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"የSS ጥያቄ ወደ የUSSD ጥያቄ ተለውጧል"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"ወደ አዲስ የSS ጥያቄ ተለውጧል"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"የስራ መገለጫ"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"ዘርጋ"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"ሰብስብ"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"ዝርጋታን ቀያይር"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 9a48e14..ecc24ca 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -140,6 +140,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"‏شبكة Wi-Fi التابعة لـ <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"‏الاتصال عبر شبكة WiFi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"‏شبكة VoWifi التابعة لـ <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"إيقاف"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"‏شبكة Wi-Fi مفضّلة"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"شبكة بيانات الجوال مفضَّلة"</string>
@@ -429,10 +437,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"‏للسماح للتطبيق بالدخول إلى أوامر إضافية لموفر الموقع. قد يتيح هذا للتطبيق التداخل مع تشغيل تقنية نظام تحديد المواقع العالمي (GPS) أو مصادر الموقع الأخرى."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"الوصول إلى الموقع الجغرافي الدقيق في الواجهة الأمامية فقط"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"لا يمكن لهذا التطبيق معرفة موقعك الجغرافي بالضبط إلا عندما يعمل في الخلفية. ويجب تفعيل خدمات الموقع الجغرافي هذه وأن تكون متاحة على الهاتف حتى يتمكن التطبيق من استخدامها. وقد يؤدي هذا إلى زيادة استهلاك طاقة البطارية."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"الوصول إلى الموقع التقريبي (استنادًا إلى الشبكة)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"‏يمكن لهذا التطبيق معرفة موقعك من خلال مصادر الشبكات مثل أبراج الجوّال وشبكات Wi-Fi. ويجب تشغيل خدمات المواقع هذه وأن تكون متاحة على الجهاز اللوحي حتى يتمكن التطبيق من استخدامها."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"‏يمكن لهذا التطبيق معرفة موقعك من خلال مصادر الشبكات مثل أبراج الجوّال وشبكات Wi-Fi. ويجب تشغيل خدمات المواقع هذه وأن تكون متاحة على جهاز التلفزيون حتى يتمكن التطبيق من استخدامها."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"‏يمكن لهذا التطبيق معرفة موقعك من خلال مصادر الشبكات مثل أبراج الجوّال وشبكات Wi-Fi. ويجب تشغيل خدمات المواقع هذه وأن تكون متاحة على الهاتف حتى يتمكن التطبيق من استخدامها."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"الوصول إلى الموقع الجغرافي التقريبي (بالاعتماد على الشبكة) في الخلفية فقط"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"‏يمكن لهذا التطبيق معرفة موقعك مستعينًا بمصادر الشبكات مثل الأبراج الخلوية وشبكات Wi-Fi ولكن يجب أن يعمل في الخلفية. ويجب تفعيل خدمات المواقع هذه وتوفّرها على جهازك اللوحي كي يتمكن التطبيق من استخدامها."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"‏يمكن لهذا التطبيق معرفة موقعك مستعينًا بمصادر الشبكات مثل الأبراج الخلوية وشبكات Wi-Fi ولكن يجب أن يعمل في الخلفية. ويجب تفعيل خدمات المواقع هذه وتوفّرها على جهاز التلفزيون كي يتمكن التطبيق من استخدامها."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"‏يمكن لهذا التطبيق معرفة موقعك مستعينًا بمصادر الشبكات مثل الأبراج الخلوية وشبكات Wi-Fi ولكن يجب أن يعمل في الخلفية. ويجب تفعيل خدمات المواقع هذه وتوفّرها على هاتفك كي يتمكن التطبيق من استخدامها."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"الوصول إلى الموقع الجغرافي في الخلفية"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"إذا تمّ منح إذن التطبيق هذا بالإضافة إلى الموقع الجغرافي التقريبي أو الدقيق، يمكن للتطبيق الوصول إلى الموقع الجغرافي أثناء تشغيله في الخلفية."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"تغيير إعداداتك الصوتية"</string>
@@ -1504,7 +1512,7 @@
     <string name="forward_intent_to_work" msgid="621480743856004612">"أنت تستخدم هذا التطبيق في ملفك الشخصي للعمل"</string>
     <string name="input_method_binding_label" msgid="1283557179944992649">"طريقة الإرسال"</string>
     <string name="sync_binding_label" msgid="3687969138375092423">"مزامنة"</string>
-    <string name="accessibility_binding_label" msgid="4148120742096474641">"إمكانية الدخول"</string>
+    <string name="accessibility_binding_label" msgid="4148120742096474641">"إمكانية الوصول"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"الخلفية"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغيير الخلفية"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"برنامج تلقّي الإشعارات الصوتية"</string>
@@ -1957,6 +1965,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"‏تم تغيير طلب SS إلى طلب USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"‏تم التغيير إلى طلب SS الجديد."</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"الملف الشخصي للعمل"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"توسيع"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"تصغير"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"تبديل التوسيع"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 4df7643..b897e24 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> ৱাই-ফাই"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"ৱাই- ফাই কলিং | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"অফ হৈ আছে"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"ৱাই-ফাইক অগ্ৰাধিকাৰ দিয়া হৈছে"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"ম\'বাইলক অগ্ৰাধিকাৰ দিয়া হৈছে"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"অৱস্থানৰ অতিৰিক্ত নির্দেশনাসমূহত প্ৰৱেশ কৰিবলৈ এপক অনুমতি দিয়ে। ইয়ে এপটোক জিপিএছ বা অন্য অৱস্থান উৎসসমূহৰ কাৰ্যকলাপত হস্তক্ষেপ কৰাৰ সুযোগ দিব পাৰে।"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"কেৱল অগ্ৰভূমিত অৱস্থানৰ সঠিক তথ্য় পাওক"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"এই এপটোৱে যেতিয়া ই নেপথ্যত চলি থাকে তেতিয়া আপোনাৰ সঠিক অৱস্থান নিৰ্ণয় কৰিব পাৰে। এপটোৱে ব্যৱহাৰ কৰিব পৰাকৈ এই অৱস্থান সেৱাসমূহ অন হৈ থাকিবই লাগিব আৰু আপোনাৰ ফ\'নত উপলব্ধ হ\'ব লাগিব। ইয়াৰ ফলত বেটাৰিৰ খৰচ বাঢ়িব পাৰে।"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"অনুমানিক অৱস্থান (নেটৱর্ক ভিত্তিক) ব্যৱহাৰ কৰিব পাৰে"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"চেল টাৱাৰ আৰু ৱাই-ফাই নেটৱর্কৰ দৰে নেটৱর্কৰ উৎসসমূহক ভিত্তি কৰি এই এপটোৱে আপোনাৰ অৱস্থান নিৰ্ণয় কৰিব পাৰে। এই অৱস্থানৰ সেৱাসমূহ অন হৈ থাকিলে আৰু আপোনাৰ টেবলেটটোত উপলব্ধ হ\'লেহে এপটোৱে সেইবোৰ ব্যৱহাৰ কৰিবলৈ সক্ষম হ\'ব।"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"চেল টাৱাৰ আৰু ৱাই-ফাই নেটৱর্কৰ দৰে নেটৱর্কৰ উৎসসমূহক ভিত্তি কৰি এই এপটোৱে আপোনাৰ অৱস্থান নিৰ্ণয় কৰিব পাৰে। এই অৱস্থানৰ সেৱাসমূহ অন হৈ থাকিলে আৰু আপোনাৰ টিভিত উপলব্ধ হ\'লেহে এপটোৱে সেইবোৰ ব্যৱহাৰ কৰিবলৈ সক্ষম হ\'ব।"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"এই এপটোৱে ম\'বাইলৰ টাৱাৰ আৰু ৱাই-ফাইৰ নেটৱৰ্ক আদিৰ দৰে নেটৱৰ্কৰ উৎসসমূহক ভিত্তি কৰি আপোনাৰ অৱস্থান চিনাক্ত কৰিব পাৰে। সেই অৱস্থান সেৱাসমূহ আপোনাৰ ফ\'নত সক্ষম অৱস্থাত থাকিলেহে এপটোৱে সেইবোৰ ব্যৱহাৰ কৰিব পাৰিব।"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"কেৱল অগ্ৰভূমিত থকা অৱস্থাতহে আনুমানিক অৱস্থানৰ (নেটৱৰ্কৰ ওপৰত ভিত্তি কৰি) এক্সেছ"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"এই এপটোৱে অগ্ৰভূমিত থকা অৱস্থাতহে চেল টাৱাৰ আৰু ৱাই-ফাই নেটৱৰ্ক আদিৰ দৰে নেটৱৰ্ক উৎসৰ ওপৰত ভিত্তি কৰি আপোনাৰ অৱস্থান জানিব পাৰে। এপটোৱে এই অৱস্থান সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ হ\'লে সেইবোৰ অন হৈ থকাৰ লগতে আপোনাৰ টেবলেটত থাকিবই লাগিব।"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"এই এপটোৱে অগ্ৰভূমিত থকা অৱস্থাতহে চেল টাৱাৰ আৰু ৱাই-ফাই নেটৱৰ্ক আদিৰ দৰে নেটৱৰ্ক উৎসৰ ওপৰত ভিত্তি কৰি আপোনাৰ অৱস্থান জানিব পাৰে। এপটোৱে এই অৱস্থান সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ হ\'লে সেইবোৰ অন হৈ থকাৰ লগতে আপোনাৰ টিভিত থাকিবই লাগিব।"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"এই এপটোৱে অগ্ৰভূমিত থকা অৱস্থাতহে চেল টাৱাৰ আৰু ৱাই-ফাই নেটৱৰ্ক আদিৰ দৰে নেটৱৰ্ক উৎসৰ ওপৰত ভিত্তি কৰি আপোনাৰ অৱস্থান জানিব পাৰে। এপটোৱে এই অৱস্থান সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ হ\'লে সেইবোৰ অন হৈ থকাৰ লগতে আপোনাৰ ফ\'নত থাকিবই লাগিব।"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"নেপথ্যত চলি থকা সময়ত অৱস্থানৰ এক্সেছ"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ইয়াৰ উপৰিও যদি ইয়াক আনুমানিক বা সঠিক অৱস্থানৰ এক্সেছ দিয়া হয়, তেন্তে উক্ত এপে নেপথ্যত চলি থকাৰ সময়ত অৱস্থানৰ এক্সেছ লাভ কৰিব পাৰে।"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"আপোনাৰ অডিঅ\' ছেটিংসমূহ সলনি কৰক"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS অনুৰোধ USSD অনুৰোধলৈ সলনি কৰা হ\'ল"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"নতুন SS অনুৰোধলৈ সলনি কৰা হ\'ল"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"বিস্তাৰ কৰক"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"সংকুচিত কৰক"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"সম্প্ৰসাৰণ ট’গল কৰক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 4bb6c1f..3f3d685 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"WiFi Zəngi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Deaktiv"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi tərcih edilir"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobil tərcih"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Tətbiqə ekstra məkan provayder əmrlərinə girişə imkan verir. Bu, tətbiqə GPS və ya digər lokal mənbələrlə əməliyyata müdaxiləyə imkan verə bilər."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"yalnız ön planda dəqiq məkana daxil olun"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Bu tətbiq yalnız ön fonda olduqda dəqiq məkanınızı əldə edə bilər. Tətbiqin bunlardan istifadə etməsi üçün bu məkan xidmətləri aktiv edilməlidir və telefonda əlçatan olmalıdır. Bu, batareya sərfiyyatını artıra bilər."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"təxmini məkana (şəbəkə əsaslı) giriş"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Bu tətbiq mobil qüllələr və Wi-Fi şəbəkələri kimi şəbəkə mənbələrinin əassında əkanınızı əldə edə bilər. Bu məkan xidmətləri aktiv edilməlidir və planşetdə tətbiq tərəfindən istifadə üçün əlçatan olmalıdır."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Bu tətbiq mobil qüllələr və Wi-Fi şəbəkələri kimi şəbəkə mənbələrinin əassında əkanınızı əldə edə bilər. Bu məkan xidmətləri aktiv edilməlidir və TV\'də tətbiq tərəfindən istifadə üçün əlçatan olmalıdır."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Bu tətbiq mobil qüllələr və Wi-Fi şəbəkələri kimi şəbəkə mənbələrinin əassında əkanınızı əldə edə bilər. Bu məkan xidmətləri aktiv edilməlidir və telefonda tətbiq tərəfindən istifadə üçün əlçatan olmalıdır."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"yalnız ön planda təxmini məkana (şəbəkəyə əsaslanan) giriş"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Bu tətbiq baza stansiyaları və Wi-Fi şəbəkələri kimi şəbəkə mənbələrinə əsaslanaraq məkanınızı əldə edə bilər. Bu, yalnız tətbiq ön planda olduqda mümkündür. Tətbiqin istifadə edə bilməsi üçün bu məkan xidmətləri aktiv edilməli və planşetdə əlçatan olmalıdır."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Bu tətbiq baza stansiyaları və Wi-Fi kimi şəbəkə mənbələrinə əsaslanaraq məkanınızı əldə edə bilər. Bu, yalnız tətbiq ön planda olduqda mümkündür. Tətbiqin istifadə edə bilməsi üçün bu məkan xidmətləri aktiv edilməli və TV-də əlçatan olmalıdır."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Bu tətbiq baza stansiyaları və Wi-Fi kimi şəbəkə mənbələrinə əsaslanaraq məkanınızı əldə edə bilər. Bu, yalnız tətbiq ön planda olduqda mümkündür. Tətbiqin istifadə edə bilməsi üçün bu məkan xidmətləri aktiv edilməli və telefonda əlçatan olmalıdır."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"arxa fonda məkan girişi"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Bu, təqribi və ya dəqiq məkan girişinə əlavə olaraq verilərsə, tətbiq arxa fonda işləyərkən məkana daxil ola bilər."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"audio ayarlarınızı dəyişir"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS sorğusu USSD sorğusuna dəyişdirildi"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Yeni SS sorğusuna dəyişdirildi"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"İş profili"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Genişləndirin"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Yığcamlaşdırın"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"keçid genişlənməsi"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index e650f2d..ca2c823 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -137,6 +137,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Pozivanje preko Wi-Fi-ja | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Isključeno"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Prednost ima Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Želim mobilne podatke"</string>
@@ -213,7 +221,7 @@
     <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Sat će se ugasiti."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefon će se isključiti."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Da li želite da isključite telefon?"</string>
-    <string name="reboot_safemode_title" msgid="7054509914500140361">"Ponovo pokreni sistem u bezbednom režimu"</string>
+    <string name="reboot_safemode_title" msgid="7054509914500140361">"Restartuj sistem u bezbednom režimu"</string>
     <string name="reboot_safemode_confirm" msgid="55293944502784668">"Da li želite da ponovo pokrenete sistem u bezbednom režimu? Ovo će onemogućiti sve instalirane aplikacije nezavisnih proizvođača. One će biti vraćene kada ponovo pokrenete sistem."</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Nedavno"</string>
     <string name="no_recent_tasks" msgid="8794906658732193473">"Nema nedavnih aplikacija."</string>
@@ -420,10 +428,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Omogućava aplikaciji da pristupa dodatnim komandama davaoca usluga lokacije. To može da omogući aplikaciji da utiče na rad GPS-a ili drugih izvora lokacije."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"pristup preciznoj lokaciji samo u prvom planu"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Ova aplikacija može da odredi vašu tačnu lokaciju samo kada radi u prvom planu. Ove usluge lokacije moraju da budu uključene i dostupne na telefonu da bi aplikacija mogla da ih koristi. To može da poveća potrošnju baterije."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"pristup približnoj lokaciji (utvrđena preko mreže)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ova aplikacija može da pristupi vašoj lokaciji pomoću izvora mreže, kao što su mobilni predajnici i Wi-Fi mreže. Ove usluge lokacije moraju da budu uključene i dostupne na tabletu da bi aplikacija mogla da ih koristi."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ova aplikacija može da pristupi vašoj lokaciji pomoću izvora mreže, kao što su mobilni predajnici i Wi-Fi mreže. Ove usluge lokacije moraju da budu uključene i dostupne na TV-u da bi aplikacija mogla da ih koristi."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ova aplikacija može da pristupi vašoj lokaciji pomoću izvora mreže, kao što su mobilni predajnici i Wi-Fi mreže. Ove usluge lokacije moraju da budu uključene i dostupne na telefonu da bi aplikacija mogla da ih koristi."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"pristup približnoj lokaciji (utvrđenoj preko mreže) samo u prvom planu"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Ova aplikacija može da pristupi vašoj lokaciji pomoću izvora mreže, kao što su mobilni predajnici i Wi-Fi mreže, ali samo kada aplikacija radi u prvom planu. Ove usluge lokacije moraju da budu uključene i dostupne na tabletu da bi aplikacija mogla da ih koristi"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Ova aplikacija može da pristupi vašoj lokaciji pomoću izvora mreže, kao što su mobilni predajnici i Wi-Fi mreže, ali samo kada aplikacija radi u prvom planu. Ove usluge lokacije moraju da budu uključene i dostupne na televizoru da bi aplikacija mogla da ih koristi."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Ova aplikacija može da pristupi vašoj lokaciji pomoću izvora mreže, kao što su mobilni predajnici i Wi-Fi mreže, ali samo kada aplikacija radi u prvom planu. Ove usluge lokacije moraju da budu uključene i dostupne na telefonu da bi aplikacija mogla da ih koristi."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"pristup lokaciji u pozadini"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ako se pored približnog ili preciznog pristupa lokacija odobri i ovaj, aplikacija može da pristupa lokaciji dok je pokrenuta u pozadini."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"promena audio podešavanja"</string>
@@ -507,11 +515,11 @@
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"onemogućavanje zaključavanja ekrana"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Dozvoljava aplikaciji da onemogući zaključavanje tastature i sve povezane bezbednosne mere sa lozinkama. Na primer, telefon onemogućava zaključavanje tastature pri prijemu dolaznog telefonskog poziva, a zatim ga ponovo omogućava po završetku poziva."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"koristi biometrijski hardver"</string>
-    <string name="permdesc_useBiometric" msgid="8389855232721612926">"Dozvoljava aplikaciji da koristi biometrijski hardver za potvrdu autentičnosti"</string>
+    <string name="permdesc_useBiometric" msgid="8389855232721612926">"Dozvoljava aplikaciji da koristi biometrijski hardver za potvrdu identiteta"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"upravljaj hardverom za otiske prstiju"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Dozvoljava aplikaciji da aktivira metode za dodavanje i brisanje šablona otisaka prstiju koji će se koristiti."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"koristi hardver za otiske prstiju"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Dozvoljava aplikaciji da koristi hardver za otiske prstiju radi potvrde autentičnosti"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Dozvoljava aplikaciji da koristi hardver za otiske prstiju radi potvrde identiteta"</string>
     <string name="permlab_audioRead" msgid="6617225220728465565">"čitanje muzičke kolekcije"</string>
     <string name="permdesc_audioRead" msgid="5034032570243484805">"Dozvoljava aplikaciji da čita muzičku kolekciju."</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"izmena muzičke kolekcije"</string>
@@ -898,7 +906,7 @@
     <string name="factorytest_failed" msgid="5410270329114212041">"Fabričko testiranje nije uspelo"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Radnja FACTORY_TEST je podržana samo za pakete instalirane u direktorijumu /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nije pronađen nijedan paket koji obezbeđuje radnju FACTORY_TEST."</string>
-    <string name="factorytest_reboot" msgid="6320168203050791643">"Ponovo pokreni"</string>
+    <string name="factorytest_reboot" msgid="6320168203050791643">"Restartuj"</string>
     <string name="js_dialog_title" msgid="1987483977834603872">"Na stranici na adresi „<xliff:g id="TITLE">%s</xliff:g>“ piše:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"Potvrda navigacije"</string>
@@ -1318,7 +1326,7 @@
     <string name="sim_done_button" msgid="827949989369963775">"Gotovo"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"SIM kartica je dodata"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"Restartujte uređaj da biste mogli da pristupite mobilnoj mreži."</string>
-    <string name="sim_restart_button" msgid="4722407842815232347">"Ponovo pokreni"</string>
+    <string name="sim_restart_button" msgid="4722407842815232347">"Restartuj"</string>
     <string name="install_carrier_app_notification_title" msgid="9056007111024059888">"Aktivirajte mobilnu uslugu"</string>
     <string name="install_carrier_app_notification_text" msgid="3346681446158696001">"Preuzmite aplikaciju mobilnog operatera da biste aktivirali novi SIM"</string>
     <string name="install_carrier_app_notification_text_app_name" msgid="1196505084835248137">"Preuzmite aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g> da biste aktivirali novu SIM karticu"</string>
@@ -1858,6 +1866,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS zahtev je promenjen u USSD zahtev"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Promenjeno je u novi SS zahtev"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Profil za Work"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Proširi"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Skupi"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"uključite/isključite proširenje"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index db75d1d..3462a84 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -138,6 +138,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi ад <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi-тэлефанія | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWi-Fi ад <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Выкл."</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Прыярытэт Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Прыярытэт мабільнай сеткі"</string>
@@ -423,10 +431,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Дазваляе праграме атрымліваць доступ да дадатковых каманд службаў вызначэння месцазнаходжання. Гэта можа дазволіць праграме ўмешвацца ў функцыянаванне GPS або іншых крыніц даных аб месцазнаходжаннi."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"доступ да дакладнага месцазнаходжання толькі ў асноўным рэжыме"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Гэта праграма можа атрымліваць звесткі пра ваша дакладнае месцазнаходжанне толькі ў асноўным рэжыме. Службы геалакацыі павінны быць уключаны і даступныя на вашым тэлефоне, каб праграма магла імі карыстацца. Гэта можа павялічыць спажыванне зараду акумулятара."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"атрымліваць доступ да прыблізнага месцазнаходжання (на аснове даных сеткі)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Гэта праграма можа атрымліваць звесткі пра ваша месцазнаходжанне на падставе даных сеткавых крыніц, такіх як вышкі сотавай сувязі і сеткі Wi-Fi. Гэтыя сэрвісы вызначэння месцазнаходжання павінны быць уключаны i даступныя на вашым планшэце, каб праграма магла іх выкарыстоўваць."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Гэта праграма можа атрымліваць звесткі пра ваша месцазнаходжанне на падставе даных сеткавых крыніц, такіх як вышкі сотавай сувязі і сеткі Wi-Fi. Гэтыя сэрвісы вызначэння месцазнаходжання павінны быць уключаны i даступныя на вашым тэлевізары, каб праграма магла іх выкарыстоўваць."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Гэта праграма можа атрымліваць звесткі пра ваша месцазнаходжанне на падставе даных сеткавых крыніц, такіх як вышкі сотавай сувязі і сеткі Wi-Fi. Гэтыя сэрвісы вызначэння месцазнаходжання павінны быць уключаны i даступныя на вашым тэлефоне, каб праграма магла іх выкарыстоўваць."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"доступ да прыблізнага месцазнаходжання (на падставе сеткі) толькі ў актыўным рэжыме"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Гэта праграма можа атрымліваць звесткі пра ваша месцазнаходжанне толькі ў актыўным рэжыме на падставе даных сеткавых крыніц, такіх як вышкі сотавай сувязі і сеткі Wi-Fi. Каб праграма магла карыстацца гэтымі службамі геалакацыі, неабходна ўключыць і зрабіць іх даступнымі на планшэце."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Гэта праграма можа атрымліваць звесткі пра ваша месцазнаходжанне толькі ў актыўным рэжыме на падставе даных сеткавых крыніц, такіх як вышкі сотавай сувязі і сеткі Wi-Fi. Каб праграма магла карыстацца гэтымі службамі геалакацыі, неабходна ўключыць і зрабіць іх даступнымі на тэлевізары."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Гэта праграма можа атрымліваць звесткі пра ваша месцазнаходжанне толькі ў актыўным рэжыме на падставе даных сеткавых крыніц, такіх як вышкі сотавай сувязі і сеткі Wi-Fi. Каб праграма магла карыстацца гэтымі службамі геалакацыі, неабходна ўключыць і зрабіць іх даступнымі на тэлефоне."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"доступ да вызначэння месцазнаходжання ў фонавым рэжыме"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Акрамя доступу да прыкладнага ці дакладнага месцазнаходжання праграма можа мець доступ да вызначэння геалакацыі ў фонавым рэжыме працы. На гэта патрабуецца дазвол."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"змяняць налады аудыё"</string>
@@ -1891,6 +1899,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS-запыт заменены на USSD-запыт"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Зроблена замена на новы SS-запыт"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Працоўны профіль"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Разгарнуць"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Згарнуць"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"разгарнуць/згарнуць"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index e2e5bd4..6693dfd 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi от <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Обаждания през Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWi-Fi от <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Изключено"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Предпочита се Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Предпочитат се мобилни данни"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Разрешава на приложението достъп до допълнителни команди на доставчика на местоположение. Това може да позволи на приложението да смущава работата на GPS или на другите източници на местоположение."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"достъп до точното местоположение само на преден план"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Приложението може да получава данни за точното ви местоположение само когато работи на преден план. Тези услуги за местоположение трябва да са включени и налице на телефона ви, за да могат да се използват от приложението. Това може да увеличи потреблението на батерията."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"достъп до приблизителното местоположение (въз основа на мрежата)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Приложението може да получава данни за местоположението ви въз основа на мрежови източници, като клетъчни кули и Wi-Fi. Тези услуги за местоположение трябва да са включени и налице на таблета ви, за да могат да се използват от приложението."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Приложението може да получава данни за местоположението ви въз основа на мрежови източници, като клетъчни кули и Wi-Fi. Тези услуги за местоположение трябва да са включени и налице на телевизора ви, за да могат да се използват от приложението."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Приложението може да получава данни за местоположението ви въз основа на мрежови източници, като клетъчни кули и Wi-Fi. Тези услуги за местоположение трябва да са включени и налице на телефона ви, за да могат да се използват от приложението."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"достъп до приблизителното местоположение (основано на мрежи) само на преден план"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Приложението може да получава данни за местоположението ви въз основа на мрежови източници, като клетъчни базови станции и Wi-Fi мрежи, само когато работи на преден план. Тези услуги за местоположение трябва да са включени и налице на таблета ви, за да могат да се използват от приложението."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Приложението може да получава данни за местоположението ви въз основа на мрежови източници, като клетъчни базови станции и Wi-Fi мрежи, само когато работи на преден план. Тези услуги за местоположение трябва да са включени и налице на телевизора ви, за да могат да се използват от приложението."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Приложението може да получава данни за местоположението ви въз основа на мрежови източници, като клетъчни базови станции и Wi-Fi мрежи, само когато работи на преден план. Тези услуги за местоположение трябва да са включени и налице на телефона ви, за да могат да се използват от приложението."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"достъп до местоположението на заден план"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ако разрешението бъде предоставено в допълнение към достъпа до приблизителното или точното местоположение, приложението може да осъществява достъп до местоположението, докато се изпълнява на заден план."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"промяна на настройките ви за звука"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS заявката е променена на USSD заявка"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Променено на нова SS заявка"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Служебен потребителски профил"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Разгъване"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Свиване"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"превключване на разгъването"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 0122c6c..120abf0 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> ওয়াই-ফাই"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"ওয়াই-ফাই কলিং | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"বন্ধ আছে"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"পছন্দের ওয়াই-ফাই"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"পছন্দের মোবাইল"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"লোকেশনের সাথে সম্পর্কিত তথ্য প্রদানকারীর অতিরিক্ত কম্যান্ডগুলিকে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ এটি অ্যাপ্লিকেশানটিকে GPS অথবা অন্যান্য লোকেশন নির্ণয়ের সাথে সম্পর্কিত উৎসগুলির ক্রিয়াপ্রণালীর নিয়ন্ত্রণকে মঞ্জুর করতে পারে৷"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"শুধুমাত্র অ্যাপটি খোলা থাকলে আপনার যথাযথ লোকেশন অ্যাক্সেস করা"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"এই অ্যাপটি ফোরগ্রাউন্ডে চলতে থাকলে যেকোনও সময়ে আপনার যথাযথ লোকেশন জানতে পারবে। এই লোকেশন পরিষেবাগুলি অবশ্যই চালু রাখতে হবে এবং আপনার ফোনে সেগুলি উপলভ্য থাকতে হবে যাতে অ্যাপটি সেগুলি ব্যবহার করতে পারে। এর জন্য অতিরিক্ত ব্যাটারি খরচ হতে পারে।"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"আনুমানিক লোকেশন (নেটওয়ার্ক-ভিত্তিক) অ্যাক্সেস করুন"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"মোবাইল টাওয়ার এবং ওয়াই-ফাই নেটওয়ার্কগুলির মত নেটওয়ার্ক উৎসগুলির উপর ভিত্তি করে এই অ্যাপটি আপনার লোকেশন শনাক্ত করতে পারে৷ এই লোকেশন পরিষেবাগুলি অবশ্যই চালু রাখতে হবে এবং অ্যাপটি যাতে সেগুলি ব্যবহার করতে পারে সেইজন্য সেগুলিকে আপনার ট্যাবলেটে উপলব্ধ করে রাখতে হবে৷"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"মোবাইল টাওয়ার এবং ওয়াই-ফাই নেটওয়ার্কগুলির মত নেটওয়ার্কের উৎসগুলির উপর ভিত্তি করে এই অ্যাপটি আপনার লোকেশন শনাক্ত করতে পারে৷ এই লোকেশন পরিষেবাগুলি অবশ্যই চালু রাখতে হবে এবং অ্যাপটি যাতে সেগুলি ব্যবহার করতে পারে সেজন্য সেগুলিকে আপনার টিভিতে উপলব্ধ করে রাখতে হবে৷"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"মোবাইল টাওয়ার এবং ওয়াই-ফাই নেটওয়ার্কগুলির মত নেটওয়ার্ক উৎসগুলির উপর ভিত্তি করে এই অ্যাপটি আপনার লোকেশন শনাক্ত করতে পারে৷ এই লোকেশন পরিষেবাগুলি অবশ্যই চালু রাখতে হবে এবং অ্যাপটি যাতে সেগুলি ব্যবহার করতে পারে সেজন্য সেগুলিকে আপনার ফোনে উপলব্ধ করে রাখতে হবে৷"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"শুধুমাত্র খোলা অবস্থায় আনুমানিক লোকেশন (নেটওয়ার্ক ভিত্তিক) অ্যাক্সেস করবে"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"অ্যাপটি শুধুমাত্র খোলা অবস্থায় সেল টাওয়ার এবং ওয়াই-ফাইয়ের মতো নেটওয়ার্ক সোর্স ব্যবহার করে আপনার লোকেশন জানতে পারবে। লোকেশন সংক্রান্ত এই পরিষেবাগুলি অবশ্যই চালু থাকতে হবে এবং আপনার ট্যাবলেটে সেগুলি উপলভ্য থাকতে হবে যাতে অ্যাপটি সেগুলি ব্যবহার করতে পারে।"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"অ্যাপটি শুধুমাত্র খোলা অবস্থায় সেল টাওয়ার এবং ওয়াই-ফাইয়ের মতো নেটওয়ার্ক সোর্স ব্যবহার করে আপনার লোকেশন জানতে পারবে। লোকেশন সংক্রান্ত এই পরিষেবাগুলি অবশ্যই চালু থাকতে হবে এবং আপনার টিভিতে সেগুলি উপলভ্য থাকতে হবে যাতে অ্যাপটি সেগুলি ব্যবহার করতে পারে।"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"অ্যাপটি শুধুমাত্র খোলা অবস্থায় সেল টাওয়ার এবং ওয়াই-ফাইয়ের মতো নেটওয়ার্ক সোর্স ব্যবহার করে আপনার লোকেশন জানতে পারবে। লোকেশন সংক্রান্ত এই পরিষেবাগুলি অবশ্যই চালু থাকতে হবে এবং আপনার ফোনে সেগুলি উপলভ্য থাকতে হবে যাতে অ্যাপটি সেগুলি ব্যবহার করতে পারে।"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ব্যাকগ্রাউন্ডে লোকেশন অ্যাক্সেস করা"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"আনুমানিক বা একদম যথাযথ লোকেশন অ্যাক্সেস করার অনুমতি দেওয়া হলে এই অ্যাপটি ব্যাকগ্রাউন্ডে চালু থাকাকালীন আপনার লোকেশন অ্যাক্সেস করতে পারবে।"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"আপনার অডিও সেটিংস পরিবর্তন করে"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS অনুরোধ USSD অনুরোধে পরিবর্তন করা হয়েছে"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"নতুন SS অনুরোধে পরিবর্তন করা হয়েছে"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"কর্মস্থলের প্রোফাইল"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"বড় করুন"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"সঙ্কুচিত করুন"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"টগল সম্প্রসারণ"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 453bedf..e0abbe1 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -137,6 +137,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> WiFi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Pozivanje putem WiFi-ja | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Isključeno"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Preferira se WiFi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferira se mobilna mreža"</string>
@@ -420,10 +428,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Dozvoljava aplikaciji pristup dodatnim naredbama pružatelja lokacija. Ovim se aplikaciji može dozvoliti da ometa rad GPS-a ili drugih izvora lokacija."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"pristup tačnoj lokaciji samo u prvom planu"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Ova aplikacija može odrediti vašu tačnu lokaciju samo kada je u prvom planu. Ove usluge lokacije moraju biti uključene i dostupne na vašem telefonu da ih aplikacija može koristiti. To može dovesti do povećane potrošnje baterije."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"pristup približnoj lokaciji (utvrđena preko mreže)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ova aplikacija može odrediti vašu lokaciju na osnovu izvora mreže kao što su predajnici za mobilnu mrežu i WiFi mreže. Ove usluge za određivanje lokacije moraju biti uključene i omogućene na vašem tabletu kako bi ih aplikacija mogla koristiti."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ova aplikacija može odrediti vašu lokaciju na osnovu izvora mreže kao što su predajnici za mobilnu mrežu i WiFi mreže. Ove usluge za određivanje lokacije moraju biti uključene i omogućene na vašem TV-u kako bi ih aplikacija mogla koristiti."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ova aplikacija može odrediti vašu lokaciju na osnovu izvora mreže kao što su predajnici za mobilnu mrežu i WiFi mreže. Ove usluge za određivanje lokacije moraju biti uključene i omogućene na vašem telefonu kako bi ih aplikacija mogla koristiti."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"pristup približnoj lokaciji (utvrđena preko mreže) samo u prvom planu"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Ova aplikacija može odrediti vašu lokaciju na osnovu izvora mreže kao što su predajnici za mobilnu mrežu i WiFi mreže ali samo kada je aplikacija u prvom planu. Ove usluge za određivanje lokacije moraju biti uključene i omogućene na vašem tabletu kako bi ih aplikacija mogla koristiti."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Ova aplikacija može odrediti vašu lokaciju na osnovu izvora mreže kao što su predajnici za mobilnu mrežu i WiFi mreže ali samo kada je aplikacija u prvom planu. Ove usluge za određivanje lokacije moraju biti uključene i omogućene na vašem TV uređaju kako bi ih aplikacija mogla koristiti."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Ova aplikacija može odrediti vašu lokaciju na osnovu izvora mreže kao što su predajnici za mobilnu mrežu i WiFi mreže ali samo kada je aplikacija u prvom planu. Ove usluge za određivanje lokacije moraju biti uključene i omogućene na vašem telefonu kako bi ih aplikacija mogla koristiti."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"pristup lokaciji u pozadini"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ako je ovo odobreno, pored pristupa približnoj ili tačnoj lokaciji, aplikacija može pristupiti lokaciji dok radi u pozadini."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"izmjene postavki zvuka"</string>
@@ -1860,6 +1868,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS zahtjev je promijenjen u USSD zahtjev"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Promijenjeno u novi SS zahtjev"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Profil za posao"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Proširi"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Suzi"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"aktiviraj/deaktiviraj proširenje"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index a212014..cb2c183 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi‑Fi (<xliff:g id="SPN">%s</xliff:g>)"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Trucades per Wi‑Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi (<xliff:g id="SPN">%s</xliff:g>)"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Desactivat"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Preferència per la Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferència per dades mòbils"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permet que l\'aplicació accedeixi a ordres addicionals del proveïdor d\'ubicacions; per tant, és possible que l\'aplicació pugui interferir en el funcionament del GPS o d\'altres fonts d\'ubicacions."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"accedeix a la ubicació exacta només en primer pla"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Aquesta aplicació pot obtenir la teva ubicació exacta només quan està en primer pla. Aquests serveis d\'ubicació han d\'estar activats i disponibles al telèfon perquè l\'aplicació els pugui utilitzar, i això pot fer que el consum de bateria augmenti."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"accedir a la ubicació aproximada (basada en la xarxa)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Aquesta aplicació pot obtenir la teva ubicació a partir de fonts de xarxa, com ara torres de telefonia mòbil i xarxes Wi-Fi. Aquests serveis d\'ubicació han d\'estar activats i disponibles a la tauleta perquè l\'aplicació els pugui utilitzar."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Aquesta aplicació pot obtenir la teva ubicació a partir de fonts de xarxa, com ara torres de telefonia mòbil i xarxes Wi-Fi. Aquests serveis d\'ubicació han d\'estar activats i disponibles al televisor perquè l\'aplicació els pugui utilitzar."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Aquesta aplicació pot obtenir la teva ubicació a partir de fonts de xarxa, com ara torres de telefonia mòbil i xarxes Wi-Fi. Aquests serveis d\'ubicació han d\'estar activats i disponibles al telèfon perquè l\'aplicació els pugui utilitzar."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"accedeix a la ubicació aproximada (basada en xarxa) només en primer pla"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Aquesta aplicació pot obtenir la teva ubicació a partir de fonts de xarxa, com ara torres de telefonia mòbil i xarxes Wi‑Fi, però només quan està en primer pla. Aquests serveis d\'ubicació han d\'estar activats i disponibles a la tauleta perquè l\'aplicació els pugui utilitzar."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Aquesta aplicació pot obtenir la teva ubicació a partir de fonts de xarxa, com ara torres de telefonia mòbil i xarxes Wi‑Fi, però només quan està en primer pla. Aquests serveis d\'ubicació han d\'estar activats i disponibles al televisor perquè l\'aplicació els pugui utilitzar."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Aquesta aplicació pot obtenir la teva ubicació a partir de fonts de xarxa, com ara torres de telefonia mòbil i xarxes Wi‑Fi, però només quan està en primer pla. Aquests serveis d\'ubicació han d\'estar activats i disponibles al telèfon perquè l\'aplicació els pugui utilitzar."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"accedir a la ubicació en segon pla"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Si es concedeix aquest permís, a més de l\'accés a la ubicació aproximada o exacta, l\'aplicació pot accedir a la ubicació mentre s\'executa en segon pla."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"canviar la configuració d\'àudio"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"La sol·licitud SS s\'ha canviat per una sol·licitud USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"S\'ha canviat a una nova sol·licitud SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Perfil professional"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Desplega"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Replega"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"desplega o replega"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index d71f72c..019e7e0 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -138,6 +138,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g>: Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Volání přes Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g>: VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Vypnuto"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Preferována síť W-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferována mobilní data"</string>
@@ -423,10 +431,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Umožňuje aplikaci přístup k dalším příkazům poskytovatele polohy. To aplikaci umožní zasahovat do fungování systému GPS a dalších zdrojů polohy."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"přístup k přesné poloze jen na popředí"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Tato aplikace může zjistit vaši přesnou polohu, jen když běží na popředí. Aby tyto služby určování polohy mohla aplikace používat, musí být v telefonu dostupné a musí být zapnuté. Tyto služby mohou způsobit rychlejší vybíjení baterie."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"přístup k přibližné poloze (pomocí sítě)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Tato aplikace může zjistit vaši polohu podle zdrojů sítě, jako jsou vysílací věže nebo sítě Wi-Fi. Aby tyto služby určování polohy mohla aplikace používat, musí být v tabletu dostupné a musí být zapnuté."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Tato aplikace může zjistit vaši polohu podle zdrojů sítě, jako jsou vysílací věže nebo sítě Wi-Fi. Aby tyto služby určování polohy mohla aplikace používat, musí být v televizi dostupné a musí být zapnuté."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Tato aplikace může zjistit vaši polohu podle zdrojů sítě, jako jsou vysílací věže nebo sítě Wi-Fi. Aby tyto služby určování polohy mohla aplikace používat, musí být v telefonu dostupné a musí být zapnuté."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"přístup k přibližené poloze (na základě sítě) jen na popředí"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Tato aplikace může zjistit vaši polohu podle zdrojů sítě, jako jsou vysílací věže nebo sítě Wi-Fi (ale pouze pokud je aplikace na popředí). Aby tyto služby určování polohy mohla aplikace používat, musí být v tabletu dostupné a musí být zapnuté."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Tato aplikace může zjistit vaši polohu podle zdrojů sítě, jako jsou vysílací věže nebo sítě Wi-Fi (ale pouze pokud je aplikace na popředí). Aby tyto služby určování polohy mohla aplikace používat, musí být v televizi dostupné a musí být zapnuté."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Tato aplikace může zjistit vaši polohu podle zdrojů sítě, jako jsou vysílací věže nebo sítě Wi-Fi (ale pouze pokud je aplikace na popředí). Aby tyto služby určování polohy mohla aplikace používat, musí být v telefonu dostupné a musí být zapnuté."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"přístup k poloze na pozadí"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Bude-li oprávnění uděleno dodatečně k přístupu k přibližné nebo přesné poloze, aplikace bude moci používat polohu při spuštění na pozadí."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"změna nastavení zvuku"</string>
@@ -1891,6 +1899,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Požadavek SS byl změněn na požadavek USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Změněno na nový požadavek SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Pracovní profil"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Rozbalit"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Sbalit"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"přepnout rozbalení"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 6e9ae6b..f7013ec 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi via <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi-opkald | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi via <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Fra"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"WiFi-netværk er foretrukket"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobildata foretrækkes"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Tillader, at appen kan få adgang til yderligere kommandoer for placeringsudbydere. Dette kan gøre det muligt for appen at forstyrre GPS-funktionen eller andre placeringskilder."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"få kun adgang til nøjagtig placering i forgrunden"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Denne app kan kun få din nøjagtige placering, når den er i forgrunden. Disse placeringstjenester skal være aktiverede og tilgængelige på din telefon, før appen kan bruge dem. Dette kan øge batteriforbruget."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"få adgang til omtrentlig placering (netværksbaseret)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Denne app kan bestemme din placering ved hjælp af netværkskilder, som f.eks. mobilmaster og Wi-Fi-netværk. Disse placeringstjenester skal være aktiverede og tilgængelige på din tablet, før appen kan bruge dem."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Denne app kan bestemme din placering ved hjælp af netværkskilder, som f.eks. mobilmaster og Wi-Fi-netværk. Disse placeringstjenester skal være aktiverede og tilgængelige på dit fjernsyn, før appen kan bruge dem."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Denne app kan bestemme din placering ved hjælp af netværkskilder, som f.eks. mobilmaster og Wi-Fi-netværk. Disse placeringstjenester skal være aktiverede og tilgængelige på din telefon, før appen kan bruge dem."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"få kun adgang til omtrentlig placering (netværksbaseret) i forgrunden"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Denne app kan fastslå din placering ved hjælp af netværkskilder som f.eks. mobilmaster og Wi-Fi-netværk, men kun når appen er i forgrunden. Disse placeringstjenester skal være aktiverede og tilgængelige på din tablet, før appen kan bruge dem."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Denne app kan fastslå din placering ved hjælp af netværkskilder som f.eks. mobilmaster og Wi-Fi-netværk, men kun når appen er i forgrunden. Disse placeringstjenester skal være aktiverede og tilgængelige på dit fjernsyn, før appen kan bruge dem."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Denne app kan fastslå din placering ved hjælp af netværkskilder som f.eks. mobilmaster og Wi-Fi-netværk, men kun når appen er i forgrunden. Disse placeringstjenester skal være aktiveret og tilgængelige på din telefon, før appen kan bruge dem."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"adgang til placering i baggrunden"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Hvis appen godkendes, og der gives adgang til den omtrentlige eller nøjagtige placering, kan appen registrere placeringen, mens den kører i baggrunden."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"skifte dine lydindstillinger"</string>
@@ -646,11 +654,11 @@
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Tjek længden samt tilladte tegn i adgangskoder og pinkoder til skærmlåsen."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Overvåg forsøg på oplåsning af skærm"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Overvåg antallet af forkert indtastede adgangskoder, når du låser skærmen op, og lås din tablet, eller slet alle data i den, hvis der er indtastet for mange forkerte adgangskoder."</string>
-    <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Overvåg antallet af forkert indtastede adgangskoder ved oplåsning af skærmen, og lås tv\'et eller slet alle dets data, hvis der indtastes for mange forkerte adgangskoder."</string>
+    <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Overvåg antallet af forkert indtastede adgangskoder ved oplåsning af skærmen, og lås tv\'et eller slet alle dets data, hvis der angives for mange forkerte adgangskoder."</string>
     <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Overvåg antallet af forkerte adgangskoder ved oplåsning af skærmen, og lås telefonen eller slet alle data på telefonen, hvis der er indtastet for mange forkerte adgangskoder."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Registrer antallet af forkerte adgangskoder, der indtastes ved oplåsning af skærmen, og lås din tablet, eller slet alle brugerens data, hvis adgangskoden tastes forkert for mange gange."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Registrer antallet af forkerte adgangskoder, der indtastes ved oplåsning af skærmen, og lås tv-adgangen, eller slet alle brugerens data, hvis adgangskoden tastes forkert for mange gange."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Registrer antallet af forkerte adgangskoder, der indtastes ved oplåsning af skærmen, og lås telefonen, eller slet alle brugerens data, hvis adgangskoden tastes forkert for mange gange."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Registrer antallet af forkerte adgangskoder, der angives ved oplåsning af skærmen, og lås din tablet, eller slet alle brugerens data, hvis adgangskoden tastes forkert for mange gange."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Registrer antallet af forkerte adgangskoder, der angives ved oplåsning af skærmen, og lås tv-adgangen, eller slet alle brugerens data, hvis adgangskoden tastes forkert for mange gange."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Registrer antallet af forkerte adgangskoder, der angives ved oplåsning af skærmen, og lås telefonen, eller slet alle brugerens data, hvis adgangskoden tastes forkert for mange gange."</string>
     <string name="policylab_resetPassword" msgid="4934707632423915395">"Skifte skærmlås"</string>
     <string name="policydesc_resetPassword" msgid="1278323891710619128">"Skifter skærmlås"</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Låse skærmen"</string>
@@ -802,7 +810,7 @@
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Tryk på Menu for at låse op eller foretage et nødopkald."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Tryk på Menu for at låse op."</string>
     <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Tegn oplåsningsmønster"</string>
-    <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Nødopkald"</string>
+    <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Nødsituation"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Tilbage til opkald"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Rigtigt!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Prøv igen"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS-anmodningen blev ændret til en USSD-anmodning"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Ændret til en SS-anmodning"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Arbejdsprofil"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Udvid"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Skjul"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"Slå udvidelse til eller fra"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index e0f8201..2bad90e 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -70,7 +70,7 @@
     <string name="ThreeWCMmi" msgid="9051047170321190368">"Dreierkonferenz"</string>
     <string name="RuacMmi" msgid="7827887459138308886">"Ablehnung unerwünschter Anrufe"</string>
     <string name="CndMmi" msgid="3116446237081575808">"Rufnummernübermittlung"</string>
-    <string name="DndMmi" msgid="1265478932418334331">"Nicht stören"</string>
+    <string name="DndMmi" msgid="1265478932418334331">"Bitte nicht stören"</string>
     <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Anrufer-ID ist standardmäßig beschränkt. Nächster Anruf: Beschränkt"</string>
     <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Anrufer-ID ist standardmäßig beschränkt. Nächster Anruf: Nicht beschränkt"</string>
     <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Anrufer-ID ist standardmäßig nicht beschränkt. Nächster Anruf: Beschränkt"</string>
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> WLAN"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"WLAN-Telefonie | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWLAN"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Aus"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"WLAN bevorzugt"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobilverbindung bevorzugt"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Ermöglicht der App, auf zusätzliche Standortanbieterbefehle zuzugreifen. Damit könnte die App die Funktionsweise von GPS oder anderen Standortquellen beeinträchtigen."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"Nur bei Ausführung im Vordergrund auf den genauen Standort zugreifen"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Diese App kann deinen genauen Standort nur dann ermitteln, wenn sie im Vordergrund ausgeführt wird. Die App kann diese Standortdienste nur verwenden, wenn sie auf deinem Smartphone aktiviert und verfügbar sind. Hierdurch kann sich der Akkuverbrauch erhöhen."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"Auf den ungefähren Standort zugreifen (netzwerkbasiert)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Diese App kann deinen Standort mithilfe von Netzwerkquellen wie Mobilfunkmasten und WLAN ermitteln. Die App kann diese Standortdienste nur verwenden, wenn sie auf deinem Tablet aktiviert und verfügbar sind."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Diese App kann deinen Standort mithilfe von Netzwerkquellen wie Mobilfunkmasten und WLAN ermitteln. Die App kann diese Standortdienste nur verwenden, wenn sie auf deinem Fernseher aktiviert und verfügbar sind."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Diese App kann deinen Standort mithilfe von Netzwerkquellen wie Mobilfunkmasten und WLAN ermitteln. Die App kann diese Standortdienste nur verwenden, wenn sie auf deinem Smartphone aktiviert und verfügbar sind."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"Nur bei Ausführung im Vordergrund auf den ungefähren Standort (netzwerkbasiert) zugreifen"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Diese App kann deinen Standort anhand von Netzwerkquellen wie Mobilfunkmasten und WLANs ermitteln, allerdings nur, wenn sie im Vordergrund ausgeführt wird. Diese Standortdienste müssen auf deinem Tablet aktiviert und verfügbar sein, damit die App sie nutzen kann."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Diese App kann deinen Standort anhand von Netzwerkquellen wie Mobilfunkmasten und WLANs ermitteln, allerdings nur, wenn sie im Vordergrund ausgeführt wird. Diese Standortdienste müssen auf deinem Fernseher aktiviert und verfügbar sein, damit die App sie nutzen kann."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Diese App kann deinen Standort anhand von Netzwerkquellen wie Mobilfunkmasten und WLANs ermitteln, allerdings nur, wenn sie im Vordergrund ausgeführt wird. Diese Standortdienste müssen auf deinem Smartphone aktiviert und verfügbar sein, damit die App sie nutzen kann."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"Im Hintergrund auf den Standort zugreifen"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Wenn zusätzlich zum Zugriff auf den ungefähren oder genauen Standort diese Erlaubnis erteilt wird, kann die App bei Ausführung im Hintergrund auf den Standort zugreifen."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"Audio-Einstellungen ändern"</string>
@@ -640,8 +648,8 @@
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Ermöglicht dem Eigentümer die Bindung an die Oberfläche eines Mobilfunkanbieter-Messaging-Dienstes auf oberster Ebene. Für normale Apps sollte dies nie erforderlich sein."</string>
     <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"An Mobilfunkanbieter-Dienste binden"</string>
     <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"Ermöglicht dem Eigentümer die Bindung an Mobilfunkanbieter-Dienste. Für normale Apps sollte dies nicht erforderlich sein."</string>
-    <string name="permlab_access_notification_policy" msgid="4247510821662059671">"Auf \"Nicht stören\" zugreifen"</string>
-    <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Ermöglicht der App Lese- und Schreibzugriff auf die \"Nicht stören\"-Konfiguration"</string>
+    <string name="permlab_access_notification_policy" msgid="4247510821662059671">"Auf \"Bitte nicht stören\" zugreifen"</string>
+    <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Ermöglicht der App Lese- und Schreibzugriff auf die \"Bitte nicht stören\"-Konfiguration"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Zulässige Länge und Zeichen für Passwörter für die Displaysperre festlegen"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Versuche zum Entsperren des Displays überwachen"</string>
@@ -1804,10 +1812,10 @@
     <string name="zen_mode_until" msgid="7336308492289875088">"Bis <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_alarm" msgid="9128205721301330797">"Bis <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (nächste Weckzeit)"</string>
     <string name="zen_mode_forever" msgid="931849471004038757">"Bis zur Deaktivierung"</string>
-    <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Bis zur Deaktivierung von \"Nicht stören\""</string>
+    <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Bis zur Deaktivierung von \"Bitte nicht stören\""</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
     <string name="toolbar_collapse_description" msgid="2821479483960330739">"Minimieren"</string>
-    <string name="zen_mode_feature_name" msgid="5254089399895895004">"Nicht stören"</string>
+    <string name="zen_mode_feature_name" msgid="5254089399895895004">"Bitte nicht stören"</string>
     <string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"Ruhezeit"</string>
     <string name="zen_mode_default_weeknights_name" msgid="3081318299464998143">"Abends unter der Woche"</string>
     <string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"Wochenende"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS-Anfrage wurde in USSD-Anfrage geändert"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"In neue SS-Anfrage geändert"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Arbeitsprofil"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Maximieren"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Minimieren"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"Maximierung ein-/auschalten"</string>
@@ -1832,7 +1842,7 @@
     <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
     <string name="usb_midi_peripheral_product_name" msgid="4971827859165280403">"USB-Port für Peripheriegeräte"</string>
     <string name="floating_toolbar_open_overflow_description" msgid="4797287862999444631">"Weitere Optionen"</string>
-    <string name="floating_toolbar_close_overflow_description" msgid="559796923090723804">"Überlauf schließen"</string>
+    <string name="floating_toolbar_close_overflow_description" msgid="559796923090723804">"Dreipunkt-Menü schließen"</string>
     <string name="maximize_button_text" msgid="7543285286182446254">"Maximieren"</string>
     <string name="close_button_text" msgid="3937902162644062866">"Schließen"</string>
     <string name="notification_messaging_title_template" msgid="3452480118762691020">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 6090465..15e4b1c 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Κλήση Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Ανενεργό"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Προτίμηση Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Προτίμηση δικτύου κινητής τηλεφωνίας"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Επιτρέπει στην εφαρμογή την πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας. Αυτό μπορεί να δώσει τη δυνατότητα στην εφαρμογή να παρέμβει στη λειτουργία του GPS ή άλλων πηγών τοποθεσίας."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"πρόσβαση στην ακριβή τοποθεσία μόνο στο προσκήνιο"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την ακριβή τοποθεσία σας όταν βρίσκεται στο προσκήνιο. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στο τηλέφωνό σας, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή. Με την ενεργοποίηση αυτής της ρύθμισης, μπορεί να αυξηθεί η κατανάλωση μπαταρίας."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"έχει πρόσβαση στην τοποθεσία κατά προσέγγιση (με βάση το δίκτυο)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την τοποθεσία σας βάσει πηγών δικτύου, όπως κεραίες κινητής τηλεφωνίας και δίκτυα Wi-Fi. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στο tablet που χρησιμοποιείτε, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την τοποθεσία σας βάσει πηγών δικτύου, όπως κεραίες κινητής τηλεφωνίας και δίκτυα Wi-Fi. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στην τηλεόρασή σας, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την τοποθεσία σας βάσει πηγών δικτύου, όπως κεραίες κινητής τηλεφωνίας και δίκτυα Wi-Fi. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στο τηλέφωνό σας, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"πρόσβαση στην κατά προσέγγιση τοποθεσία (βάσει δικτύου) μόνο στο προσκήνιο"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την τοποθεσία σας βάσει πηγών δικτύου, όπως κεραίες κινητής τηλεφωνίας και δίκτυα Wi-Fi, αλλά μόνο όταν η εφαρμογή βρίσκεται στο προσκήνιο. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στο tablet που χρησιμοποιείτε, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την τοποθεσία σας βάσει πηγών δικτύου, όπως κεραίες κινητής τηλεφωνίας και δίκτυα Wi-Fi, αλλά μόνο όταν η εφαρμογή βρίσκεται στο προσκήνιο. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στην τηλεόρασή σας, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την τοποθεσία σας βάσει πηγών δικτύου, όπως κεραίες κινητής τηλεφωνίας και δίκτυα Wi-Fi, αλλά μόνο όταν η εφαρμογή βρίσκεται στο προσκήνιο. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στο τηλέφωνό σας, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"πρόσβαση στην τοποθεσία στο παρασκήνιο"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Εάν εκχωρηθεί επιπρόσθετα σε μια καταπροσέγγιση ή ακριβή πρόσβαση τοποθεσίας, η εφαρμογή μπορεί να έχει πρόσβαση στην τοποθεσία κατά την εκτέλεση στο παρασκήνιο."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"αλλάζει τις ρυθμίσεις ήχου"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Το αίτημα SS τροποποιήθηκε σε αίτημα USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Τροποποιήθηκε σε νέο αίτημα SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Προφίλ εργασίας"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Ανάπτυξη"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Σύμπτυξη"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"εναλλαγή επέκτασης"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index e102e5b..8b6b404 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi Calling | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Off"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi preferred"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobile preferred"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"access precise location only in the foreground"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"This app can get your exact location only when it is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"access approximate location (network-based)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"This app can pick up your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"This app can pick up your location based on network sources such as mobile towers and Wi-Fi networks. These location services must be turned on and available on your TV for the app to be able to use them."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"This app can get your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your phone for the app to be able to use them."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"access approximate location (network-based) only in the foreground"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your TV for the app to be able to use them."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"access location in the background"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"If this is granted additionally to the approximate or precise location access, the app can access the location while running in the background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"change your audio settings"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS request changed to USSD request"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Changed to new SS request"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Work profile"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Expand"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Collapse"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"toggle expansion"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 518efc9..4929e87 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi Calling | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Off"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi preferred"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobile preferred"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"access precise location only in the foreground"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"This app can get your exact location only when it is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"access approximate location (network-based)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"This app can pick up your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"This app can pick up your location based on network sources such as mobile towers and Wi-Fi networks. These location services must be turned on and available on your TV for the app to be able to use them."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"This app can get your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your phone for the app to be able to use them."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"access approximate location (network-based) only in the foreground"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your TV for the app to be able to use them."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"access location in the background"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"If this is granted additionally to the approximate or precise location access, the app can access the location while running in the background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"change your audio settings"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS request changed to USSD request"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Changed to new SS request"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Work profile"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Expand"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Collapse"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"toggle expansion"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index e102e5b..8b6b404 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi Calling | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Off"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi preferred"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobile preferred"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"access precise location only in the foreground"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"This app can get your exact location only when it is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"access approximate location (network-based)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"This app can pick up your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"This app can pick up your location based on network sources such as mobile towers and Wi-Fi networks. These location services must be turned on and available on your TV for the app to be able to use them."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"This app can get your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your phone for the app to be able to use them."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"access approximate location (network-based) only in the foreground"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your TV for the app to be able to use them."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"access location in the background"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"If this is granted additionally to the approximate or precise location access, the app can access the location while running in the background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"change your audio settings"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS request changed to USSD request"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Changed to new SS request"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Work profile"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Expand"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Collapse"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"toggle expansion"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index e102e5b..8b6b404 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi Calling | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Off"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi preferred"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobile preferred"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"access precise location only in the foreground"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"This app can get your exact location only when it is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"access approximate location (network-based)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"This app can pick up your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"This app can pick up your location based on network sources such as mobile towers and Wi-Fi networks. These location services must be turned on and available on your TV for the app to be able to use them."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"This app can get your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your phone for the app to be able to use them."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"access approximate location (network-based) only in the foreground"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your TV for the app to be able to use them."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"This app can get your location based on network sources such as phone masts and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"access location in the background"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"If this is granted additionally to the approximate or precise location access, the app can access the location while running in the background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"change your audio settings"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS request changed to USSD request"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Changed to new SS request"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Work profile"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Expand"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Collapse"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"toggle expansion"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 29a797b..b646d86b 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -136,6 +136,10 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‎‎‏‏‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‎‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="SPN">%s</xliff:g>‎‏‎‎‏‏‏‎ Wi-Fi‎‏‎‎‏‎"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‎‎‏‎WiFi Calling | ‎‏‎‎‏‏‎<xliff:g id="SPN">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‎‎‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="SPN">%s</xliff:g>‎‏‎‎‏‏‏‎ VoWifi‎‏‎‎‏‎"</string>
+    <string name="wfcSpnFormat_wifi_calling" msgid="4990486735013125329">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‏‏‎‏‎‎‎‏‎Wi-Fi Calling‎‏‎‎‏‎"</string>
+    <string name="wfcSpnFormat_wifi" msgid="1892673884655959773">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎Wi-Fi‎‏‎‎‏‎"</string>
+    <string name="wfcSpnFormat_wifi_calling_wo_hyphen" msgid="1336669776254502831">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‏‎WiFi Calling‎‏‎‎‏‎"</string>
+    <string name="wfcSpnFormat_vowifi" msgid="1765176406171272629">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎VoWifi‎‏‎‎‏‎"</string>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‏‎‎‏‎‎‎‏‎‎Off‎‏‎‎‏‎"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‎Wi-Fi preferred‎‏‎‎‏‎"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎Mobile preferred‎‏‎‎‏‎"</string>
@@ -417,10 +421,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources.‎‏‎‎‏‎"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‎‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‏‎access precise location only in the foreground‎‏‎‎‏‎"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‏‏‎‏‏‏‎‎‎‎‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‎‎This app can get your exact location only when it is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption.‎‏‎‎‏‎"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎access approximate location (network-based)‎‏‎‎‏‎"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎This app can get your location based on network sources such as cell towers and Wi-Fi networks. These location services must be turned on and available on your tablet for the app to be able to use them.‎‏‎‎‏‎"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‏‏‎This app can get your location based on network sources such as cell towers and Wi-Fi networks. These location services must be turned on and available on your TV for the app to be able to use them.‎‏‎‎‏‎"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‏‏‎‏‎‎‎‎‎‎‎‎‏‏‎This app can get your location based on network sources such as cell towers and Wi-Fi networks. These location services must be turned on and available on your phone for the app to be able to use them.‎‏‎‎‏‎"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‎access approximate location (network-based) only in the foreground‎‏‎‎‏‎"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎This app can get your location based on network sources such as cell towers and Wi-Fi networks, but only when when the app is in the foreground. These location services must be turned on and available on your tablet for the app to be able to use them.‎‏‎‎‏‎"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‎‏‏‎‎This app can get your location based on network sources such as cell towers and Wi-Fi networks, but only when when the app is in the foreground. These location services must be turned on and available on your TV for the app to be able to use them.‎‏‎‎‏‎"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‏‏‎‏‎‏‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎‏‎‎This app can get your location based on network sources such as cell towers and Wi-Fi networks, but only when the app is in the foreground. These location services must be turned on and available on your phone for the app to be able to use them.‎‏‎‎‏‎"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‏‎‎‎‏‏‎‎access location in the background‎‏‎‎‏‎"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‎If this is granted additionally to the approximate or precise location access the app can access the location while running in the background.‎‏‎‎‏‎"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‎‏‎‏‎‎‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎change your audio settings‎‏‎‎‏‎"</string>
@@ -1825,6 +1829,7 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‎‏‎‏‎‏‏‏‎‎‎‏‎SS request changed to USSD request‎‏‎‎‏‎"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‏‏‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‏‏‎‎Changed to new SS request‎‏‎‎‏‎"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‏‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎‏‏‎‎‎Work profile‎‏‎‎‏‎"</string>
+    <string name="notification_alerted_content_description" msgid="1296617716556420585">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎‎‏‎Alerted‎‏‎‎‏‎"</string>
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‏‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‏‏‏‎‎‎‏‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‎Expand‎‏‎‎‏‎"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‏‎Collapse‎‏‎‎‏‎"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‎‏‏‏‎‎toggle expansion‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 254d6bb..c51e1aa 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi de <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Llamada por Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi de <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Desactivada"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Red Wi-Fi preferida"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Red móvil preferida"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite que la aplicación acceda a comandos adicionales del proveedor de ubicación. Esto puede permitirle a la aplicación interferir con el funcionamiento del GPS o de otras fuentes de ubicación."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"acceder a la ubicación exacta solo en primer plano"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Esta app puede obtener tu ubicación exacta solo cuando está en primer plano. Los servicios de ubicación deben estar activados y disponibles en el teléfono para que la app pueda usarlos. Es posible que aumente el consumo de batería."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"acceder a la ubicación aproximada (según la red)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Esta app puede obtener tu ubicación a través de fuentes de red, como torres de telefonía móvil y redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles en tu tablet para que la app pueda usarlos."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Esta app puede obtener tu ubicación a través de fuentes de red, telefonía móvil y redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles en tu TV para que la app pueda usarlos."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Esta app puede obtener tu ubicación a través de fuentes de red, como torres de celulares y redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles en tu teléfono para que la app pueda usarlos."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"acceso a la ubicación aproximada (mediante red) solo en primer plano"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Esta app puede obtener tu ubicación desde fuentes de red, como torres de telefonía celular y redes Wi-Fi, pero solo en primer plano. Los servicios de ubicación deben estar activados y disponibles en tu tablet para que la app pueda usarlos."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Esta app puede obtener tu ubicación desde fuentes de red, como torres de telefonía celular y redes Wi-Fi, pero solo en primer plano. Los servicios de ubicación deben estar activados y disponibles en tu TV para que la app pueda usarlos."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Esta app puede obtener tu ubicación desde fuentes de red, como torres de telefonía celular y redes Wi-Fi, pero solo en primer plano. Los servicios de ubicación deben estar activados y disponibles en tu teléfono para que la app pueda usarlos."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"acceder a la ubicación en segundo plano"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Si este permiso se otorga de manera adicional para aproximar o precisar el acceso a la ubicación, la app podrá acceder a la ubicación mientras se ejecuta en segundo plano."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"cambiar tu configuración de audio"</string>
@@ -643,11 +651,11 @@
     <string name="permlab_access_notification_policy" msgid="4247510821662059671">"Acceso a la función No interrumpir"</string>
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permite que la aplicación lea y modifique la configuración de la función No interrumpir."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
-    <string name="policydesc_limitPassword" msgid="2502021457917874968">"Permite controlar la longitud y los caracteres permitidos en las contraseñas y los PIN para el bloqueo de pantalla."</string>
+    <string name="policydesc_limitPassword" msgid="2502021457917874968">"Controlar la longitud y los caracteres permitidos en las contraseñas y los PIN para el bloqueo de pantalla."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Supervisa los intentos para desbloquear la pantalla"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Controla la cantidad de contraseñas incorrectas ingresadas al desbloquear la pantalla y bloquea la tablet o borra todos los datos de la tablet si se ingresaron demasiadas contraseñas incorrectas."</string>
     <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Permite controlar la cantidad de contraseñas incorrectas que se escriben al desbloquear la pantalla y permite bloquear la TV o borrar todos los datos de la TV si se escriben demasiadas contraseñas incorrectas."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Controla la cantidad de contraseñas ingresadas incorrectamente al desbloquear la pantalla y bloquea el dispositivo o borra todos sus datos si se ingresan demasiadas contraseñas incorrectas."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Supervisar la cantidad de contraseñas ingresadas incorrectamente al desbloquear la pantalla, y bloquear el dispositivo o borrar todos sus datos si se ingresan demasiadas contraseñas incorrectas."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Permite controlar la cantidad de contraseñas incorrectas que se escriben al desbloquear la pantalla y bloquear la tablet, o borrar todos los datos del usuario, si se ingresan demasiadas contraseñas incorrectas."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Permite controlar la cantidad de contraseñas incorrectas que se escriben al desbloquear la pantalla y bloquear la televisión, o borrar todos los datos del usuario, si se ingresan demasiadas contraseñas incorrectas."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Permite controlar la cantidad de contraseñas incorrectas que se escriben al desbloquear la pantalla y bloquear el teléfono, o borrar todos los datos del usuario, si se ingresan demasiadas contraseñas incorrectas."</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Se cambió la solicitud SS por una solicitud USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Se cambió a una nueva solicitud SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Perfil de trabajo"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Expandir"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Contraer"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"activar o desactivar la expansión"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 2472e2b..a7ec220 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi‑Fi de <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Llamada por Wi‑Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWiFi de <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Desactivado"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Dar preferencia a Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferir datos móviles"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite que la aplicación acceda a otros comandos del proveedor de ubicación. De esta forma, la aplicación podrá interferir en el funcionamiento del GPS o de otras fuentes de ubicación."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"acceder a la ubicación exacta solo en primer plano"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Esta aplicación solo puede obtener tu ubicación exacta cuando está en primer plano. Estos servicios de ubicación deben estar activados y disponibles en tu teléfono para que la aplicación pueda utilizarlos. Es posible que aumente el consumo de batería."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"acceder a tu ubicación aproximada (basada en red)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Esta aplicación puede obtener tu ubicación a partir de fuentes de red como las antenas de telefonía móvil y las redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles en tu tablet para que la aplicación pueda usarlos."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Esta aplicación puede obtener tu ubicación a partir de fuentes de red como las antenas de telefonía móvil y las redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles en tu TV para que la aplicación pueda usarlos."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Esta aplicación puede obtener tu ubicación a partir de fuentes de red como las antenas de telefonía móvil y las redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles en tu teléfono para que la aplicación pueda usarlos."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"acceder a la ubicación aproximada (a partir de la red) solo en primer plano"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Esta aplicación puede obtener tu ubicación a partir de fuentes de red como las antenas de telefonía móvil y las redes Wi‑Fi, pero únicamente si la aplicación está en primer plano. Estos servicios de ubicación deben estar activados y disponibles en el tablet para que la aplicación pueda usarlos."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Esta aplicación puede obtener tu ubicación a partir de fuentes de red como las antenas de telefonía móvil y las redes Wi‑Fi, pero únicamente si la aplicación está en primer plano. Estos servicios de ubicación deben estar activados y disponibles en la TV para que la aplicación pueda usarlos."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Esta aplicación puede obtener tu ubicación a partir de fuentes de red como las antenas de telefonía móvil y las redes Wi‑Fi, pero únicamente si la aplicación está en primer plano. Estos servicios de ubicación deben estar activados y disponibles en el teléfono para que la aplicación pueda usarlos."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"acceder a la ubicación en segundo plano"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Si se concede este permiso además del acceso a la ubicación exacta o aproximada, la aplicación podrá acceder a la ubicación mientras se ejecuta en segundo plano."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"cambiar la configuración de audio"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Se ha cambiado la solicitud de SS a una solicitud de USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Se ha cambiado a una nueva solicitud de SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Perfil de trabajo"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Mostrar"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Ocultar"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"alternar mostrar y ocultar"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index b77b772..05486c2 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g>: WiFi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"WiFi-kõne | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g>: VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Väljas"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"WiFi eelistusega"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Eelistatud on mobiilne andmeside"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Võimaldab rakendusel juurde pääseda asukohapakkuja erikäskudele. See võib lubada rakendusel mõjutada GPS-i või muude asukohaallikate tööd."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"juurdepääs täpsele asukohale ainult esiplaanil"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"See rakendus hangib teie täpse asukoha ainult siis, kui see töötab esiplaanil. Need asukohateenused peavad olema sisse lülitatud ja teie telefonis saadaval, et rakendus saaks neid kasutada. See võib suurendada akutoite tarbimist."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"juurdepääs ligikaudsele asukohale (võrgupõhine)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"See rakendus näeb võrguallikate (nt mobiilimastid ja WiFi-võrgud) abil teie asukohta. Need asukohateenused peavad olema sisse lülitatud ja teie tahvelarvutis saadaval, et rakendus neid kasutada saaks."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"See rakendus näeb võrguallikate (nt mobiilimastid ja WiFi-võrgud) abil teie asukohta. Need asukohateenused peavad olema sisse lülitatud ja teie teleris saadaval, et rakendus neid kasutada saaks."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"See rakendus näeb võrguallikate (nt mobiilimastid ja WiFi-võrgud) abil teie asukohta. Need asukohateenused peavad olema sisse lülitatud ja teie telefonis saadaval, et rakendus neid kasutada saaks."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"pääseda juurde ligikaudsele asukohale (võrgupõhiselt) ainult esiplaanil"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"See rakendus näeb võrguallikate (nt mobiilimastid ja WiFi-võrgud) abil teie asukohta, kuid ainult siis, kui rakendus töötab esiplaanil. Need asukohateenused peavad olema sisse lülitatud ja teie tahvelarvutis saadaval, et rakendus saaks neid kasutada."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"See rakendus näeb võrguallikate (nt mobiilimastid ja WiFi-võrgud) abil teie asukohta, kuid ainult siis, kui rakendus töötab esiplaanil. Need asukohateenused peavad olema sisse lülitatud ja teie teleris saadaval, et rakendus saaks neid kasutada."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"See rakendus näeb võrguallikate (nt mobiilimastid ja WiFi-võrgud) abil teie asukohta, kuid ainult siis, kui rakendus töötab esiplaanil. Need asukohateenused peavad olema sisse lülitatud ja teie telefonis saadaval, et rakendus saaks neid kasutada."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"juurdepääs asukohale taustal"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Kui see on antud ka umbkaudsele või täpsele asukohale juurdepääsu puhul, saab rakendus taustal käitamisel juurdepääsu asukohale."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"muuda heliseadeid"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS-taotlus muudeti USSD-taotluseks"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Muudeti uueks SS-taotluseks"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Tööprofiil"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Laienda"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Ahenda"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"vaheta laiendamist"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 26d8b31..b301568b 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi bidezko deiak | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Desaktibatuta"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi sarea hobesten da"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Datu-konexioa hobesten da"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Kokapen-hornitzailearen agindu gehigarriak atzitzea baimentzen die aplikazioei. Horrela, agian aplikazioek GPSaren edo bestelako kokapenaren iturburuen funtzionamenduan eragina izan dezakete."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"lortu kokapen zehatza aurreko planoan bakarrik"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Aplikazioak zure kokapen zehatza lor dezake aurreko planoan funtzionatzen duenean bakarrik. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu telefonoan, aplikazioak erabil ditzan. Baliteke bateria gehiago erabiltzea."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"atzitu gutxi gorabeherako kokapena (sarean oinarrituta)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Aplikazioak zure kokapenaren berri izan dezake sareen iturburuak (adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak) erabilita. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu tabletan, aplikazioak erabil ditzan."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Aplikazioak zure kokapenaren berri izan dezake sareen iturburuak (adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak) erabilita. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu telebistan, aplikazioak erabil ditzan."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Aplikazioak zure kokapenaren berri izan dezake sareen iturburuak (adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak) erabilita. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu telefonoan, aplikazioak erabil ditzan."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"Atzitu sarean oinarritutako gutxi gorabeherako kokapena aurreko planoan bakarrik"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Aplikazioa aurreko planoan dagoenean, zure kokapenaren berri izan dezake sareen iturburuak erabilita; adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu tabletan, aplikazioak erabil ditzan."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Aplikazioa aurreko planoan dagoenean, zure kokapenaren berri izan dezake sareen iturburuak erabilita; adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu telebistan, aplikazioak erabil ditzan."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Aplikazioa aurreko planoan dagoenean, zure kokapenaren berri izan dezake sareen iturburuak erabilita; adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu telefonoan, aplikazioak erabil ditzan."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"Atzitu kokapena atzeko planoan"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Baimen hau ematen bada kokapen zehatz edo gutxi gorabeherakorako sarbideaz gain, atzeko planoan exekutatu bitartean atzitu ahalko du aplikazioak kokapena."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"aldatu audio-ezarpenak"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS eskaera USSD eskaerara aldatu da"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"SS eskaera berrira aldatu da"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Work profila"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Zabaldu"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Tolestu"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"zabaldu edo tolestu"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 2d6c2ef..00a86ce 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"‏درحال تماس ازطریق WiFi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"خاموش"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"‏Wi-Fi ترجیحی"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"داده شبکه تلفن همراه ارجح است"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"‏به برنامه اجازه می‌دهد به دستورات ارائه‌دهنده مکان تکمیلی دسترسی داشته باشد. این کار ممکن است به برنامه امکان دهد با کارکرد GPS یا منابع دیگر مکان تداخل داشته باشد."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"دسترسی به مکان دقیق فقط در پیش‌زمینه"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"این برنامه فقط زمانی می‌تواند موقعیت مکانی دقیق شما را دریافت کند که در پیش‌زمینه باشد. برای اینکه برنامه بتواند از خدمات مکان استفاده کند، این خدمات باید در تلفنتان روشن و دردسترس باشد. ممکن است با این کار مصرف باتری افزایش یابد."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"دسترسی به مکان تقریبی (مبتنی بر شبکه)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"‏این برنامه می‌تواند براساس منابع شبکه مانند دکل‌های مخابراتی و شبکه‌های Wi-Fi، مکان شما را تشخیص دهد. این خدمات مکان باید روشن و در رایانه لوحی شما دردسترس باشند تا برنامه بتواند از آن‌ها استفاده کند."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"‏این برنامه می‌تواند براساس منابع شبکه مانند دکل‌های مخابراتی و شبکه‌های Wi-Fi، مکان شما را تشخیص دهد. این خدمات مکان باید روشن و در تلویزیون شما دردسترس باشند تا برنامه بتواند از آن‌ها استفاده کند."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"‏این برنامه می‌تواند براساس منابع شبکه مانند دکل‌های مخابراتی و شبکه‌های Wi-Fi، مکان شما را تشخیص دهد. این خدمات مکان باید روشن و در تلفن شما دردسترس باشند تا برنامه بتواند از آن‌ها استفاده کند."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"دسترسی به مکان تقریبی (مبتنی بر شبکه) فقط در پیش‌زمینه"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"‏این برنامه می‌تواند براساس منابع شبکه مانند دکل‌های مخابراتی و شبکه‌های Wi-Fi، مکانتان را تشخیص دهد، اما فقط درصورتی‌که برنامه در پیش‌زمینه باشد. این خدمات مکان باید روشن و در رایانه لوحی شما دردسترس باشند تا برنامه بتواند از آن‌ها استفاده کند."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"‏این برنامه می‌تواند براساس منابع شبکه مانند دکل‌های مخابراتی و شبکه‌های Wi-Fi، مکانتان را تشخیص دهد، اما فقط درصورتی‌که برنامه در پیش‌زمینه باشد. این خدمات مکان باید روشن و در تلویزیون شما دردسترس باشند تا برنامه بتواند از آن‌ها استفاده کند."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"‏این برنامه می‌تواند براساس منابع شبکه مانند دکل‌های مخابراتی و شبکه‌های Wi-Fi، مکانتان را تشخیص دهد، اما فقط درصورتی‌که برنامه در پیش‌زمینه است. این خدمات مکان باید روشن و در تلفن شما دردسترس باشند تا برنامه بتواند از آن‌ها استفاده کند."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"دسترسی به مکان در پس‌زمینه"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"اگر این مجوز نیز برای دسترسی دقیق یا تقریبی به مکان داده شود، برنامه می‌تواند درحین اجرا در پس‌زمینه به مکان دسترسی پیدا کند."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"تغییر تنظیمات صوتی"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"‏درخواست SS به‌ درخواست USSD تغییر کرد"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"‏به‌ درخواست SS جدید تغییر کرد"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"نمایه کاری"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"بزرگ کردن"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"کوچک کردن"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"روشن/خاموش کردن بزرگ‌نمایی"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 39c4912..7fc02df 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi-puhelut | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Ei käytössä"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi ensisijainen"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobiiliverkko ensisijainen"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Antaa sovelluksen käyttää ylimääräisiä sijaintipalvelukomentoja. Sovellus saattaa tällöin häiritä GPS:n tai muiden sijaintilähteiden toimintaa."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"käyttää tarkkaa sijaintia vain etualalla"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Tämä sovellus saa tarkat sijaintitietosi käyttöönsä vain etualalla. Näiden sijaintipalveluiden tulee olla käytössä ja käytettävissä puhelimellasi, jotta sovellus voi käyttää niitä. Tämä voi lisätä akun kulutusta."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"käyttää likimääräistä sijaintia (verkkopohjainen)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Tämä sovellus voi määrittää sijaintisi matkapuhelinverkon tukiasemien, Wi-Fi-verkkojen ja muiden verkkolähteiden perusteella. Näiden sijaintipalveluiden tulee olla käytössä ja käytettävissä tabletillasi, jotta sovellus voi käyttää niitä."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Tämä sovellus voi määrittää sijaintisi matkapuhelinverkon tukiasemien, Wi-Fi-verkkojen ja muiden verkkolähteiden perusteella. Näiden sijaintipalveluiden tulee olla käytössä ja käytettävissä TV:lläsi, jotta sovellus voi käyttää niitä."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Tämä sovellus voi määrittää sijaintisi matkapuhelinverkon tukiasemien, Wi-Fi-verkkojen ja muiden verkkolähteiden perusteella. Näiden sijaintipalveluiden tulee olla käytössä ja käytettävissä puhelimellasi, jotta sovellus voi käyttää niitä."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"käyttää karkeaa verkkoon perustuvaa sijaintia vain etualalla"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Tämä sovellus voi määrittää sijaintisi matkapuhelinverkon tukiasemien, Wi-Fi-verkkojen ja muiden verkkolähteiden perusteella vain jos sovellus on etualalla. Näiden sijaintipalveluiden tulee olla päällä ja käytettävissä tabletilla, jotta sovellus voi käyttää niitä."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Tämä sovellus voi määrittää sijaintisi matkapuhelinverkon tukiasemien, Wi-Fi-verkkojen ja muiden verkkolähteiden perusteella vain jos sovellus on etualalla. Näiden sijaintipalveluiden tulee olla päällä ja käytettävissä televisiossa, jotta sovellus voi käyttää niitä."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Tämä sovellus voi määrittää sijaintisi matkapuhelinverkon tukiasemien, Wi-Fi-verkkojen ja muiden verkkolähteiden perusteella vain jos sovellus on etualalla. Näiden sijaintipalveluiden tulee olla päällä ja käytettävissä puhelimessa, jotta sovellus voi käyttää niitä."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"käytä sijaintia taustalla"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Jos tämä myönnetään karkean tai tarkan sijainnin käyttöoikeuden lisäksi, sovellus voi käyttää sijaintia toimiessaan taustalla."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"muuta ääniasetuksia"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS-pyyntö vaihdettu USSD-pyynnöksi"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Vaihdettu uudeksi SS-pyynnöksi"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Työprofiili"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Laajenna"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Tiivistä"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"Laajenna/tiivistä painikkeella"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index a03f25f..b58a051 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Appels Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"Voix par Wi-Fi <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Désactivé"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Réseau Wi-Fi de préférence"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Connexion cellulaire de préférence"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permet à l\'application d\'accéder à des commandes de localisation supplémentaires offertes par le fournisseur. Elle est ainsi susceptible d\'interférer avec le bon fonctionnement du GPS ou de toute autre source de localisation."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"accéder à votre position précise seulement en avant-plan"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Cette application peut obtenir votre position exacte seulement lorsqu\'elle fonctionne en avant-plan. Ces services de localisation doivent être activés et accessibles sur votre téléviseur pour que l\'application puisse les utiliser. Cela peut entraîner une utilisation accrue de la pile."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"accéder à votre position approximative (réseau)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Cette application peut déterminer votre position à l\'aide de différentes sources de localisation sur le réseau, comme les tours de téléphonie cellulaire et les réseaux Wi-Fi. Ces services de localisation doivent être activés et accessibles sur votre tablette pour que l\'application puisse les utiliser."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Cette application peut déterminer votre position à l\'aide de différentes sources de localisation sur le réseau, comme les tours de téléphonie cellulaire et les réseaux Wi-Fi. Ces services de localisation doivent être activés et accessibles sur votre téléviseur pour que l\'application puisse les utiliser."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Cette application peut déterminer votre position à l\'aide de différentes sources de localisation sur le réseau, comme les tours de téléphonie cellulaire et les réseaux Wi-Fi. Ces services de localisation doivent être activés et accessibles sur votre téléphone pour que l\'application puisse les utiliser."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"accéder à la position approximative (selon les données réseau), mais uniquement lorsque l\'application s\'exécute au premier plan"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Cette application peut déterminer votre position à l\'aide de différentes sources de localisation sur le réseau, comme les tours de téléphonie cellulaire et les réseaux Wi-Fi, mais uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et accessibles sur votre tablette pour que l\'application puisse les utiliser."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Cette application peut déterminer votre position à l\'aide de différentes sources de localisation sur le réseau, comme les tours de téléphonie cellulaire et les réseaux Wi-Fi, mais uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et accessibles sur votre téléviseur pour que l\'application puisse les utiliser."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Cette application peut déterminer votre position à l\'aide de différentes sources de localisation sur le réseau, comme les tours de téléphonie cellulaire et les réseaux Wi-Fi, mais uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et accessibles sur votre téléphone pour que l\'application puisse les utiliser."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"accès à la localisation en arrière-plan"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Si cette autorisation est accordée en plus de l\'accès approximatif ou précis à la localisation, alors l\'application peut accéder à la localisation lorsqu\'elle fonctionne en arrière-plan."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modifier vos paramètres audio"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"La demande SS a été remplacée par une demande USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"La demande a été remplacée par une nouvelle demande SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Profil professionnel"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Développer"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Réduire"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"activer/désactiver le développement"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 5e9d5c1..6f9e0bc 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Appels Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWiFi <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Désactivé"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi de préférence"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Données mobiles de préférence"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permet à l\'application d\'accéder à des commandes de localisation supplémentaires offertes par le fournisseur. Elle est ainsi susceptible d\'interférer avec le bon fonctionnement du GPS ou de toute autre source de localisation."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"accéder à la position exacte au premier plan uniquement"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Cette application peut obtenir votre position exacte uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et disponibles sur votre téléphone pour que l\'application puisse les utiliser. Ceci peut réduire l\'autonomie de la batterie."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"accéder à votre position approximative (selon le réseau)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Cette application peut obtenir votre position via des sources de réseau telles que les antennes-relais et les réseaux Wi-Fi. Ces services de localisation doivent être activés et disponibles sur votre tablette pour que l\'application puisse les utiliser."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Cette application peut obtenir votre position via des sources de réseau telles que les antennes-relais et les réseaux Wi-Fi. Ces services de localisation doivent être activés et disponibles sur votre téléviseur pour que l\'application puisse les utiliser."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Cette application peut obtenir votre position via des sources de réseau telles que les antennes-relais et les réseaux Wi-Fi. Ces services de localisation doivent être activés et disponibles sur votre téléphone pour que l\'application puisse les utiliser."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"accéder à la position approximative (à l\'aide des réseaux) au premier plan uniquement"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Cette application peut obtenir votre position à l\'aide de sources de réseau telles que les antennes-relais et les réseaux Wi-Fi, mais uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et disponibles sur votre tablette pour que l\'application puisse les utiliser."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Cette application peut obtenir votre position à l\'aide de sources de réseau telles que les antennes-relais et les réseaux Wi-Fi, mais uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et disponibles sur votre téléviseur pour que l\'application puisse les utiliser."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Cette application peut obtenir votre position à l\'aide de sources de réseau telles que les antennes-relais et les réseaux Wi-Fi, mais uniquement lorsqu\'elle s\'exécute au premier plan. Ces services de localisation doivent être activés et disponibles sur votre téléphone pour que l\'application puisse les utiliser."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"accéder à la position en arrière-plan"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Si vous lui accordez cette autorisation en plus de l\'accès à la position approximative ou précise, l\'application peut accéder à votre position lorsqu\'elle est s\'exécute en arrière-plan."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modifier vos paramètres audio"</string>
@@ -665,13 +673,13 @@
     <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"Effacer les informations sur cet utilisateur de ce téléphone sans avertissement"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Définir le proxy global du mobile"</string>
     <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Indiquer le proxy global à utiliser pour l\'appareil lorsque la règle est activée. Seul le propriétaire de l\'appareil peut définir le proxy global."</string>
-    <string name="policylab_expirePassword" msgid="5610055012328825874">"Config. expir. mot passe verr. écran"</string>
+    <string name="policylab_expirePassword" msgid="5610055012328825874">"Définir l\'expiration du mot de passe de verrouillage d\'écran"</string>
     <string name="policydesc_expirePassword" msgid="5367525762204416046">"Modifier la fréquence de modification du mot de passe, du code d\'accès ou du schéma de verrouillage de l\'écran"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Définir chiffrement du stockage"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Exiger le chiffrement des données d\'application stockées"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Désactiver les appareils photo"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Empêcher l\'utilisation de tous les appareils photos"</string>
-    <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Désact. options du verr. écran"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Désactiver les options de verrouillage de l\'écran"</string>
     <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Empêcher l\'utilisation de certaines fonctionnalités du verrouillage de l\'écran."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Domicile"</item>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Requête SS transformée en requête USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Remplacement par une nouvelle requête SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Profil professionnel"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Développer"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Réduire"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"activer/désactiver le développement"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index d522b53..7f5a244 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wifi de <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Chamadas por wifi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi de <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Desactivado"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wifi preferida"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Datos móbiles preferidos"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite á aplicación acceder a comandos adicionais de fornecedor de localizacións. É posible que isto provoque que a aplicación interfira co funcionamento do GPS ou doutras fontes da localización."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"acceder á localización exacta só en primeiro plano"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Esta aplicación pode obter a túa localización exacta só cando se atope en primeiro plano. É necesario activar estes servizos de localización e deben estar dispoñibles no teléfono para que a aplicación poida utilizalos. Ademais, poden supoñer un aumento do consumo de batería."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"acceder á localización aproximada (baseada na rede)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Esta aplicación pode obter a túa localización a partir de fontes de rede como torres de telecomunicacións e redes wifi. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles na túa tableta."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Esta aplicación pode obter a túa localización a partir de fontes de rede como torres de telecomunicacións e redes wifi. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles na túa televisión."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Esta aplicación pode obter a túa localización a partir de fontes de rede como torres de telecomunicacións e redes wifi. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles no teu teléfono."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"acceder á localización aproximada a partir de fontes de rede só en primeiro plano"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Esta aplicación pode obter a túa localización a partir de fontes de rede, como torres de telecomunicacións e redes wifi, pero só mentres está en primeiro plano. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles na túa tableta."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Esta aplicación pode obter a túa localización a partir de fontes de rede, como torres de telecomunicacións e redes wifi, pero só mentres está en primeiro plano. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles na túa televisión."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Esta aplicación pode obter a túa localización a partir de fontes de rede, como torres de telecomunicacións e redes wifi, pero só mentres está en primeiro plano. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles no teu teléfono."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"acceder á localización en segundo plano"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Se a aplicación ten acceso á localización aproximada ou exacta e lle concedes este permiso, poderá consultar onde te atopas cando estea en segundo plano."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"cambiar a configuración de son"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"A solicitude SS transformouse nunha solicitude USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Transformouse nunha nova solicitude SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Perfil de traballo"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Despregar"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Contraer"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"alterna a expansión"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 9e9c21e..5f98ff2 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> વાઇ-ફાઇ"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"વાઇ-ફાઇ કૉલિંગ | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"બંધ"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"વાઇ-ફાઇ પસંદ કર્યું"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"મોબાઇલને પસંદગી"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"એપ્લિકેશનને વધારાના સ્થાન પ્રદાતા આદેશોને ઍક્સેસ કરવાની મંજૂરી આપે છે. આ એપ્લિકેશનને GPS અથવા અન્ય સ્થાન સ્રોતોના ઓપરેશનમાં દખલ કરવાની મંજૂરી આપી શકે છે."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"ફૉરગ્રાઉન્ડમાં ફક્ત ચોક્કસ સ્થાન ઍક્સેસ કરો"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"આ ઍપ ફક્ત બૅકગ્રાઉન્ડમાં હોય ત્યારે જ તમારું ચોક્કસ સ્થાન મેળવી શકે છે. ઍપ આ સ્થાન સેવાઓનો ઉપયોગ કરી શકે તે માટે તમારા ફોન પર આ સેવાઓ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે. આ બૅટરી વપરાશ વધારી શકે છે."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"અંદાજિત સ્થાન ઍક્સેસ કરો (નેટવર્ક-આધારિત)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"આ ઍપ્લિકેશન, સેલ ટાવર્સ અને વાઇ-ફાઇ નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ટેબ્લેટ પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"આ ઍપ્લિકેશન, સેલ ટાવર્સ અને વાઇ-ફાઇ નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ટીવી પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"આ ઍપ્લિકેશન, સેલ ટાવર્સ અને વાઇ-ફાઇ નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ફોન પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"અંદાજિત જગ્યાને (નેટવર્ક આધારિત) માત્ર ફૉરગ્રાઉન્ડમાંથી ઍક્સેસ કરો"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"સેલ ટાવર અને વાઇ-ફાઇ નેટવર્ક જેવા નેટવર્ક સૉર્સનો ઉપયોગ કરીને આ અ‍ૅપ તમારી જગ્યા જાણી શકે છે, પરંતુ આ માત્ર ત્યારે શક્ય છે જ્યારે આ અ‍ૅપ ફૉરગ્રાઉન્ડમાં ચાલુ હોય. ઍપ આ જગ્યાની સેવાઓનો ઉપયોગ કરી શકે તે માટે તમારા ટૅબ્લેટ પર આ સેવાઓ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"સેલ ટાવર અને વાઇ-ફાઇ નેટવર્ક જેવા નેટવર્ક સૉર્સનો ઉપયોગ કરીને આ અ‍ૅપ તમારી જગ્યા જાણી શકે છે, પરંતુ આ માત્ર ત્યારે શક્ય છે જ્યારે આ અ‍ૅપ ફૉરગ્રાઉન્ડમાં ચાલુ હોય. ઍપ આ જગ્યાની સેવાઓનો ઉપયોગ કરી શકે તે માટે તમારા ટીવી પર આ સેવાઓ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"સેલ ટાવર અને વાઇ-ફાઇ નેટવર્ક જેવા નેટવર્ક સૉર્સનો ઉપયોગ કરીને આ અ‍ૅપ તમારી જગ્યા જાણી શકે છે, પરંતુ આ માત્ર ત્યારે શક્ય છે જ્યારે આ અ‍ૅપ ફૉરગ્રાઉન્ડમાં ચાલુ હોય. ઍપ આ જગ્યાની સેવાઓનો ઉપયોગ કરી શકે તે માટે તમારા ફોન પર આ સેવાઓ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"બૅકગ્રાઉન્ડમાં સ્થાન ઍક્સેસ કરો"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"જો અંદાજિત અથવા ચોક્કસ સ્થાનના ઍક્સેસ ઉપરાંત આને પરવાનગી આપવામાં આવી હશે, તો ઍપ બૅકગ્રાઉન્ડમાં ચાલતી હોય ત્યારે સ્થાનને ઍક્સેસ કરી શકશે."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"તમારી ઑડિઓ સેટિંગ્સ બદલો"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS વિનંતીને USSD વિનંતીમાં બદલવામાં આવી છે"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"નવી SS વિનંતીમાં બદલવામાં આવી છે"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"કાર્યાલયની પ્રોફાઇલ"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"વિસ્તૃત કરો"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"સંકુચિત કરો"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"વિસ્તરણ ટૉગલ કરો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 87b35c9..92e3ae5 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> वाई-फ़ाई"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"वाई-फ़ाई कॉलिंग | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"बंद"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"वाई-फ़ाई को प्राथमिकता"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"मोबाइल को प्राथमिकता"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ऐप को कुछ और जगह की जानकारी देने वाले आदेशों की पहुंच पाने देता है. इससे ऐप जीपीएस या जगह की जानकारी देने वाले दूसरे स्रोतों के काम में रोक-टोक कर सकता है."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"ऐप्लिकेशन \'जगह की सटीक जानकारी\' सिर्फ़ सामने खुली होने पर एक्सेस करे"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"यह ऐप्लिकेशन सिर्फ़ तब आपकी \'जगह की सटीक जानकारी\' का इस्तेमाल कर सकता है जब यह स्क्रीन पर दिखाई दे रहा हो. यह ज़रूरी है कि \'जगह की जानकारी\' वाली ये सेवाएं आपके फ़ोन में मौजूद हों और चालू की गई हों ताकि ऐप्लिकेशन उनका इस्तेमाल कर पाए. ऐसा करने से ज़्यादा बैटरी खर्च हो सकती है."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"अनुमानित जगह की पहुंच दें (नेटवर्क-आधारित)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"यह ऐप सेल टावर और वाई-फ़ाई नेटवर्क जैसे नेटवर्क के स्रोतों के आधार पर आपकी जगह का पता कर सकता है. ये जगह की जानकारी आपके टैबलेट पर चालू और मौजूद होनी चाहिए ताकि ऐप उनका इस्तेमाल कर सके."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"यह ऐप सेल टावर और वाई-फ़ाई नेटवर्क जैसे नेटवर्क के स्रोतों के आधार पर आपकी जगह का पता कर सकता है. ये जगह की जानकारी आपके टीवी पर चालू और मौजूद होनी चाहिए ताकि ऐप उनका इस्तेमाल कर सके."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"यह ऐप सेल टावर और वाई-फ़ाई नेटवर्क जैसे नेटवर्क के स्रोतों के आधार पर आपकी जगह का पता कर सकता है. ये जगह की जानकारी आपके फ़ोन पर चालू और मौजूद होनी चाहिए ताकि ऐप उनका इस्तेमाल कर सके."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"स्क्रीन पर दिखाई देते समय \'जगह की अनुमानित जानकारी\' (नेटवर्क-आधारित) एक्सेस करें"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"यह ऐप्लिकेशन सेल टावर और वाई-फ़ाई नेटवर्क जैसे नेटवर्क स्रोतों के आधार पर आपकी जगह का पता लगा सकता है, लेकिन सिर्फ़ तब जब ऐप्लिकेशन स्क्रीन पर दिखाई दे रहा हो. यह ज़रूरी है कि \'जगह की जानकारी\' वाली ये सेवाएं आपके टैबलेट में मौजूद हों और चालू की गई हों ताकि ऐप्लिकेशन उनका इस्तेमाल कर पाए."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"यह ऐप्लिकेशन सेल टावर और वाई-फ़ाई नेटवर्क जैसे नेटवर्क स्रोतों के आधार पर आपकी जगह का पता लगा सकता है, लेकिन सिर्फ़ तब जब ऐप्लिकेशन स्क्रीन पर दिखाई दे रहा हो. यह ज़रूरी है कि \'जगह की जानकारी\' वाली ये सेवाएं आपके टीवी पर मौजूद हों और चालू की गई हों ताकि ऐप्लिकेशन उनका इस्तेमाल कर पाए."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"यह ऐप्लिकेशन सेल टावर और वाई-फ़ाई नेटवर्क जैसे नेटवर्क स्रोतों के आधार पर आपकी जगह का पता लगा सकता है, लेकिन सिर्फ़ तब, जब ऐप्लिकेशन स्क्रीन पर दिखाई दे रहा हो. यह ज़रूरी है कि \'जगह की जानकारी\' वाली ये सेवाएं आपके फ़ोन में मौजूद हों और चालू की गई हों ताकि ऐप्लिकेशन उनका इस्तेमाल कर पाए."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"बैकग्राउंड में जगह की जानकारी एक्सेस करना"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"अनुमानित या बिल्कुल सही जगह की जानकारी का एक्सेस करने की अनुमति अलग से दिए जाने पर, बैकग्राउंड में चलने के दौरान ऐप्लिकेशन आपकी जगह की जानकारी एक्सेस कर सकता है."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"अपनी ऑडियो सेटिंग बदलें"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"एसएस कोड चलाने के अनुरोध को यूएसएसडी कोड चलाने के अनुरोध में बदला गया"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"एसएस कोड चलाने के नए अनुरोध में बदला गया"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"कार्य प्रोफ़ाइल"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"विस्तार करें"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"छोटा करें"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"टॉगल विस्तार"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 7b24bba..7e581a20 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -137,6 +137,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi pozivi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Isključeno"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Prednost ima Wi-Fi mreža"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Za mobilne uređaje"</string>
@@ -222,7 +230,7 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Opcije telefona"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Zaključavanje zaslona"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Isključi"</string>
-    <string name="global_action_emergency" msgid="7112311161137421166">"Hitno"</string>
+    <string name="global_action_emergency" msgid="7112311161137421166">"Hitne službe"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Izvješće o bugovima"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Završi sesiju"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Snimka zaslona"</string>
@@ -420,10 +428,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Omogućuje aplikaciji pristup dodatnim naredbama davatelja usluga lokacije. To može omogućiti aplikaciji ometanje rada GPS-a ili drugih izvora lokacije."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"pristupiti preciznoj lokaciji samo u prednjem planu"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Aplikacija može dobiti vašu točnu lokaciju samo kada je u prednjem planu. Te usluge lokacije moraju biti uključene i dostupne na telefonu da bi ih aplikacija mogla upotrebljavati. To može pojačati potrošnju baterije."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"pristupati približnoj lokaciji (na temelju mreža)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Aplikacija može dohvatiti vašu lokaciju putem mrežnih izvora poput baznih stanica i Wi-Fi mreža. Te usluge lokacije moraju biti uključene i dostupne na tabletu da bi ih aplikacija mogla upotrebljavati."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Aplikacija može dohvatiti vašu lokaciju putem mrežnih izvora poput baznih stanica i Wi-Fi mreža. Te usluge lokacije moraju biti uključene i dostupne na televizoru da bi ih aplikacija mogla upotrebljavati."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Aplikacija može dohvatiti vašu lokaciju putem mrežnih izvora poput baznih stanica i Wi-Fi mreža. Te usluge lokacije moraju biti uključene i dostupne na telefonu da bi ih aplikacija mogla upotrebljavati."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"pristupiti približnoj lokaciji (na temelju mreže) samo u prednjem planu"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Ova aplikacija može dobiti vašu lokaciju na temelju mrežnih izvora kao što su bazne stanice i Wi-Fi mreže, no samo kad je u prednjem planu. Te usluge lokacije moraju biti uključene i dostupne na vašem tabletu da bi ih aplikacija mogla upotrebljavati."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Ova aplikacija može dobiti vašu lokaciju na temelju mrežnih izvora kao što su bazne stanice i Wi-Fi mreže, no samo kad je u prednjem planu. Te usluge lokacije moraju biti uključene i dostupne na vašem televizoru da bi ih aplikacija mogla upotrebljavati."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Ova aplikacija može dobiti vašu lokaciju na temelju mrežnih izvora kao što su bazne stanice i Wi-Fi mreže, no samo kad je u prednjem planu. Te usluge lokacije moraju biti uključene i dostupne na vašem telefonu da bi ih aplikacija mogla upotrebljavati."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"pristup lokaciji u pozadini"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ako se ovo odobrava dodatno za pristup približnoj ili preciznoj lokaciji, aplikacija može pristupiti lokaciji tijekom rada u pozadini."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"promjena postavki zvuka"</string>
@@ -805,7 +813,7 @@
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Pritisnite Izbornik za otključavanje ili pozivanje hitnih službi."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Pritisnite Izbornik za otključavanje."</string>
     <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Iscrtajte uzorak za otključavanje"</string>
-    <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Hitno"</string>
+    <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Hitne službe"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Uzvrati poziv"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Ispravno!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Pokušajte ponovo"</string>
@@ -1858,6 +1866,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS zahtjev promijenjen je u USSD zahtjev"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Promijenjeno u novi SS zahtjev"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Radni profil"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Proširivanje"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Sažimanje"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"promjena proširenja"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index b02b68b..41bf09b 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi-hívás | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Ki"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi előnyben részesítve"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferált: mobil"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Lehetővé teszi az alkalmazás számára további helyszolgáltatói parancsok elérését. Ezáltal az alkalmazás beavatkozhat a GPS vagy más helyforrások működésébe."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"pontos helyadatokhoz való hozzáférés csak előtérben"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Ez az alkalmazás csak akkor férhet hozzá az eszköz pontos helyadataihoz, amikor az előtérben fut. A helyszolgáltatásoknak bekapcsolt és hozzáférhető állapotban kell lenniük a telefonon ahhoz, hogy az alkalmazás használhassa őket. Ez növelheti az akkumulátorhasználatot."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"hozzáférés a hozzávetőleges (hálózatalapú) helyadatokhoz"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Az alkalmazás hozzáférhet hálózati forrásokon (például az adótornyokon és a Wi-Fi-hálózatokon) alapuló helyadataihoz. A helyszolgáltatásoknak bekapcsolt és elérhető állapotban kell lenniük a táblagépen ahhoz, hogy az alkalmazás használhassa őket."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Az alkalmazás hozzáférhet hálózati forrásokon (például az adótornyokon és a Wi-Fi-hálózatokon) alapuló helyadataihoz. A helyszolgáltatásoknak bekapcsolt és elérhető állapotban kell lenniük a TV-n ahhoz, hogy az alkalmazás használhassa őket."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Az alkalmazás hozzáférhet hálózati forrásokon (például az adótornyokon és a Wi-Fi-hálózatokon) alapuló helyadataihoz. A helyszolgáltatásoknak bekapcsolt és elérhető állapotban kell lenniük a telefonon ahhoz, hogy az alkalmazás használhassa őket."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"hozzávetőleges (hálózaton alapuló) helyadatokhoz való hozzáférés csak előtérben"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Ez az alkalmazás hozzáférhet a hálózati forrásokon (például az adótornyokon és a Wi-Fi-hálózatokon) alapuló helyadataihoz, de csak akkor, amikor az előtérben fut. A helyszolgáltatásoknak bekapcsolt és hozzáférhető állapotban kell lenniük a táblagépen ahhoz, hogy az alkalmazás használhassa őket."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Ez az alkalmazás hozzáférhet a hálózati forrásokon (például az adótornyokon és a Wi-Fi-hálózatokon) alapuló helyadataihoz, de csak akkor, amikor az előtérben fut. A helyszolgáltatásoknak bekapcsolt és hozzáférhető állapotban kell lenniük a tévén ahhoz, hogy az alkalmazás használhassa őket."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Ez az alkalmazás hozzáférhet a hálózati forrásokon (például az adótornyokon és a Wi-Fi-hálózatokon) alapuló helyadataihoz, de csak akkor, amikor az előtérben fut. A helyszolgáltatásoknak bekapcsolt és hozzáférhető állapotban kell lenniük a telefonon ahhoz, hogy az alkalmazás használhassa őket."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"Hozzáférés a helyadatokhoz a háttérben"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ha engedélyezi ezt a hozzávetőleges vagy pontos helyadatokhoz való hozzáférés mellett, akkor az alkalmazás hozzáférhet a helyadatokhoz, miközben a háttérben fut."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"hangbeállítások módosítása"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Az SS-kérés módosítva USSD-kérésre"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Új SS-kérésre módosítva"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Munkaprofil"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Kibontás"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Összecsukás"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"kibontás be- és kikapcsolása"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 90ab955..30721cf 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Զանգեր Wi-Fi-ի միջոցով | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Անջատված է"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi, նախընտրելի"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Նախընտրելի է բջջային ցանցը"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Ծրագրին թույլ է տալիս օգտագործել տեղադրության մասին տվյալների աղբյուրների կառավարման լրացուցիչ հրահանգներ: Սա կարող է ծրագրին թույլ տալ միջամտել GPS-ի կամ տեղադրության մասին տվյալների այլ աղբյուրների գործառույթներին:"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"Տեղադրության ճշգրիտ տվյալների հասանելիություն միայն ֆոնային ռեժիմում"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ֆոնային ռեժիմում։ Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր հեռախոսում, որպեսզի հավելվածը կարողանա օգտագործել դրանք: Սա կարող է արագացնել մարտկոցի լիցքի սպառումը:"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"օգտագործել մոտավոր տեղադրությունը (ցանցային)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր պլանշետում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր հեռուստացույցում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր հեռախոսում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"Մոտավոր տեղադրությունը (ցանցային) հասանելի է միայն ֆոնային ռեժիմում"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից, սակայն միայն երբ հավելվածն աշխատում է ֆոնային ռեժիմում: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր պլանշետում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից, սակայն միայն երբ հավելվածն աշխատում է ֆոնային ռեժիմում: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր հեռուստացույցում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից, սակայն միայն երբ հավելվածն աշխատում է ֆոնային ռեժիմում: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր հեռախոսում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"տեղադրության մասին տվյալների հասանելիություն ֆոնային ռեժիմում"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Եթե բացի մոտավոր կամ ճշգրիտ տեղորոշման տվյալների հասանելիությունից հավելվածին տրամադրեք այս թույլտվությունը, հավելվածին տեղադրության մասին տվյալները հասանելի կլինեն ֆոնային ռեժիմում։"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"փոխել ձեր աուդիո կարգավորումները"</string>
@@ -1139,8 +1147,8 @@
     <string name="noApplications" msgid="2991814273936504689">"Ոչ մի հավելված չի կարող կատարել այս գործողությունը:"</string>
     <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> – աշխատանքն ընդհատվեց"</string>
     <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> գործընթացն ընդհատվել է"</string>
-    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածի աշխատանքը շարունակաբար ընդհատվում է"</string>
-    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> գործընթացը շարունակաբար ընդհատվում է"</string>
+    <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g>-ն էլի ընդհատվեց"</string>
+    <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g>՝ նորից ընդհատվեց"</string>
     <string name="aerr_restart" msgid="7581308074153624475">"Կրկին բացել հավելվածը"</string>
     <string name="aerr_report" msgid="5371800241488400617">"Հաղորդել"</string>
     <string name="aerr_close" msgid="2991640326563991340">"Փակել"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS հարցումը փոխվել է USSD հարցման"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Փոխվել է նոր SS հարցման"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Աշխատանքային պրոֆիլ"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Ընդարձակել"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Կոծկել"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"Կոծկել/Ընդարձակել"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 924b264..49c80d7 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Panggilan WiFi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Nonaktif"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi dipilih"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Seluler dipilih"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Memungkinkan aplikasi mengakses perintah penyedia lokasi ekstra. Tindakan ini memungkinkan aplikasi mengganggu pengoperasian GPS atau sumber lokasi lain."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"akses lokasi pasti hanya saat di latar depan"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Aplikasi ini bisa mendapatkan lokasi pasti Anda ketika aplikasi berada di latar depan. Fitur layanan lokasi ini harus diaktifkan dan tersedia di ponsel agar dapat digunakan oleh aplikasi. Fitur ini dapat meningkatkan konsumsi baterai."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"akses perkiraan lokasi (berbasis jaringan)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Aplikasi ini dapat memperoleh lokasi Anda berdasarkan sumber jaringan seperti menara seluler dan jaringan Wi-Fi. Layanan lokasi ini harus diaktifkan dan tersedia di tablet agar aplikasi dapat menggunakannya."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Aplikasi ini dapat memperoleh lokasi Anda berdasarkan sumber jaringan seperti menara seluler dan jaringan Wi-Fi. Layanan lokasi ini harus diaktifkan dan tersedia di TV agar aplikasi dapat menggunakannya."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Aplikasi ini dapat memperoleh lokasi Anda berdasarkan sumber jaringan seperti menara seluler dan jaringan Wi-Fi. Layanan lokasi ini harus diaktifkan dan tersedia di ponsel agar aplikasi dapat menggunakannya."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"akses perkiraan lokasi (berbasis jaringan) hanya di latar depan"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Aplikasi ini dapat mengetahui lokasi berdasarkan sumber jaringan seperti menara seluler dan jaringan Wi-Fi, namun hanya jika aplikasi berada di latar depan. Layanan lokasi tersebut harus diaktifkan dan tersedia di tablet agar aplikasi dapat menggunakannya."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Aplikasi ini dapat mengetahui lokasi berdasarkan sumber jaringan seperti menara seluler dan jaringan Wi-Fi, namun hanya jika aplikasi berada di latar depan. Layanan lokasi tersebut harus diaktifkan dan tersedia di TV agar aplikasi dapat menggunakannya."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Aplikasi ini dapat mengetahui lokasi berdasarkan sumber jaringan seperti menara seluler dan jaringan Wi-Fi, namun hanya jika aplikasi berada di latar depan. Layanan lokasi tersebut harus diaktifkan dan tersedia di ponsel agar aplikasi dapat menggunakannya."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"akses lokasi di latar belakang"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Jika aplikasi diberi izin tambahan ke akses lokasi perkiraan atau akurat, aplikasi dapat mengakses lokasi saat bekerja di latar belakang."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ubah setelan audio Anda"</string>
@@ -644,19 +652,19 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Mengizinkan aplikasi membaca dan menulis konfigurasi status Jangan Ganggu."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Mengontrol panjang dan karakter yang diizinkan dalam sandi dan PIN kunci layar."</string>
-    <string name="policylab_watchLogin" msgid="5091404125971980158">"Memantau upaya pembukaan kunci layar"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Memantau jumlah sandi yang salah ketik saat membuka kunci layar, dan mengunci tablet atau menghapus semua data tablet jika sandi yang salah ketik terlalu banyak."</string>
-    <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Memantau banyaknya sandi salah yang diketikkan saat membuka kunci layar, dan mengunci TV atau menghapus semua data TV jika terlalu banyak sandi salah diketikkan."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Memantau jumlah sandi salah ketik saat membuka kunci layar, dan mengunci ponsel atau menghapus semua data ponsel jika sandi yang salah ketik terlalu banyak."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Memantau banyaknya sandi salah yang diketikkan saat membuka kunci layar, dan mengunci tablet atau menghapus semua data pengguna ini jika terlalu banyak sandi salah diketikkan."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Memantau banyaknya sandi salah yang diketikkan saat membuka kunci layar, dan mengunci TV atau menghapus semua data pengguna ini jika terlalu banyak sandi salah diketikkan."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Memantau banyaknya sandi salah yang diketikkan saat membuka kunci layar, dan mengunci ponsel atau menghapus semua data pengguna ini jika terlalu banyak sandi salah diketikkan."</string>
+    <string name="policylab_watchLogin" msgid="5091404125971980158">"Pantau upaya pembukaan kunci layar"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci tablet atau menghapus semua data tablet jika terjadi terlalu banyak kesalahan memasukkan sandi."</string>
+    <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci TV atau menghapus semua data TV jika terjadi terlalu banyak kesalahan memasukkan sandi."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci ponsel atau menghapus semua data ponsel jika terjadi terlalu banyak kesalahan memasukkan sandi."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci tablet atau menghapus semua data pengguna ini jika terjadi terlalu banyak kesalahan memasukkan sandi."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci TV atau menghapus semua data pengguna ini jika terjadi terlalu banyak kesalahan memasukkan sandi."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci ponsel atau menghapus semua data pengguna ini jika terjadi terlalu banyak kesalahan memasukkan sandi."</string>
     <string name="policylab_resetPassword" msgid="4934707632423915395">"Mengubah kunci layar"</string>
     <string name="policydesc_resetPassword" msgid="1278323891710619128">"Mengubah kunci layar."</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Mengunci layar"</string>
     <string name="policydesc_forceLock" msgid="1141797588403827138">"Mengontrol cara dan kapan layar mengunci."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Menghapus semua data"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Hapus data tablet tanpa peringatan dengan menyetel ulang data pabrik."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Menghapus data tablet tanpa peringatan dengan mereset ke setelan pabrik."</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Menghapus data TV tanpa peringatan dengan mengembalikan ke setelan pabrik."</string>
     <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Menghapus data ponsel tanpa peringatan dengan melakukan reset ke setelan pabrik."</string>
     <string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"Menghapus data pengguna"</string>
@@ -665,13 +673,13 @@
     <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"Menghapus data pengguna ini di ponsel ini tanpa peringatan."</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Setel proxy global perangkat"</string>
     <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Menyetel proxy global perangkat yang akan digunakan jika kebijakan diaktifkan. Hanya pemilik perangkat yang dapat menyetel proxy global."</string>
-    <string name="policylab_expirePassword" msgid="5610055012328825874">"Menyetel berakhirnya sandi kunci layar"</string>
+    <string name="policylab_expirePassword" msgid="5610055012328825874">"Setel akhir masa berlaku sandi kunci layar"</string>
     <string name="policydesc_expirePassword" msgid="5367525762204416046">"Mengubah seberapa sering sandi, PIN, atau pola kunci layar harus diubah."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setel enkripsi penyimpanan"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Mengharuskan data apl yang disimpan untuk dienkripsi."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Nonaktifkan kamera"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Mencegah penggunaan semua kamera perangkat."</string>
-    <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Menonaktifkan beberapa fitur kunci layar"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Nonaktifkan beberapa fitur kunci layar"</string>
     <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Mencegah penggunaan beberapa fitur kunci layar."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Rumah"</item>
@@ -824,7 +832,7 @@
     <string name="lockscreen_transport_stop_description" msgid="5907083260651210034">"Berhenti"</string>
     <string name="lockscreen_transport_rew_description" msgid="6944412838651990410">"Putar Ulang"</string>
     <string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"Maju cepat"</string>
-    <string name="emergency_calls_only" msgid="6733978304386365407">"Telepon urgen saja"</string>
+    <string name="emergency_calls_only" msgid="6733978304386365407">"Panggilan darurat saja"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"Jaringan terkunci"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Kartu SIM terkunci PUK."</string>
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Lihatlah Panduan Pengguna atau hubungi Layanan Pelanggan."</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Permintaan SS diubah ke permintaan USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Diubah ke permintaan SS baru"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Profil kerja"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Luaskan"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Ciutkan"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"beralih ke perluasan"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 1be394a..a33c80c 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi símtal | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Slökkt"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi í forgangi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Farsímakerfi í forgangi"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Leyfir forriti að fá aðgang að fleiri skipunum staðsetningarveitu. Þetta getur gert forritinu kleift að hafa áhrif á virkni GPS og annars staðsetningarbúnaðar."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"aðgangur að nákvæmri staðsetningu aðeins í forgrunni"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Þetta forrit getur aðeins séð staðsetningu þína þegar það er í forgrunni. Það verður að vera kveikt á þessari staðsetningarþjónustu og hún þarf að vera aðgengileg í símanum til að forritið geti notað hana. Þetta getur aukið rafhlöðunotkun."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"fá aðgang að áætlaðri staðsetningu (frá símkerfi)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Þetta forrit getur séð staðsetningu þína út frá netkerfum á borð við farsímasenda og Wi-Fi net. Það verður að vera kveikt á slíkri staðsetningarþjónustu og hún þarf að vera aðgengileg spjaldtölvunni til að forritið geti notað hana."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Þetta forrit getur séð staðsetningu þína út frá netkerfum á borð við farsímasenda og Wi-Fi net. Það verður að vera kveikt á slíkri staðsetningarþjónustu og hún þarf að vera aðgengileg sjónvarpinu til að forritið geti notað hana."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Þetta forrit getur séð staðsetningu þína út frá netkerfum á borð við farsímasenda og Wi-Fi net. Það verður að vera kveikt á slíkri staðsetningarþjónustu og hún þarf að vera aðgengileg símanum til að forritið geti notað hana."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"aðgangur að áætlaðri staðsetningu (út frá netkerfi), aðeins í forgrunni"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Þetta forrit getur séð staðsetningu þína út frá netkerfum á borð við farsímasenda og Wi-Fi net, en þó aðeins þegar það er í forgrunni. Það verður að vera kveikt á þessari staðsetningarþjónustu og hún þarf að vera aðgengileg spjaldtölvunni til að forritið geti notað hana."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Þetta forrit getur séð staðsetningu þína út frá netkerfum á borð við farsímasenda og Wi-Fi net, en þó aðeins þegar það er í forgrunni. Það verður að vera kveikt á þessari staðsetningarþjónustu og hún þarf að vera aðgengileg sjónvarpinu til að forritið geti notað hana."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Þetta forrit getur séð staðsetningu þína út frá netkerfum á borð við farsímasenda og Wi-Fi net, en þó aðeins þegar það er í forgrunni. Það verður að vera kveikt á þessari staðsetningarþjónustu og hún þarf að vera aðgengileg símanum til að forritið geti notað hana."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"aðgangur að staðsetningu í bakgrunni"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ef þetta er veitt til viðbótar við aðgang að áætlaðri eða nákvæmri staðsetningu getur forritið fengið aðgang að staðsetningu á meðan það keyrir í bakgrunni."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"breyta hljóðstillingum"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS-beiðni breytt í USSD-beiðni"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Breytt í nýja SS-beiðni"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Vinnusnið"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Stækka"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Minnka"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"stækka eða minnka"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index a3b9835..7c78677 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Chiamate Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Non attiva"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Rete preferita: Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Rete preferita: dati mobili"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Consente all\'app di accedere a ulteriori comandi del fornitore di posizione. Ciò potrebbe consentire all\'app di interferire con il funzionamento del GPS o di altre fonti di geolocalizzazione."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"Accesso alla posizione esatta solo in primo piano"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Questa app può recuperare la tua posizione esatta solo quando è in primo piano. Questi servizi di geolocalizzazione devono essere attivi e disponibili sul telefono affinché l\'app possa usarli. Potrebbe aumentare il consumo della batteria."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"accesso alla posizione approssimativa (basata sulla rete)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Questa app può accedere alla tua posizione tramite fonti di rete come antenne di telefonia mobile e reti Wi-Fi. Tali servizi di geolocalizzazione devono essere attivati e disponibili sul tablet per consentire all\'app di utilizzarli."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Questa app può accedere alla tua posizione tramite fonti di rete come antenne di telefonia mobile e reti Wi-Fi. Tali servizi di geolocalizzazione devono essere attivati e disponibili sulla TV per consentire all\'app di utilizzarli."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Questa app può accedere alla tua posizione tramite fonti di rete come antenne di telefonia mobile e reti Wi-Fi. Tali servizi di geolocalizzazione devono essere attivati e disponibili sul telefono per consentire all\'app di utilizzarli."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"Accesso alla posizione approssimativa (in base alla rete) solo in primo piano"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Questa app può recuperare la tua posizione tramite fonti di rete quali ripetitori di telefonia mobile e reti Wi-Fi, ma soltanto quando l\'app è in primo piano. Questi servizi di geolocalizzazione devono essere attivi e disponibili sul tablet affinché l\'app possa usarli."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Questa app può recuperare la tua posizione tramite fonti di rete quali ripetitori di telefonia mobile e reti Wi-Fi, ma soltanto quando l\'app è in primo piano. Questi servizi di geolocalizzazione devono essere attivi e disponibili sulla TV affinché l\'app possa usarli."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Questa app può recuperare la tua posizione tramite fonti di rete quali ripetitori di telefonia mobile e reti Wi-Fi, ma soltanto quando l\'app è in primo piano. Questi servizi di geolocalizzazione devono essere attivi e disponibili sul telefono affinché l\'app possa usarli."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"accesso alla posizione in background"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Se concedi l\'autorizzazione insieme all\'accesso alla posizione precisa o approssimativa, l\'app potrà accedere alla posizione mentre viene eseguita in background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modifica impostazioni audio"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Richiesta SS modificata in richiesta USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Modificata in nuova richiesta SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Profilo di lavoro"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Espandi"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Comprimi"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"attiva/disattiva l\'espansione"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 5bf5704..6034ee0 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -138,6 +138,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"‏שיחות WiFi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"כבוי"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"‏Wi-Fi מועדף"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"מצב מועדף: רשת סלולרית"</string>
@@ -423,10 +431,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"‏מאפשרת לאפליקציה לגשת לפקודות נוספות של ספק המיקום. הרשאה זו עשויה לאפשר לאפליקציה לשבש את פעולת ה-GPS או מקורות מיקום אחרים."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"קבלת גישה למיקום מדויק בחזית בלבד"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"אפליקציה זו יכולה לזהות את המיקום המדויק שלך רק כאשר היא פועלת בחזית. כדי שהאפליקציה תוכל להשתמש בשירותי המיקום, עליהם להיות מופעלים וזמינים בטלפון. ייתכן שפעולה זו תגביר את צריכת הסוללה."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"גישה אל מיקום משוער (מבוסס רשת)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"‏אפליקציה זו יכולה לזהות את המיקום שלך על סמך מקורות מיקום ברשת, כגון אנטנות סלולריות ורשתות Wi-Fi. שירותי מיקום אלה חייבים להיות מופעלים וזמינים בטאבלט שלך כדי שהאפליקציה תוכל להשתמש בהם."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"‏אפליקציה זו יכולה לזהות את המיקום שלך על סמך מקורות מיקום ברשת, כגון אנטנות סלולריות ורשתות Wi-Fi. שירותי מיקום אלה חייבים להיות מופעלים וזמינים בטלוויזיה שלך כדי שהאפליקציה תוכל להשתמש בהם."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"‏אפליקציה זו יכולה לזהות את המיקום שלך על סמך מקורות מיקום ברשת, כגון אנטנות סלולריות ורשתות Wi-Fi. שירותי מיקום אלה חייבים להיות מופעלים וזמינים בטלפון שלך כדי שהאפליקציה תוכל להשתמש בהם."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"קבלת גישה למיקום המשוער (מבוסס-רשת) רק במצב פעיל"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"‏אפליקציה זו יכולה לזהות את המיקום שלך על סמך מקורות מיקום ברשת, כגון אנטנות סלולריות ורשתות Wi-Fi, אבל רק כשהאפליקציה במצב פעיל. שירותי מיקום אלה חייבים להיות מופעלים וזמינים בטאבלט כדי שהאפליקציה תוכל להשתמש בהם."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"‏אפליקציה זו יכולה לזהות את המיקום שלך על סמך מקורות מיקום ברשת, כגון אנטנות סלולריות ורשתות Wi-Fi, אבל רק כשהאפליקציה במצב פעיל. שירותי מיקום אלה חייבים להיות מופעלים וזמינים בטלוויזיה כדי שהאפליקציה תוכל להשתמש בהם."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"‏אפליקציה זו יכולה לזהות את המיקום שלך על סמך מקורות מיקום ברשת, כגון אנטנות סלולריות ורשתות Wi-Fi, אבל רק כשהאפליקציה במצב פעיל. שירותי מיקום אלה חייבים להיות מופעלים וזמינים בטלפון כדי שהאפליקציה תוכל להשתמש בהם."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"גישה למיקום ברקע"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"אם מתקבל אישור, בנוסף לגישה למיקום משוער או מדויק, תהיה לאפליקציה גישה למיקום גם כשהיא פועלת ברקע."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"שנה את הגדרות האודיו שלך"</string>
@@ -622,8 +630,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"מאפשר לאפליקציה לנהל מדיניות הרשת להגדיר כללים ספציפיים-לאפליקציה."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"שנה ניהול חשבונות של שימוש ברשת"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"הרשאה זו מאפשרת לאפליקציה לשנות את אופן החישוב של נתוני שימוש ברשת מול כל אפליקציה. לא מיועד לשימוש באפליקציות רגילות."</string>
-    <string name="permlab_accessNotifications" msgid="7673416487873432268">"גישה להודעות"</string>
-    <string name="permdesc_accessNotifications" msgid="458457742683431387">"מאפשר לאפליקציה לאחזר, לבדוק ולמחוק הודעות, כולל כאלה שפורסמו על ידי אפליקציות אחרות."</string>
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"גישה להתראות"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"מאפשר לאפליקציה לאחזר, לבדוק ולמחוק התראות, כולל כאלה שפורסמו על ידי אפליקציות אחרות."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"איגוד לשירות של מאזין להתראות"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"הרשאה זו מאפשרת למשתמש לבצע איגוד לממשק הרמה העליונה של שירות מאזין להתראות. הרשאה זו אף פעם אינה נחוצה לאפליקציות רגילים."</string>
     <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"איגוד לשירות ספק תנאי"</string>
@@ -1891,6 +1899,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"‏בקשת SS שונתה לבקשת USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"‏היה שינוי לבקשת SS חדשה"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"פרופיל עבודה"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"הרחב"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"כווץ"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"החלפת מצב הרחבה"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a9f94c9..4bebf20 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi 通話 | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"OFF"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi優先"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"モバイル優先"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"位置情報提供元の追加のコマンドにアクセスすることをアプリに許可します。許可すると、アプリがGPSなどの位置情報源の動作を妨害する恐れがあります。"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"フォアグラウンドでのみ正確な位置情報にアクセス"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"このアプリは、フォアグラウンド状態でのみユーザーの正確な位置情報を取得できます。この位置情報サービスは ON の状態にして、スマートフォンでアプリがサービスを利用できるようにする必要があります。これにより、電池の消費量が増える可能性があります。"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"おおよその位置情報(ネットワーク基地局)へのアクセス"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"このアプリは、ネットワーク位置情報源(携帯基地局や Wi-Fi ネットワークなど)に基づいて、ユーザーの位置情報を取得します。これらの位置情報サービスは ON の状態にして、タブレットでアプリがサービスを利用できるようにする必要があります。"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"このアプリは、ネットワーク位置情報源(携帯基地局や Wi-Fi ネットワークなど)に基づいて、ユーザーの位置情報を取得します。これらの位置情報サービスは ON の状態にして、テレビでアプリがサービスを利用できるようにする必要があります。"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"このアプリは、ネットワーク位置情報源(携帯基地局や Wi-Fi ネットワークなど)に基づいて、ユーザーの位置情報を取得します。これらの位置情報サービスは ON の状態にして、スマートフォンでアプリがサービスを利用できるようにする必要があります。"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"フォアグラウンドでのみ(ネットワークに基づく)おおよその位置情報にアクセス"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"このアプリは、フォアグラウンドでのみ、ネットワーク位置情報源(携帯基地局や Wi-Fi ネットワークなど)に基づいて、ユーザーの位置情報を取得できます。これらの位置情報サービスは ON の状態にして、タブレットでアプリがサービスを利用できるようにする必要があります。"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"このアプリは、フォアグラウンドでのみ、ネットワーク位置情報源(携帯基地局や Wi-Fi ネットワークなど)に基づいて、ユーザーの位置情報を取得できます。これらの位置情報サービスは ON の状態にして、テレビでアプリがサービスを利用できるようにする必要があります。"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"このアプリは、フォアグラウンドでのみ、ネットワーク位置情報源(携帯基地局や Wi-Fi ネットワークなど)に基づいて、ユーザーの位置情報を取得できます。これらの位置情報サービスは ON の状態にして、スマートフォンでアプリがサービスを利用できるようにする必要があります。"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"バックグラウンドでの位置情報へのアクセス"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"これが、おおよその位置情報または正確な位置情報へのアクセスの追加権限の場合、アプリはバックグラウンドでの実行中も位置情報にアクセスできます。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"音声設定の変更"</string>
@@ -640,8 +648,8 @@
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"携帯通信会社のSMSサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"携帯通信会社のサービスへのバインド"</string>
     <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"携帯通信会社のサービスにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
-    <string name="permlab_access_notification_policy" msgid="4247510821662059671">"マナーモードへのアクセス"</string>
-    <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"マナーモード設定の読み取りと書き込みをアプリに許可します。"</string>
+    <string name="permlab_access_notification_policy" msgid="4247510821662059671">"サイレント モードへのアクセス"</string>
+    <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"サイレント モード設定の読み取りと書き込みをアプリに許可します。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールの設定"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"画面ロックのパスワードとPINの長さと使用できる文字を制御します。"</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"画面ロック解除試行の監視"</string>
@@ -1804,10 +1812,10 @@
     <string name="zen_mode_until" msgid="7336308492289875088">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>まで"</string>
     <string name="zen_mode_alarm" msgid="9128205721301330797">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>(次のアラーム)まで"</string>
     <string name="zen_mode_forever" msgid="931849471004038757">"自分が OFF にするまで"</string>
-    <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"マナーモードを OFF にするまで"</string>
+    <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"サイレント モードを OFF にするまで"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
     <string name="toolbar_collapse_description" msgid="2821479483960330739">"折りたたむ"</string>
-    <string name="zen_mode_feature_name" msgid="5254089399895895004">"マナーモード"</string>
+    <string name="zen_mode_feature_name" msgid="5254089399895895004">"サイレント モード"</string>
     <string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"ダウンタイム"</string>
     <string name="zen_mode_default_weeknights_name" msgid="3081318299464998143">"平日の夜"</string>
     <string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"週末"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS リクエストは USSD リクエストに変更されました"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"新しい SS リクエストに変更されました"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"仕事用プロファイル"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"展開"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"折りたたむ"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"展開の切り替え"</string>
@@ -1948,10 +1958,10 @@
     <string name="volume_dialog_ringer_guidance_vibrate" msgid="8902050240801159042">"着信や通知をバイブレーションで知らせます"</string>
     <string name="volume_dialog_ringer_guidance_silent" msgid="2128975224280276122">"着信音と通知音をミュートします"</string>
     <string name="notification_channel_system_changes" msgid="5072715579030948646">"システムの変更"</string>
-    <string name="notification_channel_do_not_disturb" msgid="6766940333105743037">"マナーモード"</string>
-    <string name="zen_upgrade_notification_visd_title" msgid="3288313883409759733">"新機能: マナーモードでは通知が非表示になります"</string>
+    <string name="notification_channel_do_not_disturb" msgid="6766940333105743037">"サイレント モード"</string>
+    <string name="zen_upgrade_notification_visd_title" msgid="3288313883409759733">"新機能: サイレント モードでは通知が非表示になります"</string>
     <string name="zen_upgrade_notification_visd_content" msgid="5533674060311631165">"タップすると、詳細を確認して設定を変更できます。"</string>
-    <string name="zen_upgrade_notification_title" msgid="3799603322910377294">"マナーモードが変わりました"</string>
+    <string name="zen_upgrade_notification_title" msgid="3799603322910377294">"サイレント モードが変わりました"</string>
     <string name="zen_upgrade_notification_content" msgid="1794994264692424562">"タップしてブロック対象をご確認ください。"</string>
     <string name="notification_app_name_system" msgid="4205032194610042794">"システム"</string>
     <string name="notification_app_name_settings" msgid="7751445616365753381">"設定"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index e776289..fdcfc0c 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi დარეკვა | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"გამორთული"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"სასურველია Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"უპირატესობა მიენიჭოს მობილურს"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"აპს შეეძლება წვდომა ჰქონდეს მდებარეობის სერვისის დამატებით ბრძანებებზე. შესაძლოა აპმა ეს გამოიყენოს GPS-ისა და მდებარეობის სხვა წყაროების მუშაობის პროცესში ჩარევისთვის."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"ზუსტ მდებარეობაზე წვდომა მხოლოდ წინა პლანზე"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"ამ აპს შეუძლია თქვენი ზუსტი მდებარეობის შესახებ ინფორმაციის მიღება მხოლოდ მაშინ, როცა გაშვებულია წინა პლანზე. თქვენს ტელეფონზე ჩართული და ხელმისაწვდომი უნდა იყოს მდებარეობის სერვისები, აპმა მათი გამოყენება რომ შეძლოს. ამან შეიძლება გაზარდოს ბატარეის მოხმარება."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"მიახლოებით მდებარეობაზე წვდომა (ქსელის მეშვეობით)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ამ აპს თქვენი მდებარეობის შესახებ ინფორმაციის მიღება ისეთი წყაროების მეშვეობით შეუძლია, როგორიცაა მობილური კავშირგაბმულობის ანძები და Wi-Fi ქსელები. მდებარეობის აღნიშნული სერვისები თქვენს ტაბლეტზე ჩართული და ხელმისაწვდომი უნდა იყოს, რათა აპმა მათი გამოყენება შეძლოს."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ამ აპს თქვენი მდებარეობის შესახებ ინფორმაციის მიღება ისეთი წყაროების მეშვეობით შეუძლია, როგორიცაა მობილური კავშირგაბმულობის ანძები და Wi-Fi ქსელები. მდებარეობის აღნიშნული სერვისები თქვენს ტელევიზორზე ჩართული და ხელმისაწვდომი უნდა იყოს, რათა აპმა მათი გამოყენება შეძლოს."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ამ აპს თქვენი მდებარეობის შესახებ ინფორმაციის მიღება ისეთი წყაროების მეშვეობით შეუძლია, როგორიცაა მობილური კავშირგაბმულობის ანძები და Wi-Fi ქსელები. მდებარეობის აღნიშნული სერვისები თქვენს ტელეფონზე ჩართული და ხელმისაწვდომი უნდა იყოს, რათა აპმა მათი გამოყენება შეძლოს."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"მიახლოებით მდებარეობაზე (ქსელის კოორდინატების მიხედვით) წვდომა მხოლოდ წინა პლანზე"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"ამ აპს შეუძლია თქვენი მდებარეობის შესახებ ინფორმაციის მიღება ისეთი წყაროებიდან, როგორიცაა მობილური კავშირგაბმულობის ანძები და Wi-Fi ქსელები (თუმცა მხოლოდ მაშინ, როცა აპი გაშვებულია წინა პლანზე). მდებარეობის აღნიშნული სერვისები თქვენს ტაბლეტზე ჩართული და ხელმისაწვდომი უნდა იყოს, აპმა მათი გამოყენება რომ შეძლოს."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"ამ აპს შეუძლია თქვენი მდებარეობის შესახებ ინფორმაციის მიღება ისეთი წყაროებიდან, როგორიცაა მობილური კავშირგაბმულობის ანძები და Wi-Fi ქსელები (თუმცა მხოლოდ მაშინ, როცა აპი გაშვებულია წინა პლანზე). მდებარეობის აღნიშნული სერვისები თქვენს ტელევიზორზე ჩართული და ხელმისაწვდომი უნდა იყოს, აპმა მათი გამოყენება რომ შეძლოს."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"ამ აპს შეუძლია თქვენი მდებარეობის შესახებ ინფორმაციის მიღება ისეთი წყაროებიდან, როგორიცაა მობილური კავშირგაბმულობის ანძები და Wi-Fi ქსელები (თუმცა მხოლოდ მაშინ, როცა აპი გაშვებულია წინა პლანზე). მდებარეობის აღნიშნული სერვისები თქვენს ტელეფონზე ჩართული და ხელმისაწვდომი უნდა იყოს, აპმა მათი გამოყენება რომ შეძლოს."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"მდებარეობაზე წვდომა ფონურ რეჟიმში"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ამ ნებართვის მიახლოებით ან ზუსტ მდებარეობაზე წვდომის ნებართვასთან ერთად მინიჭების შემთხვევაში, აპს შეეძლება მდებარეობაზე წვდომა ფონურ რეჟიმში."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"თქვენი აუდიო პარამეტრების შეცვლა"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS მოთხოვნა შეიცვალა USSD მოთხოვნით"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"შეიცვალა ახალი SS მოთხოვნით"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"სამსახურის პროფილი"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"გაშლა"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"ჩაკეცვა"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"გაშლის გადართვა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 375aa82..7f3e611 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi қоңыраулары | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Өшірулі"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Қалаулы Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Таңдаулы мобильдік байланыс"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Қолданбаға орын жеткізушісінің қосымша пәрмендеріне қатынасуға рұқсат береді. Бұл қолданбаға GPS немесе басқа орын көздерінің жұмысына кедергі келтіруге рұқсат беруі мүмкін."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"нақты орналасқан жер туралы ақпаратқа тек ашық экранда кіру"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Бұл қолданба нақты орналасқан жеріңіз туралы ақпаратты экранда ашық тұрғанда ғана анықтай алады. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін, олар қосулы әрі телефонда қолжетімді болуы керек. Батарея көбірек тұтынылуы мүмкін."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"шамамен алған орынға қатынасу (желі негізінде)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Бұл қолданба орналасқан жеріңізді ұялы байланыс мұнаралары мен Wi-Fi желілері сияқты желі көздерінің негізінде анықтайды. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін олар қосулы әрі планшетте қолжетімді болуы керек."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Бұл қолданба орналасқан жеріңізді ұялы байланыс мұнаралары мен Wi-Fi желілері сияқты желі көздерінің негізінде анықтайды. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін олар қосулы әрі теледидарда қолжетімді болуы керек."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Бұл қолданба орналасқан жеріңізді ұялы байланыс мұнаралары мен Wi-Fi желілері сияқты желі көздерінің негізінде анықтайды. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін олар қосулы әрі телефонда қолжетімді болуы керек."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"болжалды геодерекке (желі негізінде) тек экрандық режимде кіру"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Бұл қолданба орналасқан жеріңізді ұялы байланыс мұнаралары мен Wi-Fi желілері сияқты желі көздерінің негізінде анықтайды. Бірақ бұл үшін қолданба экрандық режимде жұмыс істеп тұруы керек. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін, олар қосулы әрі планшетте қолжетімді болуы керек."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Бұл қолданба орналасқан жеріңізді ұялы байланыс мұнаралары мен Wi-Fi желілері сияқты желі көздерінің негізінде анықтайды. Бірақ бұл үшін қолданба экранда ашық тұруы керек. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін, олар қосулы әрі теледидарда қолжетімді болуы керек."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Бұл қолданба орналасқан жеріңізді ұялы байланыс мұнаралары мен Wi-Fi желілері сияқты желі көздерінің негізінде анықтайды. Бірақ бұл үшін қолданба экранда ашық тұруы керек. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін, олар қосулы әрі телефонда қолжетімді болуы керек."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"геодеректерді фондық режимде пайдалану"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Егер ол шамамен есептегендегі немесе нақты орынды пайдалануға рұқсат алса, қолданба фондық режимде жұмыс істеп тұрып-ақ геодеректерді пайдалана алады."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"аудио параметрлерін өзгерту"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS сұрауы USSD сұрауына өзгертілді"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Жаңа SS сұрауына өзгертілді"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Жұмыс профилі"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Жаю"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Жию"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"жаю/жию"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index b9cf1eb..06e6540 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"ការហៅតាម WiFi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"បិទ"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi ជាអាទិភាព"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"ទិន្នន័យទូរសព្ទចល័តជាអាទិភាព"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ឲ្យ​កម្មវិធី​ចូល​ដំណើរការ​ពាក្យ​បញ្ជា​កម្មវិធី​ផ្ដល់​​ទីតាំង​បន្ថែម។ វា​អាច​អនុញ្ញាត​ឲ្យ​កម្មវិធី​ទាក់ទង​ជា​មួយ​ប្រតិបត្តិការ​ជីភីអេស ឬ​ប្រភព​ទីតាំង​ផ្សេង។"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"ចូល​ប្រើ​ទីតាំង​ជាក់លាក់​តែ​នៅផ្ទៃ​ខាងមុខ​ប៉ុណ្ណោះ"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"កម្មវិធីនេះ​អាចទទួល​បានទីតាំង​ពិតប្រាកដ​របស់អ្នក​តែនៅពេល​វាស្ថិតនៅ​ផ្ទៃខាងមុខប៉ុណ្ណោះ។ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក និងមាន​នៅលើ​ទូរសព្ទ​របស់អ្នក ដើម្បីឱ្យ​កម្មវិធី​នេះអាចប្រើ​ពួកវាបាន។ វាអាចប្រើ​ថាមពល​ច្រើន​ជាងមុន។"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ចូលដំណើរការទីតាំងប្រហាក់ប្រហែល (ផ្អែកលើបណ្តាញ)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"កម្មវិធី​នេះ​អាច​ទទួល​បាន​ទីតាំង​របស់​អ្នក​ ដោយ​ផ្អែក​លើ​ប្រភព​បណ្តាញ​ ដូចជា​៖​ អង់តែន​ និង​បណ្តាញ​ Wi-Fi​ ។​ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក​ និង​ត្រូវតែ​មាន​នៅ​លើ​ថេប្លេត​របស់​អ្នក ដើម្បី​ឲ្យ​កម្មវិធី​នេះ​អាច​ប្រើ​វា​បាន​។"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"កម្មវិធី​នេះ​អាច​ទទួល​បាន​ទីតាំង​របស់​អ្នក​ ដោយ​ផ្អែក​លើ​ប្រភព​បណ្តាញ​ ដូចជា​៖​ អង់តែន​ និង​បណ្តាញ​ Wi-Fi​ ។​ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក​ និង​ត្រូវតែ​មាន​នៅ​លើ​ទូរទស្សន៍​របស់​អ្នក ដើម្បី​ឲ្យ​កម្មវិធី​នេះ​អាច​ប្រើ​វា​បាន​។"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"កម្មវិធី​នេះ​អាច​ទទួល​បាន​ទីតាំង​របស់​អ្នក​ ដោយ​ផ្អែក​លើ​ប្រភព​បណ្តាញ​ ដូចជា​៖​ អង់តែន​ និង​បណ្តាញ​ Wi-Fi​ ។​ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក​ និង​ត្រូវតែ​មាន​នៅ​លើ​ទូរសព្ទ​របស់​អ្នក ដើម្បី​ឲ្យ​កម្មវិធី​នេះ​អាច​ប្រើ​វា​បាន​។"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"ចូលប្រើ​ទីតាំង​ប្រហាក់ប្រហែល (ផ្អែកលើ​បណ្តាញ) នៅផ្ទៃ​ខាងមុខ​តែប៉ុណ្ណោះ"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"កម្មវិធី​នេះ​អាច​ទទួល​បាន​ទីតាំង​របស់​អ្នក ដោយ​ផ្អែកលើ​ប្រភព​បណ្តាញ​ដូចជា អង់តែន​បណ្តាញ​ទូរសព្ទ និង​បណ្តាញ Wi-Fi ជាដើម ប៉ុន្តែនៅពេល​កម្មវិធីស្ថិតនៅ​ផ្ទៃខាងមុខ​តែប៉ុណ្ណោះ។ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក និងមាន​នៅលើ​ថេប្លេត​របស់អ្នក ដើម្បីឱ្យ​កម្មវិធី​នេះអាចប្រើ​វាបាន។"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"កម្មវិធី​នេះ​អាច​ទទួល​បាន​ទីតាំង​របស់​អ្នក ដោយ​ផ្អែកលើ​ប្រភព​បណ្តាញ​ដូចជា អង់តែន​បណ្តាញ​ទូរសព្ទ និង​បណ្តាញ Wi-Fi ជាដើម ប៉ុន្តែនៅពេល​កម្មវិធីស្ថិតនៅ​ផ្ទៃខាងមុខ​តែប៉ុណ្ណោះ។ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក និងមាន​នៅលើ​ទូរទស្សន៍​របស់អ្នក ដើម្បីឱ្យ​កម្មវិធី​នេះអាចប្រើ​វាបាន។"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"កម្មវិធី​នេះ​អាច​ទទួល​បាន​ទីតាំង​របស់​អ្នក ដោយ​ផ្អែកលើ​ប្រភព​បណ្តាញ​ដូចជា អង់តែន​បណ្តាញ​ទូរសព្ទ និង​បណ្តាញ Wi-Fi ជាដើម ប៉ុន្តែនៅពេល​កម្មវិធីស្ថិតនៅ​ផ្ទៃខាងមុខ​តែប៉ុណ្ណោះ។ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក និងមាន​នៅលើ​ទូរសព្ទ​របស់អ្នក ដើម្បីឱ្យ​កម្មវិធី​នេះអាចប្រើ​វាបាន។"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ចូល​ប្រើ​ទីតាំង​នៅ​ផ្ទៃខាងក្រោយ"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ប្រសិនបើ​ផ្ដល់​ការអនុញ្ញាត​នេះ​បន្ថែម​ពីលើ​ការចូលប្រើទីតាំងជាក់លាក់ ឬប្រហាក់ប្រហែល កម្មវិធី​នឹងអាចចូលប្រើទីតាំងនោះ ខណៈពេលដំណើរការនៅផ្ទៃខាងក្រោយ។"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ប្ដូរ​ការ​កំណត់​អូឌីយូ​របស់​អ្នក"</string>
@@ -1827,6 +1835,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"សំណើ SS ត្រូវបាន​ប្ដូរ​ទៅ​សំណើ USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"បាន​ប្ដូរ​ទៅ​សំណើ SS ថ្មី"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"ប្រវត្តិរូបការងារ"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"ពង្រីក"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"លាក់"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"បិទ/បើកការពង្រីក"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 2a480cd..88e7ce1 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> ವೈ-ಫೈ"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"ವೈಫೈ ಕರೆಮಾಡುವಿಕೆ | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ಆಫ್"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"ವೈ-ಫೈಗೆ ಆದ್ಯತೆ"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"ಮೊಬೈಲ್‌ಗೆ ಆದ್ಯತೆ"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ಹೆಚ್ಚಿನ ಸ್ಥಳ ಪೂರೈಕೆದಾರ ಆದೇಶಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಇದು GPS ಅಥವಾ ಇತರ ಸ್ಥಳ ಮೂಲಗಳ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಮಧ್ಯ ಪ್ರವೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅನುಮತಿಸಬಹುದು."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"ಮುನ್ನೆಲೆಯಲ್ಲಿ ಮಾತ್ರ ನಿಖರವಾದ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"ಈ ಅಪ್ಲಿಕೇಶನ್‌ ಮುಂಭಾಗದಲ್ಲಿರುವಾಗ ಮಾತ್ರ ನಿಮ್ಮ ನಿಖರ ಸ್ಥಳವನ್ನು ಪಡೆಯಬಹುದು. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ಅಂದಾಜು ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ (ನೆಟ್‌ವರ್ಕ್-ಆಧಾರಿತ)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‌ಗಳು ಮತ್ತು ವೈ-ಫೈ ನೆಟ್‍‍ವರ್ಕ್‌ನಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಮೂಲಗಳ ಆಧಾರದ ಮೇಲೆ ಪಡೆಯಬಹುದು. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‌ಗಳು ಮತ್ತು ವೈ-ಫೈ ನೆಟ್‍‍ವರ್ಕ್‌ನಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಮೂಲಗಳ ಆಧಾರದ ಮೇಲೆ ಪಡೆಯಬಹುದು. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಟಿವಿಯಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‌ಗಳು ಮತ್ತು ವೈ-ಫೈ ನೆಟ್‍‍ವರ್ಕ್‌ನಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಮೂಲಗಳ ಆಧಾರದ ಮೇಲೆ ಪಡೆಯಬಹುದು. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"ಮುನ್ನೆಲೆಯಲ್ಲಿ ಮಾತ್ರ ಅಂದಾಜು ಸ್ಥಳವನ್ನು (ನೆಟ್‌ವರ್ಕ್-ಆಧಾರಿತ) ಪ್ರವೇಶಿಸಿ"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"ಈ ಆ್ಯಪ್‌ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‌ಗಳು ಮತ್ತು ವೈ-ಫೈ ನೆಟ್‍‍ವರ್ಕ್‌ಗಳಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಮೂಲಗಳ ಆಧಾರದ ಮೇಲೆ ಪಡೆಯಬಹುದು, ಆದರೆ ಆ್ಯಪ್‌ ಮುನ್ನೆಲೆಯಲ್ಲಿದ್ದಾಗ ಮಾತ್ರ. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"ಈ ಆ್ಯಪ್‌ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‌ಗಳು ಮತ್ತು ವೈ-ಫೈ ನೆಟ್‍‍ವರ್ಕ್‌ಗಳಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಮೂಲಗಳ ಆಧಾರದ ಮೇಲೆ ಪಡೆಯಬಹುದು, ಆದರೆ ಆ್ಯಪ್‌ ಮುನ್ನೆಲೆಯಲ್ಲಿದ್ದಾಗ ಮಾತ್ರ. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಟಿವಿಯಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"ಈ ಆ್ಯಪ್‌ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‌ಗಳು ಮತ್ತು ವೈ-ಫೈ ನೆಟ್‍‍ವರ್ಕ್‌ಗಳಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಮೂಲಗಳ ಆಧಾರದ ಮೇಲೆ ಪಡೆಯಬಹುದು, ಆದರೆ ಆ್ಯಪ್‌ ಮುನ್ನೆಲೆಯಲ್ಲಿದ್ದಾಗ ಮಾತ್ರ. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಆ್ಯಪ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ಇದನ್ನು ಅಂದಾಜು ಅಥವಾ ನಿಖರವಾದ ಸ್ಥಳ ಪ್ರವೇಶಕ್ಕೆ ಹೆಚ್ಚುವರಿಯಾಗಿ ಅನುಮತಿಸಿದರೆ, ಆ್ಯಪ್ ಹಿನ್ನೆಲೆಯಲ್ಲಿ ರನ್ ಆಗುತ್ತಿರುವಾಗ ಅದು ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ನಿಮ್ಮ ಆಡಿಯೊ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಿ"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS ವಿನಂತಿಯನ್ನು USSD ವಿನಂತಿಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"ಹೊಸ SS ವಿನಂತಿಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"ವಿಸ್ತೃತಗೊಳಿಸಿ"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"ಕುಗ್ಗಿಸಿ"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"ವಿಸ್ತರಣೆ ಟಾಗಲ್‌ ಮಾಡಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index b66cbf4..97d799e 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi 통화 | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"꺼짐"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi를 기본으로 설정"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"모바일에 최적화됨"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"앱이 추가 위치 정보 제공 기능의 명령에 접근하도록 허용합니다. 이 경우 앱이 GPS 또는 기타 위치 소스의 작동을 방해할 수 있습니다."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"포그라운드에서만 정확한 위치에 액세스"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"이 앱은 포그라운드에 있을 때만 나의 정확한 위치를 알 수 있습니다. 앱에서 위치 서비스를 사용하려면 휴대전화에서 위치 서비스가 사용 설정되어 있으며 사용할 수 있어야 합니다. 배터리 사용량이 늘어날 수 있습니다."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"대략적인 위치(네트워크 기반)에 액세스"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"이 앱은 기지국 및 Wi-Fi 네트워크와 같은 네트워크 소스를 통해 내 위치를 알 수 있습니다. 앱에서 위치 서비스를 사용하려면 태블릿에서 위치 서비스가 사용 설정되어 있으며 사용 가능해야 합니다."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"이 앱은 기지국 및 Wi-Fi 네트워크와 같은 네트워크 소스를 통해 내 위치를 알 수 있습니다. 앱에서 위치 서비스를 사용하려면 TV에서 위치 서비스가 사용 설정되어 있으며 사용 가능해야 합니다."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"이 앱은 기지국 및 Wi-Fi 네트워크와 같은 네트워크 소스를 통해 내 위치를 알 수 있습니다. 앱에서 위치 서비스를 사용하려면 휴대전화에서 위치 서비스가 사용 설정되어 있으며 사용 가능해야 합니다."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"포그라운드에서만 대략적인 위치(네트워크 기반)에 액세스"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"앱이 포그라운드에 있을 때만 휴대전화 기지국과 Wi-Fi 네트워크 등의 네트워크 소스를 바탕으로 사용자의 위치를 파악할 수 있습니다. 앱에서 위치 서비스를 사용하려면 태블릿에서 위치 서비스가 켜져 있으며 사용 가능해야 합니다."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"앱이 포그라운드에 있을 때만 휴대전화 기지국과 Wi-Fi 네트워크 등의 네트워크 소스를 바탕으로 사용자의 위치를 파악할 수 있습니다. 앱에서 위치 서비스를 사용하려면 TV에서 위치 서비스가 켜져 있으며 사용 가능해야 합니다."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"앱이 포그라운드에 있을 때만 휴대전화 기지국과 Wi-Fi 네트워크 등의 네트워크 소스를 바탕으로 사용자의 위치를 파악할 수 있습니다. 앱에서 위치 서비스를 사용하려면 휴대전화에서 위치 서비스가 켜져 있으며 사용 가능해야 합니다."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"백그라운드에서 위치 정보 액세스"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"이 권한이 대략적인 위치 정보 또는 정확한 위치 정보 액세스 권한에 추가적으로 부여되면 앱이 백그라운드에서 실행되는 동안 위치에 액세스할 수 있습니다."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"오디오 설정 변경"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS 요청이 USSD 요청으로 변경됨"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"새 SS 요청으로 변경됨"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"직장 프로필"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"펼치기"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"접기"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"확장 전환"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index de3bcd2..6608029 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"WiFi аркылуу чалуу | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Өчүк"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi тандалган"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Тандалган мобилдик түзмөк"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Колдонмого жайгашкан жерди табуучу кошумча жабдуучулардын буйруктарын колдонуу мүмкүнчүлүгүн берет. Ушуну менен колдонмо GPS\'тин ишине жана башка жайгашкан жерлерди аныктоо кызматтарына кийлигише алат."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"так аныкталган жайгашкан жерге активдүү режимде гана кирүүгө уруксат берүү"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Бул колдонмонун активдүү режимде гана жайгашкан жериңиздин дайындарын  алууга мүмкүнчүлүгү бар. Колдонмо бул кызматтарды пайдаланышы үчүн аларды күйгүзүп, телефонуңузга туташтырып коюшуңуз керек. Ушуну менен батареянын кубаты көбүрөөк сарпталышы мүмкүн."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"болжолдуу жайгашкан жерге (тармактын негизинде) уруксат"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Бул колдонмо байланыш мунаралары жана Wi-Fi сыяктуу тармактык булактар аркылуу жайгашкан жериңизди аныктай алат. Колдонмо бул кызматтарды пайдаланышы үчүн, аларды күйгүзүп, планшетиңизге туташтырып коюшуңуз керек."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Бул колдонмо байланыш мунаралары жана Wi-Fi сыяктуу тармактык булактар аркылуу жайгашкан жериңизди аныктай алат. Колдонмо бул кызматтарды пайдаланышы үчүн, аларды күйгүзүп, сыналгыңызга туташтырып коюшуңуз керек."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Бул колдонмо байланыш мунаралары жана Wi-Fi сыяктуу тармактык булактар аркылуу жайгашкан жериңизди аныктай алат. Колдонмо бул кызматтарды пайдаланышы үчүн, аларды күйгүзүп, телефонуңузга туташтырып коюшуңуз керек."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"болжолдуу аныкталган жайгашкан жерге (тармактын негизинде) автивдүү режимде гана кирүүгө уруксат берүү"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Бул колдонмо байланыш мунаралары жана Wi-Fi сыяктуу тармактык булактар аркылуу жайгашкан жериңизди аныктай алат, бирок ал үчүн колдонмо ачылып турушу керек. Колдонмо бул кызматтарды пайдаланышы үчүн, аларды күйгүзүп, планшетиңизге туташтырып коюшуңуз керек."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Бул колдонмо байланыш мунаралары жана Wi-Fi сыяктуу тармактык булактар аркылуу жайгашкан жериңизди аныктай алат, бирок ал үчүн колдонмо ачылып турушу керек. Колдонмо бул кызматтарды пайдаланышы үчүн, аларды күйгүзүп, сыналгыңызга туташтырып коюшуңуз керек."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Бул колдонмо байланыш мунаралары жана Wi-Fi сыяктуу тармактык булактар аркылуу жайгашкан жериңизди аныктай алат, бирок ал үчүн колдонмо ачылып турушу керек. Колдонмо бул кызматтарды пайдаланышы үчүн, аларды күйгүзүп, телефонуңузга туташтырып коюшуңуз керек."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"жайгашкан жерди фондо аныктоо"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Эгер колдонмого жайгашкан жерди болжолдуу же так аныктоого уруксат берилсе, ал фондо иштеп жатып эле жайгашкан жерди аныктап турат."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"аудио жөндөөлөрүңүздү өзгөртүңүз"</string>
@@ -1827,6 +1835,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS сурамы USSD сурамына өзгөртүлдү"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Жаңы SS сурамына өзгөртүлдү"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Жумуш профили"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Жайып көрсөтүү"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Жыйыштыруу"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"жайып көрсөтүү же жыйыштыруу"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 9fb0adb..e12ec28 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"WiFi Calling | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ປິດ"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"ເລືອກໃຊ້ Wi​-Fi ກ່ອນ"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"ຕ້ອງການໃຊ້ມືຖື"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ອະນຸຍາດ​ໃຫ້​ແອັບຯ​ເຂົ້າເຖິງ​ຄຳສັ່ງ​ເພີ່ມເຕີມ​ຂອງ​ຜູ່​ໃຫ້​ບໍລິການ​ສະຖານທີ່. ນີ້​ອາດ​ຈະ​ເປັນ​ການ​ເຮັດ​ໃຫ້​ແອັບຯ ລົບກວນ​ການ​ເຮັດ​ວຽກ​ຂອງ GPS ຫຼື​ແຫລ່ງ​ຂໍ້ມູນ​ສະຖານທີ່​ອື່ນໆ​ໄດ້."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"ເຂົ້າເຖິງສະຖານທີ່ແນ່ນອນໃນພື້ນໜ້າເທົ່ານັ້ນ"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"ແອັບນີ້ສາມາດຮັບເອົາສະຖານທີ່ແນ່ນອນຂອງທ່ານໄດ້ທຸກເວລາທີ່ມັນຢູ່ໃນພື້ນໜ້າ. ການບໍລິການສະຖານທີ່ເຫຼົ່ານີ້ຕ້ອງເປີດຢູ່ ແລະ ສາມາດໃຊ້ໄດ້ໃນໂທລະສັບຂອງທ່ານເພື່ອໃຫ້ແອັບສາມາດໃຊ້ພວກມັນໄດ້. ນີ້ອາດຈະເຮັດໃຫ້ການໃຊ້ແບັດເຕີຣີເພີ່ມຂຶ້ນ."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ເຂົ້າ​ຫາທີ່ຕັ້ງໂດຍປະມານ (ອີງໃສ່ເຄືອຂ່າຍ)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"This app can get your location based on network sources such as cell towers and Wi-Fi networks. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"This app can get your location based on network sources such as cell towers and Wi-Fi networks. These location services must be turned on and available on your TV for the app to be able to use them."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"This app can get your location based on network sources such as cell towers and Wi-Fi networks. These location services must be turned on and available on your phone for the app to be able to use them."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"ເຂົ້າເຖິງສະຖານທີ່ໂດຍປະມານ (ອ້າງອີງຈາກເຄືອຂ່າຍ) ສະເພາະໃນພື້ນໜ້າ"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"ແອັບນີ້ສາມາດເບິ່ງສະຖານທີ່ຂອງທ່ານໂດຍອ້າງອີງຈາກແຫລ່ງທີ່ມເຄືອຂ່າຍ ເຊັ່ນ: ເສົາສັນຍານໂທລະສັບ ແລະ ເຄືອຂ່າຍ Wi-Fi ໄດ້, ແຕ່ສະເພາະເມື່ອແອັບເຮັດວຽກໂດຍປາກົດຢູ່ໜ້າເທົ່ານັ້ນ. ບໍລິການສະຖານທີ່ເຫຼົ່ານີ້ຈະຕ້ອງຖືກເປີດໃຊ້ ແລະ ສາມາດໃຊ້ໄດ້ຢູ່ແທັບເລັດຂອງທ່ານ, ແອັບຈຶ່ງຈະສາມາດໃຊ້ພວກມັນໄດ້."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"ແອັບນີ້ສາມາດເບິ່ງສະຖານທີ່ຂອງທ່ານໂດຍອ້າງອີງຈາກແຫລ່ງທີ່ມເຄືອຂ່າຍ ເຊັ່ນ: ເສົາສັນຍານໂທລະສັບ ແລະ ເຄືອຂ່າຍ Wi-Fi ໄດ້, ແຕ່ສະເພາະເມື່ອແອັບເຮັດວຽກໂດຍປາກົດຢູ່ໜ້າເທົ່ານັ້ນ. ບໍລິການສະຖານທີ່ເຫຼົ່ານີ້ຈະຕ້ອງຖືກເປີດໃຊ້ ແລະ ສາມາດໃຊ້ໄດ້ຢູ່ໂທລະທັດຂອງທ່ານ, ແອັບຈຶ່ງຈະສາມາດໃຊ້ພວກມັນໄດ້."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"ແອັບນີ້ສາມາດເບິ່ງສະຖານທີ່ຂອງທ່ານໂດຍອ້າງອີງຈາກແຫລ່ງທີ່ມເຄືອຂ່າຍ ເຊັ່ນ: ເສົາສັນຍານໂທລະສັບ ແລະ ເຄືອຂ່າຍ Wi-Fi ໄດ້, ແຕ່ສະເພາະເມື່ອແອັບເຮັດວຽກໂດຍປາກົດຢູ່ໜ້າເທົ່ານັ້ນ. ບໍລິການສະຖານທີ່ເຫຼົ່ານີ້ຈະຕ້ອງຖືກເປີດໃຊ້ ແລະ ສາມາດໃຊ້ໄດ້ຢູ່ໂທລະສັບຂອງທ່ານ, ແອັບຈຶ່ງຈະສາມາດໃຊ້ພວກມັນໄດ້."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ເຂົ້າເຖິງສະຖານທີ່ໃນພື້ນຫຼັງ"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ຖ້າອະນຸຍາດສິ່ງນີ້ນອກຈາກການເຂົ້າເຖິງສະຖານທີ່ໂດຍປະມານ ຫຼື ທີ່ແນ່ນອນ ແອັບສາມາດເຂົ້າເຖິງສະຖານທີ່ໄດ້ໃນຂະນະທີ່ເປີດໃຊ້ໃນພື້ນຫຼັງ."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ປ່ຽນການຕັ້ງຄ່າສຽງຂອງທ່ານ"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"ປ່ຽນຄຳຂໍ SS ເປັນຄຳຂໍ USSD ແລ້ວ"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"ປ່ຽນຄຳຂໍ SS ໃໝ່ແລ້ວ"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"ຂະຫຍາຍ"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"ຫຍໍ້ເຂົ້າ"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"ປິດ/ເປີດ ການຂະຫຍາຍ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index f5225c5..86cee5e 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -138,6 +138,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> „Wi-Fi“"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"„Wi-Fi“ skambinimas | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> „VoWifi“"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Išjungta"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Pageidautinas „Wi-Fi“ ryšys"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Pirmenybė mobiliojo ryšio tinklui"</string>
@@ -423,10 +431,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Programai leidžiama pasiekti papildomas vietovės nustatymo paslaugų teikėjų komandas. Dėl to programa gali trukdyti veikti GPS ar kitiems vietovės nustatymo šaltiniams."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"pasiekti tikslią vietovę, tik kai programa veikia priekiniame plane"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Ši programa gali gauti tikslius jūsų vietovės duomenis bet kuriuo metu, kai veikia priekiniame plane. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos telefone, kad programa galėtų jas naudoti. Tai gali padidinti akumuliatoriaus energijos suvartojimą."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"pasiekti apytikslę vietą (nustatytą atsižvelgiant į tinklą)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ši programa gali gauti jūsų vietos informaciją naudodamasi tinklo šaltinių, pvz., mobiliojo ryšio bokštų ir „Wi-Fi“ tinklų, duomenimis. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos planšetiniame kompiuteryje, kad programa galėtų jas naudoti."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ši programa gali gauti jūsų vietos informaciją naudodamasi tinklo šaltinių, pvz., mobiliojo ryšio bokštų ir „Wi-Fi“ tinklų, duomenimis. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos TV, kad programa galėtų jas naudoti."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ši programa gali gauti jūsų vietos informaciją naudodamasi tinklo šaltinių, pvz., mobiliojo ryšio bokštų ir „Wi-Fi“ tinklų, duomenimis. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos telefone, kad programa galėtų jas naudoti."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"pasiekti apytikslę vietovę (pagal tinklo duomenis), tik kai programa veikia priekiniame plane"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Ši programa gali gauti jūsų vietos informaciją naudodamasi tinklo šaltinių, pvz., mobiliojo ryšio bokštų ir „Wi-Fi“ tinklų, duomenimis, bet tik kai ji yra naudojama priekiniame plane. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos planšetiniame kompiuteryje, kad programa galėtų jas naudoti."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Ši programa gali gauti jūsų vietos informaciją naudodamasi tinklo šaltinių, pvz., mobiliojo ryšio bokštų ir „Wi-Fi“ tinklų, duomenimis, bet tik kai ji yra naudojama priekiniame plane. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos TV, kad programa galėtų jas naudoti."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Ši programa gali gauti jūsų vietos informaciją naudodamasi tinklo šaltinių, pvz., mobiliojo ryšio bokštų ir „Wi-Fi“ tinklų, duomenimis, bet tik kai ji yra naudojama priekiniame plane. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos telefone, kad programa galėtų jas naudoti."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"prieiga prie vietovės fone"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Jei papildomai suteikiama prieiga prie apytikslės arba tikslios vietovės, programa gali pasiekti vietovės duomenis veikdama fone."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"keisti garso nustatymus"</string>
@@ -1891,6 +1899,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS užklausa pakeista į USSD užklausą"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Pakeista į naują SS užklausą"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Darbo profilis"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Išskleisti"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Sutraukti"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"perjungti išskleidimą"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index d0c16d8..6f63f0c 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -137,6 +137,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi zvani | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Izslēgts"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Vēlams Wi-Fi tīkls"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Vēlams mobilo datu savienojums"</string>
@@ -420,10 +428,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Ļauj lietotnei piekļūt papildu atrašanās vietas noteikšanas nodrošinātāju komandām. Tas var ļaut lietotnei traucēt GPS vai citu atrašanās vietas noteikšanas avotu darbību."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"piekļuve precīzai atrašanās vietai, tikai darbojoties priekšplānā"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Šī lietotne var iegūt precīzu jūsu atrašanās vietu, tikai darbojoties priekšplānā. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu tālrunī, lai lietotne varētu tos izmantot. Tādējādi var palielināties akumulatora jaudas patēriņš."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"Piekļūt aptuvenai atrašanās vietai (izmantojot tīklu)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Šī lietotne var iegūt jūsu atrašanās vietu, pamatojoties uz tīkla avotiem, piemēram, mobilo sakaru torņiem un Wi-Fi tīkliem. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu planšetdatorā, lai lietotne tos varētu izmantot."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Šī lietotne var iegūt jūsu atrašanās vietu, pamatojoties uz tīkla avotiem, piemēram, mobilo sakaru torņiem un Wi-Fi tīkliem. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu televizorā, lai lietotne tos varētu izmantot."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Šī lietotne var iegūt jūsu atrašanās vietu, pamatojoties uz tīkla avotiem, piemēram, mobilo sakaru torņiem un Wi-Fi tīkliem. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu tālrunī, lai lietotne tos varētu izmantot."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"piekļuve aptuvenai atrašanās vietai (pēc tīkla datiem), tikai darbojoties priekšplānā"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Kad šī lietotne darbojas priekšplānā, tā var noteikt jūsu atrašanās vietu, izmantojot tīkla resursus, piemēram, mobilo sakaru torņus un Wi-Fi tīklus. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu planšetdatorā, lai lietotne varētu tos izmantot."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Kad šī lietotne darbojas priekšplānā, tā var noteikt jūsu atrašanās vietu, izmantojot tīkla resursus, piemēram, mobilo sakaru torņus un Wi-Fi tīklus. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu televizorā, lai lietotne varētu tos izmantot."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Kad šī lietotne darbojas priekšplānā, tā var noteikt jūsu atrašanās vietu, izmantojot tīkla resursus, piemēram, mobilo sakaru torņus un Wi-Fi tīklus. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu tālrunī, lai lietotne varētu tos izmantot."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"piekļūt atrašanās vietai fonā"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ja šī atļauja tiek piešķirta līdz ar piekļuvi aptuvenai vai precīzai atrašanās vietai, lietotne var piekļūt atrašanās vietai, darbojoties fonā."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"mainīt audio iestatījumus"</string>
@@ -1858,6 +1866,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS pieprasījums mainīts uz USSD pieprasījumu"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Mainīts uz jaunu SS pieprasījumu"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Darba profils"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Izvērst"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Sakļaut"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"izvērst/sakļaut"</string>
diff --git a/core/res/res/values-mcc302-mnc220/config.xml b/core/res/res/values-mcc302-mnc220/config.xml
index 36efd0a..c26bebe 100644
--- a/core/res/res/values-mcc302-mnc220/config.xml
+++ b/core/res/res/values-mcc302-mnc220/config.xml
@@ -33,7 +33,7 @@
         <item>LPP_PROFILE=3</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
 </resources>
diff --git a/core/res/res/values-mcc302-mnc221/config.xml b/core/res/res/values-mcc302-mnc221/config.xml
index a11dd95..96338b58 100644
--- a/core/res/res/values-mcc302-mnc221/config.xml
+++ b/core/res/res/values-mcc302-mnc221/config.xml
@@ -30,7 +30,7 @@
         <item>LPP_PROFILE=3</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
 </resources>
diff --git a/core/res/res/values-mcc302-mnc370/config.xml b/core/res/res/values-mcc302-mnc370/config.xml
index 8d29ec1..79f4bb6 100644
--- a/core/res/res/values-mcc302-mnc370/config.xml
+++ b/core/res/res/values-mcc302-mnc370/config.xml
@@ -34,7 +34,7 @@
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
 </resources>
diff --git a/core/res/res/values-mcc302-mnc610/config.xml b/core/res/res/values-mcc302-mnc610/config.xml
index 650aa62..10b007e 100644
--- a/core/res/res/values-mcc302-mnc610/config.xml
+++ b/core/res/res/values-mcc302-mnc610/config.xml
@@ -32,7 +32,7 @@
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
 </resources>
diff --git a/core/res/res/values-mcc302-mnc640/config.xml b/core/res/res/values-mcc302-mnc640/config.xml
index 4bb68dc..657d1e7 100644
--- a/core/res/res/values-mcc302-mnc640/config.xml
+++ b/core/res/res/values-mcc302-mnc640/config.xml
@@ -28,7 +28,7 @@
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
 </resources>
diff --git a/core/res/res/values-mcc302-mnc720/config.xml b/core/res/res/values-mcc302-mnc720/config.xml
index 735a8c8..ba8c75a 100644
--- a/core/res/res/values-mcc302-mnc720/config.xml
+++ b/core/res/res/values-mcc302-mnc720/config.xml
@@ -34,7 +34,7 @@
         <item>LPP_PROFILE=2</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
 </resources>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 4b3a53e..d8bb4a7 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi на <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Повици преку Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"Глас преку Wi-Fi на <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Исклучено"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Се претпочита Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Претпочитам мобилен интернет"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Овозможува апликацијата да пристапи кон дополнителни наредби на давател на локација. Ова може да овозможи апликацијата да го попечи функционирањето на GPS или други извори на локација."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"пристап до прецизната локација само во преден план"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Апликацијава може да ја добие вашата точна локација само кога е во преден план. Услугиве според локација мора да се вклучени и достапни на телефонот за да може да ги користи апликацијата. Ова може да го зголеми трошењето на батеријата."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"пристап до приближната локација (врз база на мрежа)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Апликацијава може да ја добие вашата локација од мрежните извори како што се репетиторите за мобилни мрежи и Wi-Fi мрежите. Овие услуги за локација мора да се вклучени и достапни на таблетот за да може да ги користи апликацијата."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Апликацијава може да ја добие вашата локација од мрежните извори како што се репетиторите за мобилни мрежи и Wi-Fi мрежите. Овие услуги за локација мора да се вклучени и достапни на телевизорот за да може да ги користи апликацијата."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Апликацијава може да ја добие вашата локација од мрежните извори како што се репетиторите за мобилни мрежи и Wi-Fi мрежите. Овие услуги за локација мора да се вклучени и достапни на телефонот за да може да ги користи апликацијата."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"пристап до приближна локација (според мрежа) само во преден план"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Апликацијава може да ја добие вашата локација од мрежните извори како што се репетиторите за мобилни мрежи и Wi-Fi мрежите, но само кога апликацијата е во преде план. Овие услуги за локација мора да се вклучени и достапни на таблетот за да може да ги користи апликацијата."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Апликацијава може да ја добие вашата локација од мрежните извори како што се репетиторите за мобилни мрежи и Wi-Fi мрежите, но само кога апликацијата е во преде план. Овие услуги за локација мора да се вклучени и достапни на телевизорот за да може да ги користи апликацијата."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Апликацијава може да ја добие вашата локација од мрежните извори како што се репетиторите за мобилни мрежи и Wi-Fi мрежите, но само кога апликацијата е во преде план. Овие услуги за локација мора да се вклучени и достапни на телефонот за да може да ги користи апликацијата."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"пристап до локацијата во заднина"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ако покрај дозволата за пристап до приближната или прецизната локација е доделена и оваа дозвола, тогаш апликацијата ќе може да пристапува до локацијата додека се извршува во заднина."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"менува аудио поставки"</string>
@@ -1828,6 +1836,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Барањето SS е изменето во барање USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Променето на ново барање SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Работен профил"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Прошири"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Собери"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"вклучи/исклучи проширување"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 2184af0..4a5f1cd 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> വൈഫൈ"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"വൈഫൈ കോളിംഗ് | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> Voവൈഫൈ"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ഓഫ്"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"വൈഫൈ തിരഞ്ഞെടുത്തിരിക്കുന്നു"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"മൊബൈൽ ഡാറ്റ ഉപയോഗിക്കാൻ താൽപ്പര്യപ്പെടുന്നു"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ലൊക്കേഷൻ ദാതാവിന്റെ അധിക കമാൻഡുകൾ ആക്‌സസ്സുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് GPS-ന്റെയോ മറ്റ് ലൊക്കേഷൻ ഉറവിടങ്ങളുടെയോ പ്രവർത്തനത്തിൽ ഇടപെടാൻ അപ്ലിക്കേഷനെ അനുവദിക്കാനിടയുണ്ട്."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"ഫോർഗ്രൗണ്ടിൽ മാത്രം കൃത്യമായ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യുക"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"ഫോർഗ്രൗണ്ടിൽ ഉള്ളപ്പോൾ മാത്രമേ ഈ ആപ്പിന് നിങ്ങളുടെ കൃത്യമായ ലൊക്കേഷൻ നേടാനാവൂ. ആപ്പിന് ഉപയോഗിക്കാനായി, ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓണായിരിക്കുകയും നിങ്ങളുടെ ഫോണിൽ ലഭ്യമാവുകയും വേണം. ഇതിലൂടെ ബാറ്ററി ഉപഭോഗം വർദ്ധിച്ചേക്കാം."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ഏകദേശ ലൊക്കേഷൻ (നെറ്റ്‌വർക്ക് അധിഷ്ഠിതം) ആക്സസ് ചെയ്യുക"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"സെൽ ടവറുകളും വൈഫൈ നെറ്റ്‌വർക്കുകളും പോലുള്ള നെറ്റ്‌വർക്ക് ഉറവിടങ്ങളെ അടിസ്ഥാനമാക്കിക്കൊണ്ട് ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ അനുമാനിക്കാൻ കഴിയും. നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓൺ ചെയ്തിട്ടുണ്ടെങ്കിൽ മാത്രമാണ് ആപ്പിന് അവ ഉപയോഗിക്കാൻ കഴിയുക."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"സെൽ ടവറുകളും വൈഫൈ നെറ്റ്‌വർക്കുകളും പോലുള്ള നെറ്റ്‌വർക്ക് ഉറവിടങ്ങളെ അടിസ്ഥാനമാക്കിക്കൊണ്ട് ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ അനുമാനിക്കാൻ കഴിയും. നിങ്ങളുടെ ടിവിയിൽ ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓൺ ചെയ്തിട്ടുണ്ടെങ്കിൽ മാത്രമാണ് ആപ്പിന് അവ ഉപയോഗിക്കാൻ കഴിയുക."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"സെൽ ടവറുകളും വൈഫൈ നെറ്റ്‌വർക്കുകളും പോലുള്ള നെറ്റ്‌വർക്ക് ഉറവിടങ്ങളെ അടിസ്ഥാനമാക്കിക്കൊണ്ട് ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ അനുമാനിക്കാൻ കഴിയും. നിങ്ങളുടെ ഫോണിൽ ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓൺ ചെയ്തിട്ടുണ്ടെങ്കിൽ മാത്രമാണ് ആപ്പിന് അവ ഉപയോഗിക്കാൻ കഴിയുക."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"ഫോർഗ്രൗണ്ടിൽ മാത്രം, ഏകദേശ ലൊക്കേഷൻ (നെറ്റ്‌വർക്ക്-അടിസ്ഥാനമാക്കി) ആക്‌സസ് ചെയ്യുക"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"സെൽ ടവറുകളും വൈഫൈ നെറ്റ്‌വർക്കുകളും പോലുള്ള നെറ്റ്‌വർക്ക് ഉറവിടങ്ങൾ അടിസ്ഥാനമാക്കി, ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ നേടാൻ‌ കഴിയും. എന്നാൽ, ഫോർഗ്രൗണ്ടിൽ ഉള്ളപ്പോൾ മാത്രമേ ആപ്പിന് ഇതിന് കഴിയൂ. ആപ്പിന് ഉപയോഗിക്കാനായി, ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓണായിരിക്കുകയും നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ ലഭ്യമാവുകയും വേണം."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"സെൽ ടവറുകളും വൈഫൈ നെറ്റ്‌വർക്കുകളും പോലുള്ള നെറ്റ്‌വർക്ക് ഉറവിടങ്ങൾ അടിസ്ഥാനമാക്കി, ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ നേടാൻ‌ കഴിയും. എന്നാൽ, ഫോർഗ്രൗണ്ടിൽ ഉള്ളപ്പോൾ മാത്രമേ ആപ്പിന് ഇതിന് കഴിയൂ. ആപ്പിന് ഉപയോഗിക്കാനായി, ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓണായിരിക്കുകയും നിങ്ങളുടെ ടിവിയിൽ ലഭ്യമാവുകയും വേണം."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"സെൽ ടവറുകളും വൈഫൈ നെറ്റ്‌വർക്കുകളും പോലുള്ള നെറ്റ്‌വർക്ക് ഉറവിടങ്ങൾ അടിസ്ഥാനമാക്കി, ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ നേടാൻ‌ കഴിയും. എന്നാൽ, ഫോർഗ്രൗണ്ടിൽ ഉള്ളപ്പോൾ മാത്രമേ ആപ്പിന് ഇതിന് കഴിയൂ. ആപ്പിന് ഉപയോഗിക്കാനായി, ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓണായിരിക്കുകയും നിങ്ങളുടെ ഫോണിൽ ലഭ്യമാവുകയും വേണം."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"പശ്ചാത്തലത്തിൽ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യുക"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ഏകദേശം അല്ലെങ്കിൽ കൃത്യമായ ലൊക്കേഷൻ ആക്‌സസിന് ഇത് അധികമായി അനുവദിച്ചതാണെങ്കിൽ, പശ്ചാത്തലത്തിൽ റൺ ചെയ്യുമ്പോഴും ആപ്പിന് ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യാനാവും."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"നിങ്ങളുടെ ഓഡിയോ ക്രമീകരണങ്ങൾ മാറ്റുക"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS അഭ്യർത്ഥന, USSD അഭ്യർത്ഥനയിലേക്ക് മാറ്റി"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"പുതിയ SS അഭ്യർത്ഥനയിലേക്ക് മാറ്റി"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"വികസിപ്പിക്കുക"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"ചുരുക്കുക"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"വികസിപ്പിക്കൽ ടോഗിൾ ചെയ്യുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 45e118f..994b4d9 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"WiFi дуудлага | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Идэвхгүй"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi давуу эрхтэй"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Мобайл давуу эрхтэй"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Апп нь байршил нийлүүлэгчийн нэмэлт тушаалд хандах боломжтой. Энэ нь апп-д GPS эсвэл бусад байршлын үйлчилгээний ажиллагаанд нөлөөлөх боломжийг олгоно."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"нарийвчилсан байршилд зөвхөн нүүр хэсэгт хандах"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Энэ апп нь зөвхөн нүүр хэсэгт байх үедээ л таны байршлыг нарийн тогтоох боломжтой. Апп эдгээр байршлын үйлчилгээг ашиглахын тулд эдгээрийг таны утсан дээр асааж идэвхтэй байлгах шаардлагатай. Энэ нь батарейны хэрэглээг ихэсгэж болзошгүй."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ойролцоох байршилд хандах (сүлжээнд суурилсан)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Энэ апп үүрэн цамхаг, Wi-Fi сүлжээ зэрэг сүлжээний байршлын эх сурвалжийг ашиглан таны байршлыг мэдэх боломжтой. Эдгээр байршлын үйлчилгээ нь таны таблетад асаалттай байх ёстой ба апп ашиглах боломжтой байх ёстой."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Энэ апп үүрэн цамхаг, Wi-Fi сүлжээ зэрэг сүлжээний байршлын эх сурвалжийг ашиглан таны байршлыг мэдэх боломжтой. Эдгээр байршлын үйлчилгээ нь таны ТВ-д асаалттай байх ёстой ба апп ашиглах боломжтой байх ёстой."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Энэ апп үүрэн цамхаг, Wi-Fi сүлжээ зэрэг сүлжээний байршлын эх сурвалжийг ашиглан таны байршлыг мэдэх боломжтой. Эдгээр байршлын үйлчилгээ нь таны утсанд асаалттай байх ёстой ба апп ашиглах боломжтой байх ёстой."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"ойролцоох байршилд (сүлжээнд суурилсан) зөвхөн дэлгэц дээр хандах"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Энэ апп зөвхөн дэлгэц дээр байх үед үүрэн цамхаг, Wi-Fi сүлжээ зэрэг сүлжээний эх сурвалжид тулгуурлан таны байршлыг мэдэх боломжтой. Та энэ аппад эдгээр байршлын үйлчилгээг ашиглуулахын тулд эдгээрийг таблет дээрээ асааж, боломжтой байлгах шаардлагатай."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Энэ апп зөвхөн дэлгэц дээр байх үед үүрэн цамхаг, Wi-Fi сүлжээ зэрэг сүлжээний эх сурвалжид тулгуурлан таны байршлыг мэдэх боломжтой. Та энэ аппад эдгээр байршлын үйлчилгээг ашиглуулахын тулд эдгээрийг TB дээрээ асааж, боломжтой байлгах шаардлагатай."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Энэ апп зөвхөн дэлгэц дээр байх үед үүрэн цамхаг, Wi-Fi сүлжээ зэрэг сүлжээний эх сурвалжид тулгуурлан таны байршлыг мэдэх боломжтой. Та энэ аппад эдгээр байршлын үйлчилгээг ашиглуулахын тулд эдгээрийг утсан дээрээ асааж, боломжтой байлгах шаардлагатай."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"байршилд ард хандах"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Хэрэв үүнийг ойролцоо эсвэл нарийвчилсан байршлын хандалтад нэмэлтээр зөвшөөрсөн бол энэ апп ард ажиллах явцдаа байршилд хандаж болно."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"Аудио тохиргоо солих"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS хүсэлтийг USSD хүсэлт болгон өөрчилсөн"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Шинэ SS хүсэлт болгон өөрчилсөн"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Ажлын профайл"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Дэлгэх"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Буулгах"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"унтраах/асаах өргөтгөл"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index fb4c408..ca7f6df 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> वाय-फाय"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"वाय-फाय कॉलिंग | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"बंद"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"वाय-फाय अग्रमानांकित"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"प्राधान्य दिलेला मोबाइल"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"अ‍ॅपला अतिरिक्त स्‍थान प्रदाता आदेशावर प्रवेश करण्‍याची अनुमती देते. हे कदाचित अ‍ॅपला GPS किंवा इतर स्‍थान स्त्रोत च्या ऑपरेशनमध्‍ये हस्तक्षेप करण्‍याची अनुमती देऊ शकते."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"फक्त फोरग्राउंडमध्ये अचूकपणे अ‍ॅक्सेस करा"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"हे अ‍ॅप फक्त फोरग्राउंडमध्ये असतानाच तुमचे अचूक स्थान मिळवू शकते. या स्थान सेवा सुरू करणे आणि त्या वापरण्यासाठी अ‍ॅपसाठी तुमच्या फोनवर उपलब्ध करणे आवश्यक आहे, यामुळे बॅटरी वापर वाढू शकतो."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"अंदाजे स्‍थानामध्ये (नेटवर्क-आधारित) अॅक्सेस करा"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतांच्या आधारावर तुमचे स्थान मिळवू शकतो. अॅपला या स्थान सेवा वापरण्यास सक्षम असण्यासाठी तुमच्या टॅब्लेटवर त्या चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतांच्या आधारावर तुमचे स्थान मिळवू शकतो. अॅपला या स्थान सेवा वापरण्यास सक्षम असण्यासाठी तुमच्या टीव्हीवर त्या चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतांच्या आधारावर तुमचे स्थान मिळवू शकतो. अॅपला या स्थान सेवा वापरण्यास सक्षम असण्यासाठी तुमच्या फोनवर त्या चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"फक्त फोरग्राउंडमध्ये अंदाजे स्थान (नेटवर्क आधारित) अ‍ॅक्सेस करा"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"हे अ‍ॅप फक्त फोरग्राउंडमध्ये असतानाच, सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतवर आधारित तुमचे स्थान मिळवू शकते. त्या वापरण्याकरता अॅपसाठी, या स्थान सेवा सुरू करणे आणि त्या तुमच्या टॅबलेटवर उपलब्ध करणे आवश्यक आहे."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"हे अ‍ॅप फक्त फोरग्राउंडमध्ये असतानाच, सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतवर आधारित तुमचे स्थान मिळवू शकते. त्या वापरण्याकरता अॅपसाठी, या स्थान सेवा सुरू करणे आणि त्या तुमच्या टीव्हीवर उपलब्ध करणे आवश्यक आहे."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"हे अ‍ॅप फक्त फोरग्राउंडमध्ये असतानाच, सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतवर आधारित तुमचे स्थान मिळवू शकते. ते वापरण्याकरता अॅपसाठी, या स्थान सेवा सुरू करणे आणि त्या तुमच्या फोनवर उपलब्ध करणे आवश्यक आहे."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"बॅकग्राउंडमध्ये स्थान अॅक्सेस करू शकतो"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"याला अंदाजे किंवा अचूक स्थान अॅक्सेस करण्यास अतिरिक्त मंजूरी दिल्यास, बॅकग्राउंडमध्ये चालतांना अॅप स्थान अॅक्सेस करू शकतो."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"आपल्या ऑडिओ सेटिंग्ज बदला"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS विनंती USSD विनंतीवर बदलली"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"नवीन SS विनंतीवर बदलली"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"कार्य प्रोफाईल"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"विस्तृत करा"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"संकुचित करा"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"टॉगल विस्तार"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 2896923..a1af8f2 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Panggilan Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Mati"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi diutamakan"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mudah alih diutamakan"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Membenarkan apl mengakses arahan pembekal lokasi tambahan. Ini boleh membenarkan apl untuk campur tangan dengan operasi GPS atau sumber lokasi lain."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"akses lokasi tepat hanya di latar depan"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Apl ini boleh mendapatkan lokasi tepat anda hanya apabila apl tersebut berada di latar depan. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada telefon anda untuk membolehkan apl menggunakan perkhidmatan tersebut. Tindakan ini mungkin meningkatkan penggunaan bateri."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"akses lokasi anggaran (berasaskan rangkaian)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Apl ini boleh mendapatkan lokasi anda berdasarkan sumber rangkaian seperti menara selular dan rangkaian Wi-Fi. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada tablet anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Apl ini boleh mendapatkan lokasi anda berdasarkan sumber rangkaian seperti menara selular dan rangkaian Wi-Fi. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada TV anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Apl ini boleh mendapatkan lokasi anda berdasarkan sumber rangkaian seperti menara selular dan rangkaian Wi-Fi. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada telefon anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"akses lokasi anggaran (berdasarkan rangkaian) hanya di latar depan"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Apl ini boleh mendapatkan lokasi anda berdasarkan sumber rangkaian seperti menara selular dan rangkaian Wi-Fi, tetapi hanya apabila apl itu di latar depan. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada tablet anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Apl ini boleh mendapatkan lokasi anda berdasarkan sumber rangkaian seperti menara selular dan rangkaian Wi-Fi, tetapi hanya apabila apl itu di latar depan. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada TV anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Apl ini boleh mendapatkan lokasi anda berdasarkan sumber rangkaian seperti menara selular dan rangkaian Wi-Fi, tetapi hanya apabila apl itu di latar depan. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada telefon anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"akses lokasi di latar belakang"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Jika tindakan ini dibenarkan bagi akses lokasi anggaran atau lokasi tepat, apl tersebut boleh mengakses lokasi itu semasa berjalan di latar belakang."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"tukar tetapan audio anda"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Permintaan SS ditukar kepada permintaan USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Bertukar kepada permintaan SS baharu"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Profil kerja"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Kembangkan"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Runtuhkan"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"togol pengembangan"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index e509577..372be10 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"WiFi ခေါ်ဆိုမှု | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ပိတ်ထားရသည်"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"ဝိုင်ဖိုင်အား ပိုနှစ်သက်သော"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"မိုဘိုင်းကို အသုံးပြုလိုပါသည်"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"အက်ပ်အား တည်နေရာ စီမံပေးရေး ညွှန်ကြားချက် အပိုများကို ရယူခွင့်ပြုသည်။ သို့ဖြစ်၍ အက်ပ်သည် GPS သို့မဟုတ် အခြား တည်နေရာ ရင်းမြစ်ကို သုံးကြသူတို့၏ လုပ်ငန်းများကို ဝင်စွက်ခွင့် ပြုနိုင်သည်။"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"မျက်နှာစာတွင်သာ တည်နေရာအတိအကျ အသုံးပြုခြင်း"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"မျက်နှာစာတွင် ဖွင့်ထားမှသာ ဤအက်ပ်က သင်၏တည်နေရာအတိအကျကို ရယူနိုင်ပါသည်။ သင်၏ဖုန်းတွင် အက်ပ်ကအသုံးပြုရန်အတွက် ဤတည်နေရာဝန်ဆောင်မှုများကို ဖွင့်ထားပြီး အသုံးပြု၍ ရပါမည်။ ၎င်းက ဘက်ထရီ ပိုကုန်နိုင်ပါသည်။"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"အနီးစပ်ဆုံး တည်နေရာ (ကွန်ရက် အခြေခံ)ကို ရယူသုံးရန်"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ဤအက်ပ်သည် ဆဲလ်တာဝါများနှင့် Wi-Fi ကွန်ရက်များကဲ့သို့ ကွန်ရက်အရင်းအမြစ်ပေါ် အခြေခံပြီး သင့်တည်နေရာအချက်အလက်ကို ရယူနိုင်ပါသည်။ အက်ပ်က အသုံးပြုနိုင်ရန်အတွက် ဤတည်နေရာ ဝန်ဆောင်မှုများကို ဖွင့်ထားရမည် ဖြစ်ပြီး သင့်တက်ဘလက်ပေါ်တွင် ရရှိနိုင်ရပါမည်။"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ဤအက်ပ်သည် ဆဲလ်တာဝါများနှင့် Wi-Fi ကွန်ရက်များကဲ့သို့ ကွန်ရက်အရင်းအမြစ်ပေါ် အခြေခံပြီး သင့်တည်နေရာအချက်အလက်ကို ရယူနိုင်ပါသည်။ အက်ပ်က အသုံးပြုနိုင်ရန်အတွက် ဤတည်နေရာ ဝန်ဆောင်မှုများကို ဖွင့်ထားရမည် ဖြစ်ပြီး သင့်တီဗီပေါ်တွင် ရရှိနိုင်ရပါမည်။"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ဤအက်ပ်သည် ဆဲလ်တာဝါများနှင့် Wi-Fi ကွန်ရက်များကဲ့သို့ ကွန်ရက်အရင်းအမြစ်ပေါ် အခြေခံပြီး သင့်တည်နေရာအချက်အလက်ကို ရယူနိုင်ပါသည်။ အက်ပ်က အသုံးပြုနိုင်ရန်အတွက် ဤတည်နေရာ ဝန်ဆောင်မှုများကို ဖွင့်ထားရမည် ဖြစ်ပြီး သင့်ဖုန်းပေါ်တွင် ရရှိနိုင်ရပါမည်။"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"မျက်နှာစာတွင်သာ (ကွန်ရက် အခြေပြု) တည်နေရာခန့်မှန်း အသုံးပြုခြင်း"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"ဤအက်ပ်က ဆဲလ်တာဝါများနှင့် Wi-Fi ကွန်ရက်များကဲ့သို့ ကွန်ရက်ရင်းမြစ်များအပေါ် အခြေခံပြီး သင်၏တည်နေရာကို ရယူနိုင်သော်လည်း အက်ပ်ကို မျက်နှာစာတွင်ဖွင့်ထားမှ ရပါမည်။ အက်ပ်က အသုံးပြုနိုင်ရန်အတွက် ဤတည်နေရာ ဝန်ဆောင်မှုများကို ဖွင့်ထားရမည် ဖြစ်ပြီး သင့်တက်ဘလက်ပေါ်တွင် ရရှိနိုင်ရပါမည်။"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"ဤအက်ပ်က ဆဲလ်တာဝါများနှင့် Wi-Fi ကွန်ရက်များကဲ့သို့ ကွန်ရက်ရင်းမြစ်များအပေါ် အခြေခံပြီး သင်၏တည်နေရာကို ရယူနိုင်သော်လည်း အက်ပ်ကို မျက်နှာစာတွင်ဖွင့်ထားမှ ရပါမည်။ အက်ပ်က အသုံးပြုနိုင်ရန်အတွက် ဤတည်နေရာ ဝန်ဆောင်မှုများကို ဖွင့်ထားရမည် ဖြစ်ပြီး သင့်တီဗီပေါ်တွင် ရရှိနိုင်ရပါမည်။"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"ဤအက်ပ်က ဆဲလ်တာဝါများနှင့် Wi-Fi ကွန်ရက်များကဲ့သို့ ကွန်ရက်ရင်းမြစ်များအပေါ် အခြေခံပြီး သင်၏တည်နေရာကို ရယူနိုင်သော်လည်း အက်ပ်ကို မျက်နှာစာတွင်ဖွင့်ထားမှ ရပါမည်။ အက်ပ်က အသုံးပြုနိုင်ရန်အတွက် ဤတည်နေရာ ဝန်ဆောင်မှုများကို ဖွင့်ထားရမည် ဖြစ်ပြီး သင့်ဖုန်းပေါ်တွင် ရရှိနိုင်ရပါမည်။"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"နောက်ခံတွင် တည်နေရာကို အသုံးပြုရန်"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ခန့်မှန်းခြေ သို့မဟုတ် တိကျသော တည်နေရာ ဝင်သုံးခွင့်အတွက် ၎င်းကို နောက်ဆက်တွဲ ခွင့်ပြုထားပါက နောက်ခံတွင် လုပ်ဆောင်နေစဉ် အက်ပ်က တည်နေရာကို ရယူအသုံးပြုနိုင်ပါသည်။"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"သင့်အသံအပြင်အဆင်အားပြောင်းခြင်း"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS တောင်းဆိုမှုကို USSD တောင်းဆိုမှုအဖြစ် ပြောင်းထားသည်"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"SS တောင်းဆိုမှုအသစ်သို့ ပြောင်းထားသည်"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"အလုပ်ကိုယ်ရေးအချက်အလက်"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"ချဲ့ရန်"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"ခေါက်သိမ်းရန်"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"ချဲ့ခြင်းခလုတ်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index b47c965..5fc75ad 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi-anrop | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Av"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi er foretrukket"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Først-på-mobil"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Appen gis tillatelse til å bruke ekstra kommandoer fra posisjonsleverandører. Dette kan gi appen tillatelse til å påvirke bruken av GPS eller andre posisjonskilder."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"bare tilgang til nøyaktig posisjon i forgrunnen"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Denne appen kan bare få den nøyaktige posisjonen din når den er på i forgrunnen. Disse posisjonstjenestene må være slått på og tilgjengelige på telefonen din for at appen skal kunne bruke dem. Dette kan øke batteriforbruket."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"få tilgang til omtrentlig posisjon (nettverksbasert)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Denne appen kan få posisjonen din fra nettverkskilder som mobilmaster og Wi-Fi-nettverk. Disse posisjonstjenestene må være slått på og tilgjengelige på nettbrettet ditt for at appen skal kunne bruke dem."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Denne appen kan få posisjonen din fra nettverkskilder som mobilmaster og Wi-Fi-nettverk. Disse posisjonstjenestene må være slått på og tilgjengelige på TV-en din for at appen skal kunne bruke dem."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Denne appen kan få posisjonen din fra nettverkskilder som mobilmaster og Wi-Fi-nettverk. Disse posisjonstjenestene må være slått på og tilgjengelige på telefonen din for at appen skal kunne bruke dem."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"bare tilgang til omtrentlig posisjon (nettverksbasert) i forgrunnen"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Denne appen kan bare få posisjonen din basert på nettverkskilder, for eksempel mobilmaster og Wi-Fi-nettverk, når den er på i forgrunnen. Disse posisjonstjenestene må være slått på og tilgjengelige på nettbrettet ditt for at appen skal kunne bruke dem."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Denne appen kan bare få posisjonen din basert på nettverkskilder, for eksempel mobilmaster og Wi-Fi-nettverk, når den er på i forgrunnen. Disse posisjonstjenestene må være slått på og tilgjengelige på TV-en din for at appen skal kunne bruke dem."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Denne appen kan bare få posisjonen din basert på nettverkskilder, for eksempel mobilmaster og Wi-Fi-nettverk, når den er på i forgrunnen. Disse posisjonstjenestene må være slått på og tilgjengelige på telefonen din for at appen skal kunne bruke dem."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"tilgang til posisjon i bakgrunnen"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Hvis du gir denne tillatelsen, får appen tilgang til posisjonen mens den kjører i bakgrunnen, i tillegg til tilgang til omtrentlig eller presis posisjon."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"endre lydinnstillinger"</string>
@@ -528,7 +536,7 @@
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Deler av fingeravtrykket er registrert. Prøv på nytt."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Kunne ikke registrere fingeravtrykket. Prøv på nytt."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Fingeravtrykksensoren er skitten. Rengjør den og prøv på nytt."</string>
-    <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Du flyttet fingeren for kjapt. Prøv på nytt."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Du flyttet fingeren for raskt. Prøv på nytt."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Du flyttet fingeren for sakte. Prøv på nytt."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
@@ -541,7 +549,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsavbrudd for fingeravtrykk er nådd. Prøv på nytt."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeravtrykk-operasjonen ble avbrutt."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Fingeravtrykk-operasjonen ble avbrutt av brukeren."</string>
-    <string name="fingerprint_error_lockout" msgid="5536934748136933450">"For mange forsøk. Prøve på nytt senere."</string>
+    <string name="fingerprint_error_lockout" msgid="5536934748136933450">"For mange forsøk. Prøv på nytt senere."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"For mange forsøk. Fingeravtrykkssensoren er slått av."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Prøv igjen."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Ingen fingeravtrykk er registrert."</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS-forespørsel endret til USSD-forespørsel"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Endret til ny SS-forespørsel"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Arbeidsprofil"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Vis"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Skjul"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"slå utvidelse av/på"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 47d4d6a..cddd308 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wifi कलिङ | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"निष्क्रिय"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi मनपराइयो"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"रूचाइएको मोबाइल"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"अनुप्रयोगलाई अतिरिक्त स्थान प्रदायक आदेशहरू पहुँच गर्न अनुमति दिन्छ। यो अनुप्रयोगलाई GPS वा अन्य स्थान स्रोतहरूको संचालन साथै हस्तक्षेप गर्न अनुमति दिन सक्छ।"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"अग्रभूमिमा मात्र सटीक स्थानमाथि पहुँच राख्नुहोस्"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"यो अनुप्रयोगले अग्रभागमा चलिरहेको अवस्थामा मात्र तपाईंलाई स्थानको सटिक जानकारी दिन सक्छ। यी स्थानसम्बन्धी सेवाहरू अनिवार्य रूपमा सक्रिय गरिएका हुनु पर्छ र अनुप्रयोगले यिनीहरूको प्रयोग गर्न सकोस् भन्नाका खातिर तपाईंको फोनमै उपलब्ध हुन्छन्। यस कार्यले गर्दा ब्याट्री बढी खर्च हुन सक्छ।"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"अनुमानित स्थान पहुँच गराउनुहोस् (नेटवर्कमा आधारित)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको ट्याब्लेटमा उपलब्ध हुनु पर्छ।"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको TV मा उपलब्ध हुनु पर्छ।"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको फोनमा उपलब्ध हुनु पर्छ।"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"अग्रभूमिमा मात्र अनुमानित स्थान (नेटवर्कमा आधारित) माथि पहुँच राख्नुहोस्"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको ट्याब्लेटमा उपलब्ध हुनु पर्छ।"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको TV मा उपलब्ध हुनु पर्छ।"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको फोनमा उपलब्ध हुनु पर्छ।"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"पृष्ठभूमिमा स्थानसम्बन्धी पहुँच"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"यसका अतिरिक्त यसलाई अनुमानित वा सटिक स्थानमाथि पहुँच राख्ने अनुमति दिइएको छ भने उक्त अनुप्रयोगले पृष्ठभूमिमा चलिरहेको बेला स्थानमाथि पहुँच राख्न सक्छ।"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"तपाईँका अडियो सेटिङहरू परिवर्तन गर्नुहोस्"</string>
@@ -1831,6 +1839,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS अनुरोधलाई USSD अनुरोधमा परिवर्तन गरियो"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"नयाँ SS अनुरोधमा परिवर्तन गरियो"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"कार्य प्रोफाइल"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"विस्तृत गर्नुहोस्"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"संक्षिप्त गर्नुहोस्"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"विस्तारलाई टगल गर्नुहोस्"</string>
diff --git a/core/res/res/values-night/themes_device_defaults.xml b/core/res/res/values-night/themes_device_defaults.xml
index 931674a..84c6446 100644
--- a/core/res/res/values-night/themes_device_defaults.xml
+++ b/core/res/res/values-night/themes_device_defaults.xml
@@ -52,6 +52,9 @@
     <!-- DeviceDefault theme for a window that should look like the Settings app.  -->
     <style name="Theme.DeviceDefault.Settings" parent="Theme.DeviceDefault">
         <item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
+        <item name="colorBackground">@color/primary_dark_device_default_settings</item>
+
+        <item name="listDivider">@color/list_divider_color_dark</item>
     </style>
 
     <!-- Theme for the dialog shown when an app crashes or ANRs. -->
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index ed79f7b..c1883fa 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wifi van <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Bellen via wifi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi van <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Uit"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Voorkeur voor wifi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Voorkeur voor mobiel"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Hiermee kan de app toegang krijgen tot extra opdrachten voor de locatieprovider. De app kan hiermee de werking van gps of andere locatiebronnen te verstoren."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"alleen toegang tot precieze locatie op de voorgrond"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Deze app kan je exacte locatie ophalen wanneer de app op de voorgrond wordt uitgevoerd. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je telefoon. Hierdoor kan het batterijverbruik toenemen."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"toegang tot geschatte locatie (netwerkgebaseerd)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Deze app kan je locatie ophalen op basis van netwerkbronnen zoals zendmasten en wifi-netwerken. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je tablet."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Deze app kan je locatie ophalen op basis van netwerkbronnen zoals zendmasten en wifi-netwerken. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je tv."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Deze app kan je locatie ophalen op basis van netwerkbronnen zoals zendmasten en wifi-netwerken. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je telefoon."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"alleen toegang tot geschatte locatie (op basis van netwerk) op de voorgrond"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Deze app kan je locatie ophalen op basis van netwerkbronnen zoals zendmasten en wifi-netwerken, maar alleen wanneer de app zich op de voorgrond bevindt. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je tablet."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Deze app kan je locatie ophalen op basis van netwerkbronnen zoals zendmasten en wifi-netwerken, maar alleen wanneer de app zich op de voorgrond bevindt. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je tv."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Deze app kan je locatie ophalen op basis van netwerkbronnen zoals zendmasten en wifi-netwerken, maar alleen wanneer de app zich op de voorgrond bevindt. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je telefoon."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"toegang tot locatie op de achtergrond"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Als dit wordt verleend als aanvulling op toegang tot de geschatte of precieze locatie, kan de app toegang tot de locatie krijgen terwijl de app actief is op de achtergrond."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"je audio-instellingen wijzigen"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS-verzoek gewijzigd in USSD-verzoek"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Gewijzigd in nieuw SS-verzoek"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Werkprofiel"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Uitvouwen"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Samenvouwen"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"uitvouwen in-/uitschakelen"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 031cacb..59c689b 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> ୱାଇ-ଫାଇ"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"ୱାଇଫାଇ କଲିଂ | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ଅଫ୍"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"ପସନ୍ଦ କରାଯାଇଥିବା ୱାଇ-ଫାଇ"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"ପସନ୍ଦର ମୋବାଇଲ୍‌"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ଅତିରିକ୍ତ ଲୋକେଶନ୍‍ ପ୍ରଦାନକାରୀ କମାଣ୍ଡ ଆକ୍ସେସ୍‌ କରିବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦିଏ। GPS କିମ୍ବା ଅନ୍ୟ ଲୋକେଶନ୍‍ ସୋର୍ସଗୁଡିକରେ ଆପ୍‍ଟି ପ୍ରଭାବ ପକାଇପାରେ।"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"କେବଳ ସମ୍ମୁଖଭାଗରେ ସଠିକ୍‍ ଲୋକେଶନ୍‍ର ଆକ୍ସେସ୍‍ କରନ୍ତୁ"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"ଏହି ଆପ୍‍ ଯେତେବେଳେ ସମ୍ମୁଖଭାଗରେ ଥିବାବେଳେ ଆପଣଙ୍କର ସଠିକ୍‍ ଲୋକେଶନ୍‍ ପ୍ରାପ୍ତ କରିପାରିବ। ଏହି ଲୋକେଶନ୍‍ ସେବାଗୁଡ଼ିକ ନିଶ୍ଚିତରୂପେ ଅନ୍‍ ରହିବା ଦରକାର ଏବଂ ଆପ୍‍ର ବ୍ୟବହାର ପାଇଁ ଫୋନ୍‍ରେ ଉପଲବ୍ଧ ଥିବା ଦରକାର। ଏହା ବ୍ୟାଟେରୀ ଅଧିକା ଖର୍ଚ୍ଚ କରିପାରେ।"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ପାଖାପାଖି ଲୋକେଶନ୍‍ ଆକ୍ସେସ୍‍ କରେ (ନେଟ୍‌ୱର୍କ-ଆଧାରିତ)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ଏହି ଆପ୍‍, ନେଟ୍‌ୱର୍କ ସୋର୍ସ ଉପରେ ଆଧାର କରି ଆପଣଙ୍କ ଲୋକେଶନ୍‍ ପ୍ରାପ୍ତ କରିପାରେ, ଯେପରିକି ସେଲ୍‍ ଟାୱାର୍‍ ଓ ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ। ଏହି ଲୋକେଶନ୍‌ ସେବା, ଆପଣଙ୍କ ଟାବଲେଟ୍‌ରେ ଅନ୍‍ ରହିଥିବା ଓ ଉପଲବ୍ଧ ଥିବା ଦରକାର, ଯେଉଁଥିରୁ ଆପ୍‌ ସେଗୁଡ଼ିକର ବ୍ୟବହାର କରିପାରିବ।"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ଏହି ଆପ୍‍, ନେଟ୍‌ୱର୍କ ସୋର୍ସ ଉପରେ ଆଧାର କରି ଆପଣଙ୍କ ଲୋକେଶନ୍‍ ପ୍ରାପ୍ତ କରିପାରେ, ଯେପରିକି ସେଲ୍‍ ଟାୱାର୍‍ ଓ ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ। ଏହି ଲୋକେଶନ୍‌ ସେବା, ଆପଣଙ୍କ ଟିଭିରେ ଅନ୍‍ ରହିଥିବା ଓ ଉପଲବ୍ଧ ଥିବା ଦରକାର, ଯେଉଁଥିରୁ ଆପ୍‌ ସେଗୁଡ଼ିକର ବ୍ୟବହାର କରିପାରିବ।"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ସେଲ୍‍ ଟାୱାର ଓ ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ ପରି ସୋର୍ସକୁ ଆଧାର କରି ଏହି ଆପ୍‍ ଆପଣଙ୍କ ଲୋକେଶନ୍‍ ପ୍ରାପ୍ତ କରିପାରିବ। ଏହି ଲୋକେଶନ୍‍ ସେବାଗୁଡ଼ିକର ବ୍ୟବହାର କରିବାକୁ ସେଗୁଡ଼ିକ ଅନ୍‍ କରାଯିବା ଏବଂ ଆପଣଙ୍କ ଫୋନ୍‌ରେ ଉପଲବ୍ଧ ଥିବା ଜରୁରୀ"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"କେବଳ ସମ୍ମୁଖଭାଗରେ ହାରାହାରି ଲୋକେସନ୍‍ (ନେଟ୍‍ୱର୍କ-ଆଧାରିତ)ର ଆକ୍ସେସ୍‍ କରନ୍ତୁ"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"ସେଲ୍‍ ଟାୱାର ଓ ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ ପରି ଉତ୍ସକୁ ଆଧାର କରି ଏହି ଆପ୍‍ ଆପଣଙ୍କ ଲୋକେସନ୍‍ ପ୍ରାପ୍ତ କରିପାରିବ। ଏହି ଲୋକେସନ୍‍ ସେବାଗୁଡ଼ିକର ବ୍ୟବହାର କରିବାକୁ ସେଗୁଡ଼ିକ ଚାଲୁ କରାଯିବା ଏବଂ ଆପଣଙ୍କ ଟାବ୍‍‍‍ଲେଟ୍‍‍ରେ ଉପଲବ୍ଧ ଥିବା ଜରୁରୀ ଅଟେ।"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"ସେଲ୍‍ ଟାୱାର ଓ ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ ପରି ଉତ୍ସକୁ ଆଧାର କରି ଏହି ଆପ୍‍ ଆପଣଙ୍କ ଲୋକେସନ୍‍ ପ୍ରାପ୍ତ କରିପାରିବ। ଏହି ଲୋକେସନ୍‍ ସେବାଗୁଡ଼ିକର ବ୍ୟବହାର କରିବାକୁ ସେଗୁଡ଼ିକ ଚାଲୁ କରାଯିବା ଏବଂ ଆପଣଙ୍କ ଟିଭିରେ ଉପଲବ୍ଧ ଥିବା ଜରୁରୀ ଅଟେ।"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"ସେଲ୍‍ ଟାୱାର ଓ ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ ପରି ଉତ୍ସକୁ ଆଧାର କରି ଏହି ଆପ୍‍ ଆପଣଙ୍କ ଲୋକେସନ୍‍ ପ୍ରାପ୍ତ କରିପାରିବ। ଏହି ଲୋକେସନ୍‍ ସେବାଗୁଡ଼ିକର ବ୍ୟବହାର କରିବାକୁ ସେଗୁଡ଼ିକ ଚାଲୁ କରାଯିବା ଏବଂ ଆପଣଙ୍କ ଫୋନ୍‌ରେ ଉପଲବ୍ଧ ଥିବା ଜରୁରୀ ଅଟେ।"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ବ୍ୟାକ୍‌ଗ୍ରାଉଣ୍ଡ୍‌ରେ ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ଅନୁମାନିତ କିମ୍ବା ବିଲ୍‌କୁଲ୍ ସଠିକ୍ ସ୍ଥାନ ଆକ୍ସେସ୍ କରିବାର ଅନୁମତି ଅତିରିକ୍ତ ଭାବରେ ଦିଆଗଲେ, ବ୍ୟାକ୍‌ଗ୍ରାଉଣ୍ଡରେ ଚାଲୁଥିବା ସମୟରେ ଆପ୍ ଆପଣଙ୍କର ସ୍ଥାନର ଆକ୍ସେସ୍ କରିପାରିବ।"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ଆପଣଙ୍କ ଅଡିଓ ସେଟିଙ୍ଗକୁ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS ଅନୁରୋଧ, USSD ଅନୁରୋଧକୁ ପରିବର୍ତ୍ତନ ହେଲା"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"ନୂତନ SS ଅନୁରୋଧରେ ପରିବର୍ତ୍ତନ ହେଲା"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"ବଢ଼ାନ୍ତୁ"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"ଛୋଟ କରନ୍ତୁ"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"ଟୋଗଲ୍‍ ସମ୍ପ୍ରସାରଣ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 2b30459..0bbe94d 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> ਵਾਈ-ਫਾਈ"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"ਵਾਈ-ਫਾਈ ਕਾਲਿੰਗ | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ਬੰਦ"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"ਤਰਜੀਹੀ ਵਾਈ-ਫਾਈ"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"ਮੋਬਾਈਲ ਨੂੰ ਤਰਜੀਹ ਹੈ"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ਐਪ ਨੂੰ ਵਾਧੂ ਟਿਕਾਣਾ ਪ੍ਰਦਾਤਾ ਕਮਾਂਡਾਂ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ GPS ਜਾਂ ਹੋਰ ਟਿਕਾਣਾ ਸਰੋਤਾਂ ਦੇ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾਉਣ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ।"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"ਸਿਰਫ਼ ਫੋਰਗ੍ਰਾਊਂਡ ਵਿੱਚ ਸਟੀਕ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"ਇਹ ਐਪ ਫੋਰਗ੍ਰਾਉਂਡ ਵਿੱਚ ਹੋਣ \'ਤੇ ਹੀ ਤੁਹਾਡਾ ਸਟੀਕ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ। ਇਸ ਨਾਲ ਬੈਟਰੀ ਦੀ ਖਪਤ ਵਧ ਸਕਦੀ ਹੈ।"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ਅੰਦਾਜ਼ਨ ਟਿਕਾਣੇ \'ਤੇ ਪਹੁੰਚ ਕਰੋ (ਨੈੱਟਵਰਕ-ਆਧਾਰਿਤ)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਦੁਆਰਾ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਟੀਵੀ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"ਸਿਰਫ਼ ਫੋਰਗ੍ਰਾਊਂਡ ਵਿੱਚ ਅਨੁਮਾਨਿਤ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰੋ (ਨੈੱਟਵਰਕ-ਆਧਾਰਿਤ)"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ, ਪਰ ਸਿਰਫ਼ ਐਪ ਦੇ ਫੋਰਗ੍ਰਾਊਂਡ ਹੋਣ \'ਤੇ ਹੀ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੀ ਟੈਬਲੈੱਟ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ, ਪਰ ਸਿਰਫ਼ ਐਪ ਦੇ ਫੋਰਗ੍ਰਾਊਂਡ ਹੋਣ \'ਤੇ ਹੀ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਟੀਵੀ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ, ਪਰ ਸਿਰਫ਼ ਐਪ ਦੇ ਫੋਰਗ੍ਰਾਊਂਡ ਹੋਣ \'ਤੇ ਹੀ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ਐਪ ਨੂੰ ਵਧੀਕ ਤੌਰ \'ਤੇ ਅਨੁਮਾਨਿਤ ਜਾਂ ਸਟੀਕ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਦੇਣ \'ਤੇ ਇਹ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਣ ਵੇਲੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ਆਪਣੀਆਂ ਆਡੀਓ ਸੈਟਿੰਗਾਂ ਬਦਲੋ"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS ਬੇਨਤੀ ਨੂੰ USSD ਬੇਨਤੀ ਵਿੱਚ ਬਦਲਿਆ ਗਿਆ"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"ਨਵੀਂ SS ਬੇਨਤੀ ਵਿੱਚ ਬਦਲਿਆ ਗਿਆ"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"ਵਿਸਤਾਰ ਕਰੋ"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"ਸੁੰਗੇੜੋ"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"ਟੌਗਲ ਵਿਸਤਾਰ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 7ef4907..f36edf4 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -138,6 +138,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g>, Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Połączenia przez Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g>, VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Wył."</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Preferuj Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferowane komórkowe"</string>
@@ -423,10 +431,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Pozwala aplikacji na dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji. Aplikacje z tym uprawnieniem mogą wpływać na działanie GPS-a lub innych źródeł lokalizacji."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"dostęp do dokładnej lokalizacji tylko na pierwszym planie"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Ta aplikacja może określić Twoją dokładną lokalizację tylko wtedy, gdy działa na pierwszym planie. Te usługi lokalizacyjne muszą być włączone i dostępne na telefonie, by aplikacja mogła z nich korzystać. Może to zwiększyć zużycie baterii."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"dostęp do przybliżonej lokalizacji (na podstawie sieci)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych, takich jak stacje bazowe i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne na tablecie, by aplikacja mogła z nich korzystać."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych, takich jak stacje bazowe i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne na telewizorze, by aplikacja mogła z nich korzystać."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych, takich jak stacje bazowe i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne na telefonie, by aplikacja mogła z nich korzystać."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"dostęp do przybliżonej lokalizacji (na podstawie sieci) tylko na pierwszym planie"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych takich jak stacje bazowe i sieci Wi-Fi, ale tylko wtedy, gdy działa na pierwszym planie. Wymienione usługi lokalizacyjne muszą być włączone i dostępne na tablecie, by aplikacja mogła z nich korzystać."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych takich jak stacje bazowe i sieci Wi-Fi, ale tylko wtedy, gdy działa na pierwszym planie. Wymienione usługi lokalizacyjne muszą być włączone i dostępne na telewizorze, by aplikacja mogła z nich korzystać."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych takich jak stacje bazowe i sieci Wi-Fi, ale tylko wtedy, gdy działa na pierwszym planie. Wymienione usługi lokalizacyjne muszą być włączone i dostępne na telefonie, by aplikacja mogła z nich korzystać."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"dostęp do lokalizacji w tle"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Jeśli te uprawnienia zostaną przyznane wraz z dostępem do dokładnej lub przybliżonej lokalizacji, aplikacja będzie mogła uzyskiwać dostęp do lokalizacji podczas działania w tle."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"zmienianie ustawień audio"</string>
@@ -650,7 +658,7 @@
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Pozwala aplikacji na odczyt i zmianę konfiguracji trybu Nie przeszkadzać."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrolowanie długości haseł blokady ekranu i kodów PIN oraz dozwolonych w nich znaków."</string>
-    <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitoruj próby odblokowania ekranu"</string>
+    <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitorowanie prób odblokowania ekranu"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Przy odblokowywaniu ekranu monitoruj, ile razy wpisano nieprawidłowe hasło i blokuj tablet lub usuń z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy."</string>
     <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Monitorowanie, ile razy wpisano niepoprawne hasło podczas odblokowywania ekranu, oraz blokowanie telewizora albo kasowanie na nim wszystkich danych, gdy zbyt wiele razy wpisano niepoprawne hasło."</string>
     <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Przy odblokowywaniu ekranu monitoruje, ile razy wpisano nieprawidłowe hasło, i blokuje telefon lub usuwa z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy"</string>
@@ -671,11 +679,11 @@
     <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"Kasowanie danych tego użytkownika na tym telefonie bez ostrzeżenia."</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Ustaw globalny serwer proxy urządzenia"</string>
     <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Ustawianie globalnego serwera proxy urządzenia do użycia przy włączonych zasadach. Tylko właściciel urządzenia może ustawić globalny serwer proxy."</string>
-    <string name="policylab_expirePassword" msgid="5610055012328825874">"Ustaw czas ważności hasła blokady ekranu"</string>
+    <string name="policylab_expirePassword" msgid="5610055012328825874">"Ustawianie czasu ważności hasła blokady ekranu"</string>
     <string name="policydesc_expirePassword" msgid="5367525762204416046">"Zmiana częstotliwości, z jaką należy zmieniać hasło blokady ekranu, kod PIN lub wzór."</string>
-    <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ustaw szyfrowanie pamięci"</string>
+    <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Ustawianie szyfrowania pamięci"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Wymaganie szyfrowania przechowywanych danych aplikacji"</string>
-    <string name="policylab_disableCamera" msgid="6395301023152297826">"Wyłącz aparaty"</string>
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Wyłączanie aparatów"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Zapobieganie używaniu wszystkich aparatów w urządzeniu"</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Wył. funkcji blokady ekranu"</string>
     <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Zapobieganie użyciu niektórych funkcji blokady ekranu."</string>
@@ -1891,6 +1899,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Żądanie SS zmienione na żądanie USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Zmieniono na nowe żądanie SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Profil służbowy"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Rozwiń"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Zwiń"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"przełącz rozwijanie"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 5ab4fce..05bb1ed 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi de <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Chamada no Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi de <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Desativado"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi preferido"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferência pela rede móvel"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite que o app acesse comandos do provedor não relacionados à localização. Isso pode permitir que o app interfira no funcionamento do GPS ou de outras fontes de localização."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"acessar localização precisa apenas em primeiro plano"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Este app pode ver sua localização exata a qualquer momento apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los. Isso pode aumentar o consumo de bateria."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"acessar localização aproximada (com base na rede)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Este app pode ver seu local com base nas fontes de rede, como torres de celular e redes Wi-Fi. Esses serviços de localização precisam estar ativados e disponíveis no seu tablet para que o app possa usá-los."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Este app pode ver seu local com base nas fontes de rede, como torres de celular e redes Wi-Fi. Esses serviços de localização precisam estar ativados e disponíveis na sua TV para que o app possa usá-los."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Este app pode ver seu local com base nas fontes de rede, como torres de celular e redes Wi-Fi. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"acessar localização aproximada (baseada em rede) apenas em primeiro plano"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Esse app pode acessar sua localização com base em fontes de rede, como torres de celular e redes Wi-Fi, mas apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu tablet para que o app possa usá-los."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Esse app pode acessar sua localização com base em fontes de rede, como torres de celular e redes Wi-Fi, mas apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis na sua TV para que o app possa usá-los."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Esse app pode acessar sua localização com base em fontes de rede, como torres de celular e redes Wi-Fi, mas apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"acessar a localização em segundo plano"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Se essa permissão for concedida, além do acesso à localização precisa ou aproximada, o app poderá acessar a localização durante a execução em segundo plano."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"alterar as suas configurações de áudio"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Solicitação SS alterada para solicitação USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Alterada para uma nova solicitação SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Perfil de trabalho"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Expandir"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Recolher"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"alternar expansão"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index ec853bb..abb0023 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Chamadas Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Desativado"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Rede Wi-Fi preferida"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferência pela rede móvel"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite que a aplicação aceda a comandos adicionais do fornecedor de localização. Esta opção pode permitir que a aplicação interfira com o funcionamento do GPS ou de outras fontes de localização."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"apenas aceder à localização exata em primeiro plano"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Esta aplicação apenas pode obter a sua localização exata quando estiver em primeiro plano. É necessário que estes Serviços de localização estejam ativados e disponíveis no seu telemóvel para que a aplicação os possa utilizar. Esta ação pode aumentar o consumo da bateria."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"aceder à localização aproximada (baseada na rede)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Esta aplicação pode obter a sua localização com base em fontes de rede, tais como torres de redes móveis e redes Wi-Fi. É necessário que estes serviços de localização estejam ativados e disponíveis no seu tablet para que a aplicação os possa utilizar."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Esta aplicação pode obter a sua localização com base em fontes de rede, tais como torres de redes móveis e redes Wi-Fi. É necessário que estes serviços de localização estejam ativados e disponíveis na sua TV para que a aplicação os possa utilizar."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Esta aplicação pode obter a sua localização com base em fontes de rede, tais como torres de redes móveis e redes Wi-Fi. É necessário que estes serviços de localização estejam ativados e disponíveis no seu telemóvel para que a aplicação os possa utilizar."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"aceder à localização aproximada (baseada na rede) apenas em primeiro plano"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Esta aplicação pode obter a sua localização com base em fontes de rede, tais como torres de redes móveis e redes Wi-Fi, mas apenas quando estiver em primeiro plano. É necessário que estes Serviços de localização estejam ativados e disponíveis no seu tablet para que a aplicação os possa utilizar."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Esta aplicação pode obter a sua localização com base em fontes de rede, tais como torres de redes móveis e redes Wi-Fi, mas apenas quando estiver em primeiro plano. É necessário que estes Serviços de localização estejam ativados e disponíveis na sua TV para que a aplicação os possa utilizar."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Esta aplicação pode obter a sua localização com base em fontes de rede, tais como torres de redes móveis e redes Wi-Fi, mas apenas quando estiver em primeiro plano. É necessário que estes Serviços de localização estejam ativados e disponíveis no seu telemóvel para que a aplicação os possa utilizar."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"aceder à localização em segundo plano"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Se tal for concedido em conjunto com o acesso à localização aproximada ou exata, a aplicação pode aceder à localização mesmo estando em segundo plano."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"alterar as suas definições de áudio"</string>
@@ -1341,7 +1349,7 @@
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"Sobrepor a outras aplicações"</string>
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"A aplicação <xliff:g id="NAME">%s</xliff:g> sobrepõe-se a outras aplicações"</string>
-    <string name="alert_windows_notification_title" msgid="3697657294867638947">"O <xliff:g id="NAME">%s</xliff:g> sobrepõe-se a outras aplic."</string>
+    <string name="alert_windows_notification_title" msgid="3697657294867638947">"O <xliff:g id="NAME">%s</xliff:g> sobrepõe-se a outras app"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Se não pretende que a aplicação <xliff:g id="NAME">%s</xliff:g> utilize esta funcionalidade, toque para abrir as definições e desative-a."</string>
     <string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Desligar"</string>
     <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"A verificar o <xliff:g id="NAME">%s</xliff:g>…"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"O pedido SS foi alterado para um novo pedido USSD."</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Foi alterado para um novo pedido SS."</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Perfil de trabalho"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Expandir"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Reduzir"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"ativar/desativar expansão"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 5ab4fce..05bb1ed 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi de <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Chamada no Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi de <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Desativado"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi preferido"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferência pela rede móvel"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite que o app acesse comandos do provedor não relacionados à localização. Isso pode permitir que o app interfira no funcionamento do GPS ou de outras fontes de localização."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"acessar localização precisa apenas em primeiro plano"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Este app pode ver sua localização exata a qualquer momento apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los. Isso pode aumentar o consumo de bateria."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"acessar localização aproximada (com base na rede)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Este app pode ver seu local com base nas fontes de rede, como torres de celular e redes Wi-Fi. Esses serviços de localização precisam estar ativados e disponíveis no seu tablet para que o app possa usá-los."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Este app pode ver seu local com base nas fontes de rede, como torres de celular e redes Wi-Fi. Esses serviços de localização precisam estar ativados e disponíveis na sua TV para que o app possa usá-los."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Este app pode ver seu local com base nas fontes de rede, como torres de celular e redes Wi-Fi. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"acessar localização aproximada (baseada em rede) apenas em primeiro plano"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Esse app pode acessar sua localização com base em fontes de rede, como torres de celular e redes Wi-Fi, mas apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu tablet para que o app possa usá-los."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Esse app pode acessar sua localização com base em fontes de rede, como torres de celular e redes Wi-Fi, mas apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis na sua TV para que o app possa usá-los."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Esse app pode acessar sua localização com base em fontes de rede, como torres de celular e redes Wi-Fi, mas apenas quando está em primeiro plano. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"acessar a localização em segundo plano"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Se essa permissão for concedida, além do acesso à localização precisa ou aproximada, o app poderá acessar a localização durante a execução em segundo plano."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"alterar as suas configurações de áudio"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Solicitação SS alterada para solicitação USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Alterada para uma nova solicitação SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Perfil de trabalho"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Expandir"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Recolher"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"alternar expansão"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 7c4a571..40812fd 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -137,6 +137,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Apelare prin Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Dezactivată"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Se preferă conexiunea Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Se preferă datele mobile"</string>
@@ -420,10 +428,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite aplicației să acceseze comenzi suplimentare pentru furnizorul locației. Aplicația ar putea să utilizeze această permisiune pentru a influența operațiile GPS sau ale altor surse de locații."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"să acceseze locația exactă în prim-plan"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Aplicația vă poate obține locația exactă numai când rulează în prim-plan. Serviciile de localizare trebuie să fie activate și disponibile pe telefon pentru ca aplicația să le poată folosi. Acest lucru poate accelera descărcarea bateriei."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"să acceseze locația aproximativă (bazată pe rețea)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Această aplicație vă poate obține locația cu ajutorul surselor rețelei, cum ar fi turnurile de telefonie mobilă și rețelele Wi-Fi. Aceste servicii de localizare trebuie să fie activate și disponibile pe tabletă pentru ca aplicația să le poată folosi."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Această aplicație vă poate obține locația cu ajutorul surselor rețelei, cum ar fi turnurile de telefonie mobilă și rețelele Wi-Fi. Aceste servicii de localizare trebuie să fie activate și disponibile pe televizor pentru ca aplicația să le poată folosi."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Această aplicație vă poate obține locația cu ajutorul surselor rețelei, cum ar fi turnurile de telefonie mobilă și rețelele Wi-Fi. Aceste servicii de localizare trebuie să fie activate și disponibile pe telefon pentru ca aplicația să le poată folosi."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"să acceseze locația aproximativă (bazată pe rețea) doar în prim-plan"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Aplicația vă poate determina locația folosind sursele din rețea, cum ar fi turnurile de telefonie mobilă și rețelele Wi-Fi, însă numai când rulează în prim-plan. Aceste servicii de localizare trebuie să fie activate și disponibile pe tabletă pentru ca aplicația să le poată folosi."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Aplicația vă poate determina locația folosind sursele din rețea, cum ar fi turnurile de telefonie mobilă și rețelele Wi-Fi, însă numai când rulează în prim-plan. Aceste servicii de localizare trebuie să fie activate și disponibile pe televizor pentru ca aplicația să le poată folosi."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Aplicația vă poate determina locația folosind sursele din rețea, cum ar fi turnurile de telefonie mobilă și rețelele Wi-Fi, însă numai când rulează în prim-plan. Aceste servicii de localizare trebuie să fie activate și disponibile pe telefon pentru ca aplicația să le poată folosi."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"accesați locația în fundal"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Dacă se acordă în plus față de accesul la locație aproximativă sau exactă, aplicația poate accesa locația în timp ce rulează în fundal."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modificare setări audio"</string>
@@ -1858,6 +1866,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Solicitarea SS a fost schimbată cu o solicitare USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Schimbat cu o solicitare SS nouă"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Profil de serviciu"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Extindeți"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Restrângeți"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"extindeți/restrângeți"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ece22b1..766a68b 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -138,6 +138,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Звонки по Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Отключено"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Приоритет Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Приоритет мобильного Интернета"</string>
@@ -423,10 +431,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Доступ к дополнительным командам управления источниками геоданных и вмешательство в работу системы GPS или других источников геоданных."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"Доступ к точному местоположению только в фоновом режиме"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Приложение может получать сведения о вашем точном местоположении только в фоновом режиме. Для этого необходимо включить соответствующие параметры на телефоне и разрешить использовать геоданные. Может увеличиться расход заряда батареи."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"Доступ к примерному местоположению (по координатам сети)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Приложение может получать сведения о вашем местоположении от сетевых источников, таких как вышки сотовой связи и точки доступа Wi-Fi. Необходимо включить соответствующие параметры на планшете и разрешить приложению использовать геоданные."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Приложение может получать сведения о вашем местоположении от сетевых источников, таких как вышки сотовой связи и точки доступа Wi-Fi. Необходимо включить соответствующие параметры на телевизоре и разрешить приложению использовать геоданные."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Приложение может получать сведения о вашем местоположении от сетевых источников, таких как вышки сотовой связи и точки доступа Wi-Fi. Необходимо включить соответствующие параметры на телефоне и разрешить приложению использовать геоданные."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"Доступ к примерному местоположению (по координатам сети) только в фоновом режиме"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Приложение может получать сведения о вашем местоположении от источников сетей, таких как вышки сотовой связи и точки доступа Wi-Fi, но только в фоновом режиме. Для этого необходимо включить соответствующие параметры на планшете и разрешить использовать геоданные."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Приложение может получать сведения о вашем местоположении от источников сетей, таких как вышки сотовой связи и точки доступа Wi-Fi, но только в фоновом режиме. Для этого необходимо включить соответствующие параметры на телевизоре и разрешить использовать геоданные."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Приложение может получать сведения о вашем местоположении от источников сетей, таких как вышки сотовой связи и точки доступа Wi-Fi, но только в фоновом режиме. Для этого необходимо включить соответствующие параметры на телефоне и разрешить использовать геоданные."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"доступ к геоданным в фоновом режиме"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Если помимо доступа к данным о точном или приблизительном местоположении вы предоставите это разрешение, приложение сможет получать доступ к геоданным в фоновом режиме."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"Изменение настроек аудио"</string>
@@ -1891,6 +1899,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS-запрос преобразован в USSD-запрос"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Преобразовано в SS-запрос"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Рабочий профиль"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Развернуть"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Скрыть"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"Свернуть или развернуть"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index ed3d0f5..bd5b82a 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"WiFi ඇමතුම් | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ක්‍රියාවිරහිතයි"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi වඩා කැමතියි"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"ජංගම කැමතියි"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ස්ථානය සපයන අමතර අණ වලට ප්‍රවේශය කිරීමට යෙදුමට අවසර දෙන්න. GPS ක්‍රියාවන් හෝ වෙනත් ස්ථාන මූලාශ්‍ර සමඟ මැදිහත් වීමට මෙයින් යෙදුමට ඉඩ ලැබේ."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"පෙරබිම තුළ පමණක් නිශ්චිත ස්ථානය වෙත පිවිසෙන්න"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"මෙම යෙදුම පෙරබිම තුළ ඇති විට පමණක් එයට ඔබේ නිශ්චිත ස්ථානය ලබා ගත හැකිය. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර සහ ඔබේ දුරකථනය මත ලබා ගත හැකිව තිබිය යුතුය. මෙය බැටරි පරිභෝජනය වැඩි කළ හැකිය."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ආසන්නතම ස්ථානයට (ජාලය-පාදක වූ) පිවිසීම"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"මෙම යෙදුමට ජංගම දුරකථන කුළුණු සහ Wi-Fi ජාල වැනි ජාල මූලාශ්‍ර පදනම්ව ඔබගේ ස්ථානය ලබා ගත හැකිය. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර සහ ඔබේ ටැබ්ලට් පරිගණකය මත ලබා ගත හැකිව තිබිය යුතුය."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"මෙම යෙදුමට ජංගම දුරකථන කුළුණු සහ Wi-Fi ජාල වැනි ජාල මූලාශ්‍ර පදනම්ව ඔබගේ ස්ථානය ලබා ගත හැකිය. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර සහ ඔබේ TV මත ලබා ගත හැකිව තිබිය යුතුය."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"මෙම යෙදුමට ජංගම දුරකථන කුළුණු සහ Wi-Fi ජාල වැනි ජාල මූලාශ්‍ර පදනම්ව ඔබගේ ස්ථානය ලබා ගත හැකිය. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර සහ ඔබේ දුරකථනය මත ලබා ගත හැකිව තිබිය යුතුය."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"ඉදිරියේ ඇති ආසන්න ස්ථානය (ජාලය පදනම්වූ) පමණක් ප්‍ර වේශ වන්න"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"මෙම යෙදුමට ජංගම දුරකථන කුළුණු සහ Wi-Fi ජාල වැනි ජාල මූලාශ්‍ර පදනම්ව ඔබගේ ස්ථානය ලබා ගත හැකි නමුත් යෙදුම ඉදිරියේ ඇති විට පමණී. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර ඔබේ ටැබ්ලටය මත ලබා ගත හැකිව තිබිය යුතුය."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"මෙම යෙදුමට ජංගම දුරකථන කුළුණු සහ Wi-Fi ජාල වැනි ජාල මූලාශ්‍ර පදනම්ව ඔබගේ ස්ථානය ලබා ගත හැකි නමුත් යෙදුම ඉදිරියේ ඇති විට පමණී. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර ඔබේ TV එක මත ලබා ගත හැකිව තිබිය යුතුය."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"මෙම යෙදුමට ජංගම දුරකථන කුළුණු සහ Wi-Fi ජාල වැනි ජාල මූලාශ්‍ර පදනම්ව ඔබගේ ස්ථානය ලබා ගත හැකි නමුත් යෙදුම ඉදිරියේ ඇති විට පමණී. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර ඔබේ දුරකථනය මත ලබා ගත හැකිව තිබිය යුතුය."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"පසුබිමේ ස්ථානය ප්‍රවේශ කිරීම"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"මෙය ආසන්න වශයෙන් හෝ නිශ්චිත ස්ථානයක ප්‍රවේශය ලබා දෙන්නේ නම් පසුබිම් ධාවන අතරතුරදී යෙදුමට ස්ථානය වෙත ප්‍රවේශය විය හැක."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ඔබගේ ශ්‍රව්‍ය සැකසීම් වෙනස් කරන්න"</string>
@@ -1827,6 +1835,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS ඉල්ලීම USSD ඉල්ලීමට වෙනස් කරන ලදී"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"නව SS ඉල්ලීමට වෙනස් කරන ලදී"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"කාර්යාල පැතිකඩ"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"දිග හරින්න"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"හකුළන්න"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"පුළුල් කිරීම ටොගල කරන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 525fcde..ea45c9d 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -72,7 +72,7 @@
     <string name="ThreeWCMmi" msgid="9051047170321190368">"Konferencia troch účastníkov"</string>
     <string name="RuacMmi" msgid="7827887459138308886">"Odmietnutie nevyžiadaných obťažujúcich hovorov"</string>
     <string name="CndMmi" msgid="3116446237081575808">"Doručenie volaného čísla"</string>
-    <string name="DndMmi" msgid="1265478932418334331">"Nerušiť"</string>
+    <string name="DndMmi" msgid="1265478932418334331">"Režim bez vyrušení"</string>
     <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"V predvolenom nastavení je identifikácia volajúceho obmedzená. Ďalší hovor: Obmedzené"</string>
     <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"V predvolenom nastavení je identifikácia volajúceho obmedzená. Ďalší hovor: Bez obmedzenia"</string>
     <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"V predvolenom nastavení nie je identifikácia volajúceho obmedzená. Ďalší hovor: Obmedzené"</string>
@@ -138,6 +138,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Volanie cez WiFi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Vypnuté"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Preferovať Wi‑Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferovať mobilné spojenie"</string>
@@ -423,10 +431,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Umožňuje aplikácii pristupovať k ďalším príkazom poskytovateľa informácií o polohe. Aplikácii to môže umožniť zasahovať do činnosti systému GPS alebo iných zdrojov informácií o polohe."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"prístup k presnej polohe iba v popredí"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Táto aplikácia dokáže získať vašu presnú polohu iba vtedy, keď je spustená v popredí. Na to, aby mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii v telefóne. Môže to zvýšiť spotebu batérie."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"prístup k približnej polohe (pomocou siete)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Táto aplikácia môže získať údaje o vašej polohe na základe sieťových zdrojov, ako sú mobilné veže a siete Wi‑Fi. Na to, aby aplikácia mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii na tablete."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Táto aplikácia môže získať údaje o vašej polohe na základe sieťových zdrojov, ako sú mobilné veže a siete Wi‑Fi. Na to, aby aplikácia mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii na televízore."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Táto aplikácia môže získať údaje o vašej polohe na základe sieťových zdrojov, ako sú mobilné veže a siete Wi‑Fi. Na to, aby aplikácia mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii na telefóne."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"prístup k približnej polohe (pomocou siete) iba v popredí"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Táto aplikácia môže získať údaje o vašej polohe na základe sieťových zdrojov, ako sú mobilné veže a siete Wi‑Fi, keď je spustená v popredí. Na to, aby aplikácia mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii v tablete."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Táto aplikácia môže získať údaje o vašej polohe na základe sieťových zdrojov, ako sú mobilné veže a siete Wi‑Fi, keď je spustená v popredí. Na to, aby aplikácia mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii v televízore."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Táto aplikácia môže získať údaje o vašej polohe na základe sieťových zdrojov, ako sú mobilné veže a siete Wi‑Fi, ale iba keď je spustená v popredí. Na to, aby aplikácia mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii v telefóne."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"prístup k polohe na pozadí"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ak okrem prístupu k približnej alebo presnej polohe udelíte aj toto povolenie, aplikácia bude môcť používať polohu, keď bude spustená na pozadí."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"meniť nastavenia zvuku"</string>
@@ -646,8 +654,8 @@
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby na odosielanie správ SMS a MMS operátora. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"naviazať sa na služby operátora"</string>
     <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"Umožňuje držiteľovi povolenia naviazať sa na služby operátora. Bežné aplikácie by toto povolenie nemali nikdy nepotrebovať."</string>
-    <string name="permlab_access_notification_policy" msgid="4247510821662059671">"prístup k nastaveniu Nerušiť"</string>
-    <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Umožňuje aplikácii čítať a zapisovať konfiguráciu nastavenia Nerušiť."</string>
+    <string name="permlab_access_notification_policy" msgid="4247510821662059671">"prístup k režimu bez vyrušení"</string>
+    <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Umožňuje aplikácii čítať a zapisovať konfiguráciu režimu bez vyrušení."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Nastavte dĺžku hesiel na odomknutie obrazovky aj kódov PIN a v nich používané znaky."</string>
     <string name="policylab_watchLogin" msgid="5091404125971980158">"Sledovanie pokusov o odomknutie obrazovky"</string>
@@ -1870,10 +1878,10 @@
     <string name="zen_mode_until" msgid="7336308492289875088">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_alarm" msgid="9128205721301330797">"Do <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (ďalší budík)"</string>
     <string name="zen_mode_forever" msgid="931849471004038757">"Dokiaľ túto funkciu nevypnete"</string>
-    <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dokiaľ nevypnete režim Nerušiť"</string>
+    <string name="zen_mode_forever_dnd" msgid="3792132696572189081">"Dokiaľ nevypnete režim bez vyrušení"</string>
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g> / <xliff:g id="REST">%2$s</xliff:g>"</string>
     <string name="toolbar_collapse_description" msgid="2821479483960330739">"Zbaliť"</string>
-    <string name="zen_mode_feature_name" msgid="5254089399895895004">"Nerušiť"</string>
+    <string name="zen_mode_feature_name" msgid="5254089399895895004">"Režim bez vyrušení"</string>
     <string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"Doba pokoja"</string>
     <string name="zen_mode_default_weeknights_name" msgid="3081318299464998143">"Noc pracovného dňa"</string>
     <string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"Víkend"</string>
@@ -1891,6 +1899,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Žiadosť SS bola zmenená na žiadosť USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Zmenené na novú žiadosť SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Pracovný profil"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Rozbaliť"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Zbaliť"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"prepnúť rozbalenie"</string>
@@ -2018,10 +2028,10 @@
     <string name="volume_dialog_ringer_guidance_vibrate" msgid="8902050240801159042">"Hovory a upozornenia budú vibrovať"</string>
     <string name="volume_dialog_ringer_guidance_silent" msgid="2128975224280276122">"Hovory a upozornenia budú stlmené"</string>
     <string name="notification_channel_system_changes" msgid="5072715579030948646">"Zmeny systému"</string>
-    <string name="notification_channel_do_not_disturb" msgid="6766940333105743037">"Nerušiť"</string>
-    <string name="zen_upgrade_notification_visd_title" msgid="3288313883409759733">"Novinka: režim Nerušiť skrýva upozornenia"</string>
+    <string name="notification_channel_do_not_disturb" msgid="6766940333105743037">"Režim bez vyrušení"</string>
+    <string name="zen_upgrade_notification_visd_title" msgid="3288313883409759733">"Novinka: režim bez vyrušení skrýva upozornenia"</string>
     <string name="zen_upgrade_notification_visd_content" msgid="5533674060311631165">"Klepnutím získate ďalšie informácie a budete môcť vykonať zmeny."</string>
-    <string name="zen_upgrade_notification_title" msgid="3799603322910377294">"Nastavenie Nerušiť sa zmenilo"</string>
+    <string name="zen_upgrade_notification_title" msgid="3799603322910377294">"Režim bez vyrušení sa zmenil"</string>
     <string name="zen_upgrade_notification_content" msgid="1794994264692424562">"Klepnutím skontrolujete, čo je blokované."</string>
     <string name="notification_app_name_system" msgid="4205032194610042794">"Systém"</string>
     <string name="notification_app_name_settings" msgid="7751445616365753381">"Nastavenia"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 252246a..4a41228 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -138,6 +138,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi operaterja <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Klicanje prek WiFi-ja | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"Govor prek Wi-Fi-ja operaterja <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Izklopljeno"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Prednostno Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Prednostno mobilno"</string>
@@ -423,10 +431,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Aplikaciji omogoča dostop do dodatnih ukazov ponudnika lokacij. S tem lahko aplikacija moti delovanje sistema GPS ali drugih virov lokacije."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"dostop do točne lokacije samo, ko deluje v ospredju"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Ta aplikacija lahko pridobi vašo točno lokacijo samo, ko deluje v ospredju. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v telefonu. Poraba energije akumulatorja bo morda večja."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"dostop do približne lokacije (na podlagi podatkov omrežja)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ta aplikacija lahko pridobi vašo lokacijo na podlagi omrežnih virov, kot so bazne postaje in omrežja Wi-Fi. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v tabličnem računalniku."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ta aplikacija lahko pridobi vašo lokacijo na podlagi omrežnih virov, kot so bazne postaje in omrežja Wi-Fi. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v televizorju."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ta aplikacija lahko pridobi vašo lokacijo na podlagi omrežnih virov, kot so bazne postaje in omrežja Wi-Fi. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v telefonu."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"dostop do približne lokacije (na podlagi omrežja) samo med delovanjem v ospredju"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Ta aplikacija lahko pridobi vašo lokacijo na podlagi omrežnih virov, kot so bazne postaje in omrežja Wi-Fi, vendar samo, ko deluje v ospredju. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v tabličnem računalniku."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Ta aplikacija lahko pridobi vašo lokacijo na podlagi omrežnih virov, kot so bazne postaje in omrežja Wi-Fi, vendar samo, ko deluje v ospredju. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v televizorju."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Ta aplikacija lahko pridobi vašo lokacijo na podlagi omrežnih virov, kot so bazne postaje in omrežja Wi-Fi, vendar samo, ko deluje v ospredju. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v telefonu."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"dostop do lokacije med izvajanjem v ozadju"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Če to dovolite poleg dostopa do približne ali natančne lokacije, lahko aplikacija dostopa do lokacije, medtem ko se izvaja v ozadju."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"spreminjanje nastavitev zvoka"</string>
@@ -1891,6 +1899,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Zahteva SS je spremenjena v zahtevo USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Spremenjeno v novo zahtevo SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Delovni profil"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Razširi"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Strni"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"preklop razširitve"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 9062f29..fc88556 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi në <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Telefonatë me Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi në <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Çaktivizuar"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Preferohet Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Preferohet rrjeti celular"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Lejon aplikacionin të ketë qasje në komandat shtesë të ofruesit për vendndodhjen. Kjo mund ta lejojë aplikacionin të ndërhyjë në operacionin e GPS-së apo të burimeve të tjera për vendndodhjen."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"qasu në vendndodhjen e saktë vetëm në plan të parë"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Ky aplikacion mund të marrë vendndodhjen tënde të saktë në çdo kohë kur është në plan të parë. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe në dispozicion në telefonin tënd që aplikacioni të mund t\'i përdorë. Kjo gjë mund të rritë konsumin e baterisë."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"qasu te vendndodhja e përafërt (bazuar në rrjet)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ky aplikacion mund të marrë vendndodhjen tënde bazuar në burimet e rrjetit si antenat e operatorëve celulare dhe rrjetet Wi-Fi. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe në dispozicion në tabletin tënd që aplikacioni të mund t\'i përdorë."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ky aplikacion mund të marrë vendndodhjen tënde bazuar në burimet e rrjetit si antenat e operatorëve celulare dhe rrjetet Wi-Fi. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe në dispozicion në televizorin tënd që aplikacioni të mund t\'i përdorë."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ky aplikacion mund të marrë vendndodhjen tënde bazuar në burimet e rrjetit si antenat e operatorëve celulare dhe rrjetet Wi-Fi. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe në dispozicion në telefonin tënd që aplikacioni të mund t\'i përdorë."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"qasu te vendndodhja e përafërt (bazuar te rrjeti) vetëm në plan të parë"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Ky aplikacion mund të marrë vendndodhjen tënde bazuar në burimet e rrjetit si antenat e operatorëve celulare dhe rrjetet Wi-Fi, por vetëm kur aplikacioni është në plan të parë. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe të ofrohen në tabletin tënd që aplikacioni të mund t\'i përdorë."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Ky aplikacion mund të marrë vendndodhjen tënde bazuar në burimet e rrjetit si antenat e operatorëve celulare dhe rrjetet Wi-Fi, por vetëm kur aplikacioni është në plan të parë. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe të ofrohen në televizorin tënd që aplikacioni të mund t\'i përdorë."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Ky aplikacion mund të marrë vendndodhjen tënde bazuar në burimet e rrjetit si antenat e operatorëve celulare dhe rrjetet Wi-Fi, por vetëm kur aplikacioni është në plan të parë. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe të ofrohen në telefonin tënd që aplikacioni të mund t\'i përdorë."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"qasje te vendndodhja në sfond"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Nëse kjo jepet përveç qasjes te vendndodhja e përafërt ose të saktë, aplikacioni mund të qaset te vendndodhja ndërkohë që ekzekutohet në sfond."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ndrysho cilësimet e audios"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Kërkesa SS u ndryshua në kërkesë USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"U ndryshua në kërkesë të re SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Profili i punës"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Zgjero"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Palos"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"aktivizo zgjerimin"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 642e12e..b2e3059 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -137,6 +137,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Позивање преко Wi-Fi-ја | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Искључено"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Предност има Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Желим мобилне податке"</string>
@@ -213,7 +221,7 @@
     <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Сат ће се угасити."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Телефон ће се искључити."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Да ли желите да искључите телефон?"</string>
-    <string name="reboot_safemode_title" msgid="7054509914500140361">"Поново покрени систем у безбедном режиму"</string>
+    <string name="reboot_safemode_title" msgid="7054509914500140361">"Рестартуј систем у безбедном режиму"</string>
     <string name="reboot_safemode_confirm" msgid="55293944502784668">"Да ли желите да поново покренете систем у безбедном режиму? Ово ће онемогућити све инсталиране апликације независних произвођача. Оне ће бити враћене када поново покренете систем."</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"Недавно"</string>
     <string name="no_recent_tasks" msgid="8794906658732193473">"Нема недавних апликација."</string>
@@ -420,10 +428,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Омогућава апликацији да приступа додатним командама даваоца услуга локације. То може да омогући апликацији да утиче на рад GPS-а или других извора локације."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"приступ прецизној локацији само у првом плану"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Ова апликација може да одреди вашу тачну локацију само када ради у првом плану. Ове услуге локације морају да буду укључене и доступне на телефону да би апликација могла да их користи. То може да повећа потрошњу батерије."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"приступ приближној локацији (утврђена преко мреже)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ова апликација може да приступи вашој локацији помоћу извора мреже, као што су мобилни предајници и Wi-Fi мреже. Ове услуге локације морају да буду укључене и доступне на таблету да би апликација могла да их користи."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ова апликација може да приступи вашој локацији помоћу извора мреже, као што су мобилни предајници и Wi-Fi мреже. Ове услуге локације морају да буду укључене и доступне на ТВ-у да би апликација могла да их користи."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ова апликација може да приступи вашој локацији помоћу извора мреже, као што су мобилни предајници и Wi-Fi мреже. Ове услуге локације морају да буду укључене и доступне на телефону да би апликација могла да их користи."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"приступ приближној локацији (утврђеној преко мреже) само у првом плану"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Ова апликација може да приступи вашој локацији помоћу извора мреже, као што су мобилни предајници и Wi-Fi мреже, али само када апликација ради у првом плану. Ове услуге локације морају да буду укључене и доступне на таблету да би апликација могла да их користи"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Ова апликација може да приступи вашој локацији помоћу извора мреже, као што су мобилни предајници и Wi-Fi мреже, али само када апликација ради у првом плану. Ове услуге локације морају да буду укључене и доступне на телевизору да би апликација могла да их користи."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Ова апликација може да приступи вашој локацији помоћу извора мреже, као што су мобилни предајници и Wi-Fi мреже, али само када апликација ради у првом плану. Ове услуге локације морају да буду укључене и доступне на телефону да би апликација могла да их користи."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"приступ локацији у позадини"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ако се поред приближног или прецизног приступа локација одобри и овај, апликација може да приступа локацији док је покренута у позадини."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"промена аудио подешавања"</string>
@@ -507,11 +515,11 @@
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"онемогућавање закључавања екрана"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Дозвољава апликацији да онемогући закључавање тастатуре и све повезане безбедносне мере са лозинкама. На пример, телефон онемогућава закључавање тастатуре при пријему долазног телефонског позива, а затим га поново омогућава по завршетку позива."</string>
     <string name="permlab_useBiometric" msgid="8837753668509919318">"користи биометријски хардвер"</string>
-    <string name="permdesc_useBiometric" msgid="8389855232721612926">"Дозвољава апликацији да користи биометријски хардвер за потврду аутентичности"</string>
+    <string name="permdesc_useBiometric" msgid="8389855232721612926">"Дозвољава апликацији да користи биометријски хардвер за потврду идентитета"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"управљај хардвером за отиске прстију"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Дозвољава апликацији да активира методе за додавање и брисање шаблона отисака прстију који ће се користити."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"користи хардвер за отиске прстију"</string>
-    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозвољава апликацији да користи хардвер за отиске прстију ради потврде аутентичности"</string>
+    <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозвољава апликацији да користи хардвер за отиске прстију ради потврде идентитета"</string>
     <string name="permlab_audioRead" msgid="6617225220728465565">"читање музичке колекције"</string>
     <string name="permdesc_audioRead" msgid="5034032570243484805">"Дозвољава апликацији да чита музичку колекцију."</string>
     <string name="permlab_audioWrite" msgid="2661772059799779292">"измена музичке колекције"</string>
@@ -898,7 +906,7 @@
     <string name="factorytest_failed" msgid="5410270329114212041">"Фабричко тестирање није успело"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Радња FACTORY_TEST је подржана само за пакете инсталиране у директоријуму /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Није пронађен ниједан пакет који обезбеђује радњу FACTORY_TEST."</string>
-    <string name="factorytest_reboot" msgid="6320168203050791643">"Поново покрени"</string>
+    <string name="factorytest_reboot" msgid="6320168203050791643">"Рестартуј"</string>
     <string name="js_dialog_title" msgid="1987483977834603872">"На страници на адреси „<xliff:g id="TITLE">%s</xliff:g>“ пише:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"Потврда навигације"</string>
@@ -1318,7 +1326,7 @@
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"SIM картица је додата"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"Рестартујте уређај да бисте могли да приступите мобилној мрежи."</string>
-    <string name="sim_restart_button" msgid="4722407842815232347">"Поново покрени"</string>
+    <string name="sim_restart_button" msgid="4722407842815232347">"Рестартуј"</string>
     <string name="install_carrier_app_notification_title" msgid="9056007111024059888">"Активирајте мобилну услугу"</string>
     <string name="install_carrier_app_notification_text" msgid="3346681446158696001">"Преузмите апликацију мобилног оператера да бисте активирали нови SIM"</string>
     <string name="install_carrier_app_notification_text_app_name" msgid="1196505084835248137">"Преузмите апликацију <xliff:g id="APP_NAME">%1$s</xliff:g> да бисте активирали нову SIM картицу"</string>
@@ -1858,6 +1866,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS захтев је промењен у USSD захтев"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Промењено је у нови SS захтев"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Профил за Work"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Прошири"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Скупи"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"укључите/искључите проширење"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 2ace15c..dbe9b69 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi via <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi-samtal | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi via <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Av"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi i första hand"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Använd mobildata"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Tillåter att appen får åtkomst till extra kommandon för platsleverantör. Detta kan innebära att appen tillåts störa funktionen för GPS eller andra platskällor."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"endast åtkomst till exakt plats i förgrunden"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Den här appen kan endast få information om din exakta plats när den körs i förgrunden. Platstjänsterna måste ha aktiverats och finnas på mobilen om appen ska kunna använda dem. Detta kan leda till ökad batteriförbrukning."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"få åtkomst till din ungefärliga position (nätverksbaserad)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Appen kan få information om din plats från källor i nätverket, som mobilmaster och Wi-Fi-nätverk. De platstjänsterna måste ha aktiverats och finnas på surfplattan om appen ska kunna använda dem."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Appen kan få information om din plats från källor i nätverket, som mobilmaster och Wi-Fi-nätverk. De platstjänsterna måste ha aktiverats och fungera på TV:n om appen ska kunna använda dem."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Appen kan få information om din plats från källor i nätverket, som mobilmaster och Wi-Fi-nätverk. De platstjänsterna måste ha aktiverats och finnas på mobilen om appen ska kunna använda dem."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"endast åtkomst till beräknad plats (nätverksbaserad) i förgrunden"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Appen kan endast få information om din plats från källor i nätverket, som mobilmaster och Wi-Fi-nätverk, när den körs i förgrunden. Platstjänsterna måste ha aktiverats och finnas på surfplattan om appen ska kunna använda dem."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Appen kan endast få information om din plats från källor i nätverket, som mobilmaster och Wi-Fi-nätverk, när den körs i förgrunden. Platstjänsterna måste ha aktiverats och finnas på tv:n om appen ska kunna använda dem."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Appen kan endast få information om din plats från källor i nätverket, som mobilmaster och Wi-Fi-nätverk, när den körs i förgrunden. Platstjänsterna måste ha aktiverats och finnas på mobilen om appen ska kunna använda dem."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"få åtkomst till platsinformation i bakgrunden"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Om denna behörighet ges utöver ungefärlig eller exakt platsåtkomst får appen åtkomst till platsinformation när den körs i bakgrunden."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ändra dina ljudinställningar"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS-begäran har ändrats till en USSD-begäran"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Har ändrats till ny SS-begäran"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Jobbprofil"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Utöka"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Komprimera"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"Utöka/komprimera"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index dcfa08d..46434cb 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi ya <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Kupiga Simu kupitia WiFi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi ya <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Imezimwa"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi inapedelewa"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mtandao wa simu unapendelewa"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Ruhusu programu kufikia amri za ziada za mtoa huduma za mahali. Hii huenda ikaruhusu programu ikatize matumizi ya GPS au vyanzo vingine vya eneo."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"kufikia mahali mahususi ikiwa tu programu imefunguliwa kwenye skrini"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Programu hii inaweza kupata mahali halisi ikiwa tu umeifungua kwenye skrini. Ni lazima uwashe huduma hizi za mahali na zipatikane kwenye simu yako ili programu iweze kuzitumia. Hatua hii inaweza kuongeza utumiaji wa betri."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"fikia mahali karibu na hapo (inategemea mtandao)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Programu hii inaweza kupata eneo lako kulingana na vyanzo vya mtandao kama vile minara ya simu na mitandao ya Wi-Fi. Huduma hizi za mahali lazima ziwashwe na zipatikane kwenye kompyuta yako kibao ili programu iweze kuzitumia."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Programu hii inaweza kupata eneo lako kulingana na vyanzo vya mtandao kama vile minara ya simu na mitandao ya Wi-Fi. Huduma hizi za mahali lazima ziwashwe na zipatikane kwenye runinga yako ili programu iweze kuzitumia."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Programu hii inaweza kupata eneo lako kulingana na vyanzo vya mtandao kama vile minara ya simu na mitandao ya Wi-Fi. Huduma hizi za mahali lazima ziwashwe na zipatikane kwenye simu yako ili programu iweze kuzitumia."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"fikia eneo linalokadiriwa (kulingana na mtandao) wakati tu programu inatumika kwenye skrini"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Programu hii inaweza kupata eneo lako kulingana na vyanzo vya mtandao kama vile minara ya simu na mitandao ya Wi-Fi, lakini hili hufanyika tu wakati programu inatumika kwenye skrini. Ni lazima uwashe huduma hizi za mahali na zipatikane kwenye simu kibao yako ili programu iweze kuzitumia."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Programu hii inaweza kupata eneo lako kulingana na vyanzo vya mtandao kama vile minara ya simu na mitandao ya Wi-Fi, lakini hili hufanyika tu wakati programu inatumika kwenye skrini. Ni lazima uwashe huduma hizi za mahali na zipatikane kwenye TV yako ili programu iweze kuzitumia."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Programu hii inaweza kupata eneo lako kulingana na vyanzo vya mtandao kama vile minara ya simu na mitandao ya Wi-Fi, lakini hili hufanyika tu wakati programu inatumika kwenye skrini. Ni lazima uwashe huduma hizi za mahali na zipatikane kwenye simu yako ili programu iweze kuzitumia."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ifikie mahali inapotumika chinichini"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Kama ruhusa hii itatolewa, mbali na idhini ya kufikia mahali panapokadiriwa au mahali mahususi, programu inaweza kufikia mahali wakati inatumika chinichini."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"badilisha mipangilio yako ya sauti"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Imebadilisha ombi la SS kuwa ombi la USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Imebadilisha kuwa ombi jipya la SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Wasifu wa kazini"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Panua"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Kunja"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"geuza upanuzi"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 8ed9b7d..d5b8cf8 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> வைஃபை"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"வைஃபை அழைப்பு | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ஆஃப்"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"வைஃபைக்கு முன்னுரிமை"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"மொபைல் தரவிற்கு முன்னுரிமை"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"கூடுதல் இட வழங்குநர் கட்டளைகளை அணுகப் பயன்பாட்டை அனுமதிக்கிறது. இது, GPS அல்லது பிற இருப்பிட மூலங்களின் செயல்பாட்டை இடைமறிக்க பயன்பாட்டை அனுமதிக்கலாம்."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"முன்புலத்தில் இயங்கும்போது மட்டும் துல்லியமான இருப்பிடத்தைக் கண்டறிதல்"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"இந்த ஆப்ஸ் முன்புலத்தில் இயங்கும்போது மட்டுமே நீங்கள் இருக்கும் இடத்தைத் துல்லியமாகக் கண்டறியும். உங்கள் மொபைலில், இருப்பிடச் சேவைகளை ஆப்ஸ் பயன்படுத்துவதற்கு வசதியாக, அவை ஆன் செய்யப்பட்டிருக்க வேண்டும். இதனால் பேட்டரி அதிகம் பயன்படுத்தப்படலாம்."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"தோராயமான இருப்பிடத்தை அணுகுதல் (நெட்வொர்க் அடிப்படையில்)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"இந்தப் பயன்பாடு நெட்வொர்க் மூலங்களின் (செல் கோபுரங்கள், வைஃபை நெட்வொர்க்குகள் போன்றவை) அடிப்படையில் உங்கள் இருப்பிடத்தைப் பெறலாம். பயன்பாடு பயன்படுத்தும் வகையில், உங்கள் டேப்லெட்டில் இந்த இருப்பிடச் சேவைகள் இயக்கப்பட்டு, கிடைக்கும்படி இருக்க வேண்டும்."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"இந்தப் பயன்பாடு நெட்வொர்க் மூலங்களின் (செல் கோபுரங்கள், வைஃபை நெட்வொர்க்குகள் போன்றவை) அடிப்படையில் உங்கள் இருப்பிடத்தைப் பெறலாம். பயன்பாடு பயன்படுத்தும் வகையில், உங்கள் டிவியில் இந்த இருப்பிடச் சேவைகள் இயக்கப்பட்டு, கிடைக்கும்படி இருக்க வேண்டும்."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"இந்தப் பயன்பாடு நெட்வொர்க் மூலங்களின் (செல் கோபுரங்கள், வைஃபை நெட்வொர்க்குகள் போன்றவை) அடிப்படையில் உங்கள் இருப்பிடத்தைப் பெறலாம். பயன்பாடு பயன்படுத்தும் வகையில், உங்கள் மொபைலில் இந்த இருப்பிடச் சேவைகள் இயக்கப்பட்டு, கிடைக்கும்படி இருக்க வேண்டும்."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"முன்புலத்தில் இயங்கும்போது மட்டும் தோராயமான இருப்பிடத்தைக் கண்டறிதல் (நெட்வொர்க் அடிப்படையில்)"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"ஆப்ஸ் முன்புலத்தில் இயங்கும்போது மட்டுமே மொபைல் டவர்கள், வைஃபை நெட்வொர்க்குகள் போன்ற நெட்வொர்க் மூலங்கள் மூலம் ஆப்ஸால் உங்கள் இருப்பிடத்தைப் பெற முடியும். உங்கள் டேப்லெட்டில் \'இருப்பிடச் சேவைகளை\' ஆப்ஸ் பயன்படுத்துவதற்கு வசதியாக அவை ஆன் செய்யப்பட்டிருக்க வேண்டும்."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"ஆப்ஸ் முன்புலத்தில் இயங்கும்போது மட்டுமே மொபைல் டவர்கள், வைஃபை நெட்வொர்க்குகள் போன்ற நெட்வொர்க் மூலங்கள் மூலம் ஆப்ஸால் உங்கள் இருப்பிடத்தைப் பெற முடியும். உங்கள் டிவியில் \'இருப்பிடச் சேவைகளை\' ஆப்ஸ் பயன்படுத்துவதற்கு வசதியாக அவை ஆன் செய்யப்பட்டிருக்க வேண்டும்."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"ஆப்ஸ் முன்புலத்தில் இயங்கும்போது மட்டுமே மொபைல் டவர்கள், வைஃபை நெட்வொர்க்குகள் போன்ற நெட்வொர்க் மூலங்கள் மூலம் ஆப்ஸால் உங்கள் இருப்பிடத்தைப் பெற முடியும். உங்கள் மொபைலில் \'இருப்பிடச் சேவைகளை\' ஆப்ஸ் பயன்படுத்துவதற்கு வசதியாக அவை ஆன் செய்யப்பட்டிருக்க வேண்டும்."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"பின்புலத்தில் இருப்பிடத்தை அணுகுதல்"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"தோராயமான அல்லது துல்லியமான \'இருப்பிட அணுகலுடன்\' சேர்ந்து இதற்கும் அனுமதி வழங்கப்பட்டால், ஆப்ஸ் பின்புலத்தில் இயங்கினாலும் இருப்பிடத்தை அணுக இயலும்."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"எனது ஆடியோ அமைப்புகளை மாற்றுதல்"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS கோரிக்கை, USSD கோரிக்கைக்கு மாற்றப்பட்டது"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"புதிய SS கோரிக்கைக்கு மாற்றப்பட்டது"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"பணி சுயவிவரம்"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"விரிவாக்கும்"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"சுருக்கும்"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"விரிவாக்கத்தை நிலைமாற்றும்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index cce816d..37d4a7b 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"WiFi కాలింగ్ | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ఆఫ్‌లో ఉంది"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fiకి ప్రాధాన్యత"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"మొబైల్‌కి ప్రాధాన్యత ఇవ్వబడింది"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"అదనపు స్థాన ప్రదాత ఆదేశాలను యాక్సెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. ఇది GPS లేదా ఇతర స్థాన మూలాల నిర్వహణలో యాప్‌ ప్రమేయం ఉండేలా అనుమతించవచ్చు."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"స్క్రీన్‌పై ఉన్నప్పుడు మాత్రమే ఖచ్చితమైన స్థానాన్ని యాక్సెస్ చేయండి"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"ఈ యాప్ స్క్రీన్‌పై ఉన్నప్పుడు మాత్రమే అది మీ ఖచ్చితమైన స్థానాన్ని తెలుసుకోగలదు. యాప్‌ ఉపయోగించడానికి మీ ఫోన్‌లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి. ఇది బ్యాటరీ వినియోగాన్ని పెంచవచ్చు."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ఇంచుమించు స్థానాన్ని (నెట్‌వర్క్-ఆధారితం) యాక్సెస్ చేయడం"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ఈ యాప్‌ సెల్ టవర్‌లు మరియు Wi-Fi నెట్‌వర్క్‌ల వంటి నెట్‌వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు. యాప్‌ ఉపయోగించడానికి మీ టాబ్లెట్‌లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ఈ యాప్‌ సెల్ టవర్‌లు మరియు Wi-Fi నెట్‌వర్క్‌ల వంటి నెట్‌వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు. యాప్‌ ఉపయోగించడానికి మీ టీవీలో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ఈ యాప్‌ సెల్ టవర్‌లు మరియు Wi-Fi నెట్‌వర్క్‌ల వంటి నెట్‌వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు. యాప్‌ ఉపయోగించడానికి మీ ఫోన్‌లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"స్క్రీన్‌పై ఉన్నప్పుడు మాత్రమే సమీప స్థానాన్ని (నెట్‌వర్క్-ఆధారిత) యాక్సెస్ చేయండి"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"ఈ యాప్‌ సెల్ టవర్‌లు మరియు Wi-Fi నెట్‌వర్క్‌ల వంటి నెట్‌వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు, కానీ యాప్ తెరపై ఉన్నప్పుడు మాత్రమే. యాప్‌ ఉపయోగించడానికి మీ టాబ్లెట్‌లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"ఈ యాప్‌ సెల్ టవర్‌లు మరియు Wi-Fi నెట్‌వర్క్‌ల వంటి నెట్‌వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు, కానీ యాప్ తెరపై ఉన్నప్పుడు మాత్రమే. యాప్‌ ఉపయోగించడానికి మీ టీవీలో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"ఈ యాప్‌ సెల్ టవర్‌లు మరియు Wi-Fi నెట్‌వర్క్‌ల వంటి నెట్‌వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు, కానీ యాప్ తెరపై ఉన్నప్పుడు మాత్రమే. యాప్‌ ఉపయోగించడానికి మీ ఫోన్‌లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"నేపథ్యంలో స్థానాన్ని యాక్సెస్ చేయి"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"సుమారుగా లేదా ఖచ్చితమైన స్థాన యాక్సెస్‌తో పాటు అదనందా ఇది మంజూరు చేయబడితే, యాప్ నేపథ్యంలో నడుస్తున్నప్పుడు స్థానాన్ని యాక్సెస్ చేయగలదు."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"మీ ఆడియో సెట్టింగ్‌లను మార్చడం"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS అభ్యర్థన USSD అభ్యర్థనకు మార్చబడింది"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"కొత్త SS అభ్యర్థనకు మార్చబడింది"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"కార్యాలయ ప్రొఫైల్‌"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"విస్తరింపజేయి"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"కుదించు"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"విస్తరణను టోగుల్ చేయండి"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ebbf155..1b473f0 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"การโทรผ่าน Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"ปิด"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"ต้องการใช้ Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"ต้องการใช้อินเทอร์เน็ตมือถือ"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"อนุญาตให้แอปเข้าถึงคำสั่งของผู้ให้บริการตำแหน่งเพิ่มเติม ซึ่งอาจทำให้แอปสามารถแทรกแซงการทำงานของ GPS หรือต้นทางของตำแหน่งอื่นๆ ได้"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"เข้าถึงตำแหน่งที่แม่นยำเมื่ออยู่เบื้องหน้าเท่านั้น"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"แอปนี้รับตำแหน่งที่แม่นยำของคุณได้เมื่อทำงานอยู่เบื้องหน้าเท่านั้น แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในโทรศัพท์ของคุณ ซึ่งอาจทำให้มีการใช้แบตเตอรี่มากขึ้น"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"เข้าถึงตำแหน่งโดยประมาณ (อิงจากเครือข่าย)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"แอปนี้สามารถรับตำแหน่งของคุณโดยอิงจากแหล่งข้อมูลเครือข่าย เช่น เสาสัญญาณมือถือและเครือข่าย Wi-Fi แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในแท็บเล็ตของคุณ"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"แอปนี้สามารถรับตำแหน่งของคุณโดยอิงจากแหล่งข้อมูลเครือข่าย เช่น เสาสัญญาณมือถือและเครือข่าย Wi-Fi แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในทีวีของคุณ"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"แอปนี้สามารถรับตำแหน่งของคุณโดยอิงจากแหล่งข้อมูลเครือข่าย เช่น เสาสัญญาณมือถือและเครือข่าย Wi-Fi แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในโทรศัพท์ของคุณ"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"เข้าถึงตำแหน่งโดยประมาณ (อิงตามเครือข่าย) เมื่อทำงานอยู่เบื้องหน้าเท่านั้น"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"แอปนี้รับตำแหน่งของคุณโดยอิงตามแหล่งที่มาของเครือข่าย เช่น เสาส่งสัญญาณมือถือและเครือข่าย Wi-Fi เมื่อทำงานอยู่เบื้องหน้าเท่านั้น แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในแท็บเล็ตของคุณ"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"แอปนี้รับตำแหน่งของคุณโดยอิงตามแหล่งที่มาของเครือข่าย เช่น เสาส่งสัญญาณมือถือและเครือข่าย Wi-Fi เมื่อทำงานอยู่เบื้องหน้าเท่านั้น แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในทีวีของคุณ"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"แอปนี้รับตำแหน่งของคุณโดยอิงตามแหล่งที่มาของเครือข่าย เช่น เสาส่งสัญญาณมือถือและเครือข่าย Wi-Fi เมื่อทำงานอยู่เบื้องหน้าเท่านั้น แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในโทรศัพท์ของคุณ"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"เข้าถึงตำแหน่งในเบื้องหลัง"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"หากได้รับสิทธิ์นี้เพิ่มจากการเข้าถึงตำแหน่งโดยประมาณหรือตำแหน่งที่แม่นยำ แอปจะมีสิทธิ์เข้าถึงตำแหน่งระหว่างที่ทำงานในเบื้องหลังได้"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"เปลี่ยนการตั้งค่าเสียงของคุณ"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"คำขอ SS เปลี่ยนเป็นคำขอ USSD แล้ว"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"เปลี่ยนเป็นคำขอ SS ใหม่แล้ว"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"โปรไฟล์งาน"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"ขยาย"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"ยุบ"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"สลับการขยาย"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index e5bde1d..3e3b4f9 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi ng <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Pagtawag Gamit ang Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi ng <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Naka-off"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Mas gusto ang Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mas gusto ang mobile"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Nagbibigay-daan sa app na mag-access ng mga karagdagang command ng provider ng lokasyon. Maaari nitong bigyang-daan ang app na gambalain ang pagpapatakbo ng GPS o ng iba pang mga pinagmulan ng lokasyon."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"i-access lang ang tumpak na lokasyon sa foreground"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Makukuha lang ng app na ito ang iyong eksaktong lokasyon kapag nasa foreground ito. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong telepono para magamit ng app ang mga ito. Maaaring lumakas ang pagkonsumo ng baterya dahil dito."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"i-access ang tinatantyang lokasyon (batay sa network)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Makukuha ng app na ito ang iyong lokasyon batay sa mga pinagmulan ng network gaya ng mga cell tower at Wi-Fi network. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong tablet para sa app upang magamit ang mga ito."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Makukuha ng app na ito ang iyong lokasyon batay sa mga pinagmulan ng network gaya ng mga cell tower at Wi-Fi network. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong TV para sa app upang magamit ang mga ito."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Makukuha ng app na ito ang iyong lokasyon batay sa mga pinagmulan ng network gaya ng mga cell tower at Wi-Fi network. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong telepono para sa app upang magamit ang mga ito."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"i-access lang ang tinatantiyang lokasyon (batay sa network) sa foreground"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Makukuha ng app na ito ang iyong lokasyon batay sa mga source ng network gaya ng mga cell tower at Wi-Fi network ngunit magagawa lang ito kapag nasa foreground ang app. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong tablet para magamit ng app ang mga ito."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Makukuha ng app na ito ang iyong lokasyon batay sa mga source ng network gaya ng mga cell tower at Wi-Fi network, ngunit magagawa lang ito kapag nasa foreground ang app. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong TV para magamit ng app ang mga ito."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Makukuha ng app na ito ang iyong lokasyon batay sa mga source ng network gaya ng mga cell tower at Wi-Fi network, ngunit magagawa lang ito kapag nasa foreground ang app. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong telepono para magamit ng app ang mga ito."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"i-access ang lokasyon sa background"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Kung papahintulutan ito bukod pa sa pag-access sa tinataya o tumpak na lokasyon, maaaring i-access ng app ang lokasyon habang tumatakbo sa background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"baguhin ang mga setting ng iyong audio"</string>
@@ -528,7 +536,7 @@
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Hindi buo ang natukoy na fingerprint. Pakisubukang muli."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Hindi maproseso ang fingerprint. Pakisubukang muli."</string>
     <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"Marumi ang sensor ng fingerprint. Pakilinis at subukang muli."</string>
-    <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Masyadong mabilis ang paggalaw ng daliri. Pakisubukang muli."</string>
+    <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"Napakabilis ng paggalaw ng daliri. Pakisubukan ulit."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"Masyadong mabagal ang paggalaw ng daliri. Pakisubukang muli."</string>
   <string-array name="fingerprint_acquired_vendor">
   </string-array>
@@ -541,7 +549,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Nag-time out ang fingerprint. Subukang muli."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Nakansela ang operasyong ginagamitan ng fingerprint."</string>
     <string name="fingerprint_error_user_canceled" msgid="7999639584615291494">"Kinansela ng user ang operasyon sa fingerprint."</string>
-    <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Masyadong maraming beses sumubok. Subukang muli sa ibang pagkakataon."</string>
+    <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Napakaraming pagtatangka. Subukan ulit sa ibang pagkakataon."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Masyadong maraming beses sumubok. Na-disable ang sensor para sa fingerprint."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Subukang muli."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="7654382120628334248">"Walang naka-enroll na fingerprint."</string>
@@ -1416,7 +1424,7 @@
     <string name="forward_intent_to_work" msgid="621480743856004612">"Ginagamit mo ang app na ito sa iyong profile sa trabaho"</string>
     <string name="input_method_binding_label" msgid="1283557179944992649">"Pamamaraan ng pag-input"</string>
     <string name="sync_binding_label" msgid="3687969138375092423">"I-sync"</string>
-    <string name="accessibility_binding_label" msgid="4148120742096474641">"Kakayahang Ma-access"</string>
+    <string name="accessibility_binding_label" msgid="4148120742096474641">"Pagiging Accessible"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Baguhin ang wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Ginawang USSD na kahilingan ang SS na kahilingan"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Ginawang bagong SS na kahilingan"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Profile sa trabaho"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Palawakin"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"I-collapse"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"i-toggle ang pagpapalawak"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 18e1911..e326b2c 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Kablosuz"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Kablosuz Çağrı | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Kapalı"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Kablosuz bağlantı tercihli"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobil tercihli"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Uygulamanın, ekstra konum sağlayıcı komutlarına erişmesine izin verir. Bu izin, uygulamanın GPS veya diğer konum kaynaklarının çalışmasını kesmesine olanak sağlayabilir."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"yalnızca ön planda kesin konuma erişme"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Bu uygulama yalnızca ön plandayken kesin konumunuzu alabilir. Uygulamanın bu hizmetleri kullanabilmesi için telefonunuzda bu konum hizmetleri açık ve kullanılabilir olmalıdır. Bu, pil tüketimini artırabilir."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"konum bilgilerine yaklaşık olarak erişme (ağ tabanlı)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Bu uygulama baz istasyonu ve kablosuz ağ gibi ağ kaynaklarını kullanarak konumunuzu belirleyebilir. Uygulamanın bu hizmetleri kullanabilmesi için tabletinizde bu konum hizmetleri açık ve kullanılabilir olmalıdır."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Bu uygulama baz istasyonu ve kablosuz ağ gibi ağ kaynaklarını kullanarak konumunuzu belirleyebilir. Uygulamanın bu hizmetleri kullanabilmesi için TV\'nizde bu konum hizmetleri açık ve kullanılabilir olmalıdır."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Bu uygulama baz istasyonu ve kablosuz ağ gibi ağ kaynaklarını kullanarak konumunuzu belirleyebilir. Uygulamanın bu hizmetleri kullanabilmesi için telefonunuzda bu konum hizmetleri açık ve kullanılabilir olmalıdır."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"yalnızca ön planda yaklaşık konuma (ağa dayalı) erişme"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Bu uygulama baz istasyonları ve kablosuz ağlar gibi ağ kaynaklarını dikkate alarak konumunuzu bulabilir, ancak bunu yalnızca ön plandayken yapabilir. Uygulamanın bu hizmetleri kullanabilmesi için tabletinizde bu konum hizmetleri açık ve kullanılabilir olmalıdır."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Bu uygulama baz istasyonları ve kablosuz ağlar gibi ağ kaynaklarını dikkate alarak konumunuzu bulabilir, ancak bunu yalnızca ön plandayken yapabilir. Uygulamanın bu hizmetleri kullanabilmesi için TV\'nizde bu konum hizmetleri açık ve kullanılabilir olmalıdır."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Bu uygulama baz istasyonları ve kablosuz ağlar gibi ağ kaynaklarını dikkate alarak konumunuzu bulabilir, ancak bunu yalnızca ön plandayken yapabilir. Uygulamanın bu hizmetleri kullanabilmesi için telefonunuzda bu konum hizmetleri açık ve kullanılabilir olmalıdır."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"konum bilgisine arka planda eriş"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Bu izin, yaklaşık veya tam konum erişimine ek olarak verilirse uygulama, konum bilgisine arka planda çalışırken erişebilir."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ses ayarlarınızı değiştirin"</string>
@@ -1194,7 +1202,7 @@
     <string name="dump_heap_title" msgid="5864292264307651673">"Yığın dökümü paylaşılsın mı?"</string>
     <string name="dump_heap_text" msgid="4809417337240334941">"<xliff:g id="PROC">%1$s</xliff:g>, <xliff:g id="SIZE">%2$s</xliff:g> olan işlem bellek sınırını aştı. İşlemin geliştiricisiyle paylaşabileceğiniz bir bellek yığını dökümü hazır. Dikkat: Bu bellek yığını dökümü, uygulamanın erişebildiği tüm kişisel bilgilerinizi içerebilir."</string>
     <string name="sendText" msgid="5209874571959469142">"Kısa mesaj için bir işlem seçin"</string>
-    <string name="volume_ringtone" msgid="6885421406845734650">"Zil sesi düzeyi"</string>
+    <string name="volume_ringtone" msgid="6885421406845734650">"Zil ses düzeyi"</string>
     <string name="volume_music" msgid="5421651157138628171">"Medya ses düzeyi"</string>
     <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Bluetooth üzerinden çalıyor"</string>
     <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"Sessiz zil sesi ayarlandı"</string>
@@ -1204,7 +1212,7 @@
     <string name="volume_notification" msgid="2422265656744276715">"Bildirim ses düzeyi"</string>
     <string name="volume_unknown" msgid="1400219669770445902">"Ses"</string>
     <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"Bluetooth ses düzeyi"</string>
-    <string name="volume_icon_description_ringer" msgid="3326003847006162496">"Zil sesi düzeyi"</string>
+    <string name="volume_icon_description_ringer" msgid="3326003847006162496">"Zil ses düzeyi"</string>
     <string name="volume_icon_description_incall" msgid="8890073218154543397">"Çağrı ses düzeyi"</string>
     <string name="volume_icon_description_media" msgid="4217311719665194215">"Medya ses düzeyi"</string>
     <string name="volume_icon_description_notification" msgid="7044986546477282274">"Bildirim ses düzeyi"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS isteği USSD isteği olarak değişti"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Yeni SS isteği olarak değişti"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"İş profili"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Genişlet"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Daralt"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"genişletmeyi aç/kapat"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index e9f44bf..f9cbfd6 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -138,6 +138,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> через Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Виклики через Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> через VoWi-Fi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Вимкнено"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi за умовчанням"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Мобільна мережа за умовчанням"</string>
@@ -423,10 +431,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Додаток отримуватиме доступ до додаткових команд постачальника геоданих. Можливе втручання додатка в роботу GPS чи інших джерел геоданих."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"отримувати доступ до даних про точне місцезнаходження лише в активному режимі"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Цей додаток може отримувати дані про ваше точне місцезнаходження лише в активному режимі. Щоб додаток користувався службами локації, вони мають бути наявні й увімкнені на вашому телефоні. Через це може швидше розряджатись акумулятор."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"отримувати дані про приблизне місцезнаходження (на основі мережі)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Цей додаток може отримувати дані про ваше місцезнаходження на основі джерел мережі, як-от антен мобільного зв’язку та мереж Wi-Fi. Щоб додаток міг користуватися цими службами локації, вони мають бути доступними й увімкненими на вашому планшеті."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Цей додаток може отримувати дані про ваше місцезнаходження на основі джерел мережі, як-от антен мобільного зв’язку та мереж Wi-Fi. Щоб додаток міг користуватися цими службами локації, вони мають бути доступними й увімкненими на вашому телевізорі."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Цей додаток може отримувати дані про ваше місцезнаходження на основі джерел мережі, як-от антен мобільного зв’язку та мереж Wi-Fi. Щоб додаток міг користуватися цими службами локації, вони мають бути доступними й увімкненими на вашому телефоні."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"отримувати доступ до даних про приблизне місцезнаходження (на основі мережі) лише в активному режимі"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Цей додаток може отримувати дані про ваше місцезнаходження на основі джерел мережі, як-от антен мобільного зв’язку та мереж Wi-Fi, лише в активному режимі. Щоб додаток міг користуватися цими службами локації, вони мають бути доступними й увімкненими на вашому планшеті."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Цей додаток може отримувати дані про ваше місцезнаходження на основі джерел мережі, як-от антен мобільного зв’язку та мереж Wi-Fi, лише в активному режимі. Щоб додаток міг користуватися цими службами локації, вони мають бути доступними й увімкненими на вашому телевізорі."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Цей додаток може отримувати дані про ваше місцезнаходження на основі джерел мережі, як-от антен мобільного зв’язку та мереж Wi-Fi, лише в активному режимі. Щоб додаток міг користуватися цими службами локації, вони мають бути доступними й увімкненими на вашому телефоні."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"доступ до геоданих у фоновому режимі"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Якщо ви надасте цей дозвіл і доступ до приблизного або точного місцезнаходження, додаток зможе отримувати геодані у фоновому режимі."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"змінювати налаштув-ня звуку"</string>
@@ -1340,7 +1348,7 @@
     <string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"SIM-карту додано"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"Перезапустіть пристрій, щоб отримати доступ до мобільної мережі."</string>
-    <string name="sim_restart_button" msgid="4722407842815232347">"Перезапуск"</string>
+    <string name="sim_restart_button" msgid="4722407842815232347">"Перезапустити"</string>
     <string name="install_carrier_app_notification_title" msgid="9056007111024059888">"Активувати мобільну службу"</string>
     <string name="install_carrier_app_notification_text" msgid="3346681446158696001">"Завантажити додаток оператора, щоб активувати нову SIM-карту"</string>
     <string name="install_carrier_app_notification_text_app_name" msgid="1196505084835248137">"Щоб активувати нову SIM-карту, завантажте додаток <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -1891,6 +1899,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Запит SS змінено на запит USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Змінено на новий запит SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Робочий профіль"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Розгорнути"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Згорнути"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"розгорнути або згорнути"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 96bd9a3..60b650d 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"‏WiFi کالنگ | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"آف"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"‏Wi-Fi ترجیحی"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"موبائل ترجیحی"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"‏ایپ کو اضافی مقام فراہم کنندہ کی کمانڈز تک رسائی حاصل کرنے کی اجازت دیتی ہے۔ یہ ایپ کو GPS یا دوسرے مقام کے مآخذ کے عمل کے ساتھ مداخلت کرنے کی اجازت دے سکتی ہے۔"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"صرف پیش منظر میں درست مقام تک رسائی حاصل کریں"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"یہ ایپ جب پس منظر میں ہوتی ہے تبھی یہ آپ کا صحیح مقام حاصل کر سکتی ہے۔ ایپ کو ان مقام کی سروسز کو استعمال کر سکنے کیلئے ان کا آن ہونا اور آپ کے فون پر دستیاب ہونا ضروری ہے۔"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"تخمینی مقام تک رسائی حاصل کریں (نیٹ ورک پر مبنی)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"‏نیٹ ورک مآخذات جیسے کہ سیل ٹاورز اور Wi-Fi نیٹ ورکس کی بنیاد پر یہ ایپ آپ کا مقام حاصل کر سکتی ہے۔ ایپ کو ان مقام کی سروسز کو استعمال کرنے کیلئے ان کا آن ہونا اور آپ کے ٹیبلیٹ پر دستیاب ہونا ضروری ہے۔"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"‏نیٹ ورک مآخذات جیسے کہ سیل ٹاورز اور Wi-Fi نیٹ ورکس کی بنیاد پر یہ ایپ آپ کا مقام حاصل کر سکتی ہے۔ ایپ کو ان مقام کی سروسز کو استعمال کرنے کیلئے ان کا آن ہونا اور آپ کے TV پر دستیاب ہونا ضروری ہے۔"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"‏نیٹ ورک مآخذات جیسے کہ سیل ٹاورز اور Wi-Fi نیٹ ورکس کی بنیاد پر یہ ایپ آپ کا مقام حاصل کر سکتی ہے۔ ایپ کو ان مقام کی سروسز کو استعمال کرنے کیلئے ان کا آن ہونا اور آپ کے فون پر دستیاب ہونا ضروری ہے۔"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"صرف پیش منظر میں (نیٹ ورک پر مبنی) تخمینی مقام تک رسائی حاصل کریں"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"‏نیٹ ورک ماخذات جیسے کہ سیل ٹاورز اور Wi-Fi نیٹ ورکس کی بنیاد پر یہ ایپ آپ کا مقام حاصل کر سکتی ہے لیکن صرف اس وقت جب ایپ پیش منظر میں ہو۔ ایپ کو ان مقام کی سروسز کو استعمال کرنے کے لیے ان کا آن ہونا اور آپ کے ٹیبلیٹ پر دستیاب ہونا ضروری ہے۔"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"‏نیٹ ورک ماخذات جیسے کہ سیل ٹاورز اور Wi-Fi نیٹ ورکس کی بنیاد پر یہ ایپ آپ کا مقام حاصل کر سکتی ہے لیکن صرف اس وقت جب ایپ پیش منظر میں ہو۔ ایپ کو ان مقام کی سروسز کو استعمال کرنے کے لیے ان کا آن ہونا اور آپ کی ٹی وی پر دستیاب ہونا ضروری ہے۔"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"‏نیٹ ورک ماخذات جیسے کہ سیل ٹاورز اور Wi-Fi نیٹ ورکس کی بنیاد پر یہ ایپ آپ کا مقام حاصل کر سکتی ہے لیکن صرف اس وقت جب ایپ پیش منظر میں ہو۔ ایپ کو ان مقام کی سروسز کو استعمال کرنے کے لیے ان کا آن ہونا اور آپ کے فون پر دستیاب ہونا ضروری ہے۔"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"پس منظر میں مقام کی رسائی حاصل کریں"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"اگر اضافی طور پر اسے تخمینی یا درست مقام تک رسائی کی منظوری دی جاتی ہے تو پس منظر میں چلنے کے دوران ایپ اس مقام تک رسائی حاصل کر سکتی ہے۔"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"اپنے آڈیو کی ترتیبات کو تبدیل کریں"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"‏SS درخواست کو USSD درخواست میں تبدیل کر دیا گیا"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"‏نئی SS درخواست میں تبدیل کر دیا گیا"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"دفتری پروفائل"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"پھیلائیں"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"سکیڑیں"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"پھیلاؤ کو ٹوگل کریں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index ccb9e15..2192ad4 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi chaqiruv | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWi-Fi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"O‘chiq"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi afzalligi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Mobil internet afzalligi"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Ilovaga qo‘shimcha joylashuv xizmati buyruqlaridan foydalanishga ruxsat beradi. Uning yordamida ilova GPS yoki boshqa joylashuv ma’lumoti manbalarining ishlashiga xalaqit qilishi mumkin."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"aniq joylashuv axborotini olishga faqat old fonda ruxsat"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Bu ilova faqat fon rejimida aniq joylashuv axborotingizdan foydalanishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular telefoningizda yoniq turishi va ishlashi kerak. Bunda batareya sarfi oshishi mumkin."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"taxminiy joylashuv (tarmoq asosida) ma’lumotlaridan foydalanishga ruxsat"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Bu ilova Wi-Fi va uyali tarmoq antennalari kabi tarmoq manbalari asosida joylashuvingiz axborotini olishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular planshetda yoniq bo‘lishi va ishlashi kerak."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Bu ilova Wi-Fi va uyali tarmoq antennalari kabi tarmoq manbalari asosida joylashuvingiz axborotini olishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular televizorda yoniq bo‘lishi va ishlashi kerak."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Bu ilova Wi-Fi va uyali tarmoq antennalari kabi tarmoq manbalari asosida joylashuvingiz axborotini olishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular telefoningizda yoniq bo‘lishi va ishlashi kerak."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"faqat faol rejimda taxminiy joylashuv axborotiga (tarmoq asosida) ruxsat"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Bu ilova faqat faol rejimda ekanida Wi-Fi va uyali tarmoq antennalari kabi tarmoq manbalari asosida joylashuvingiz axborotini olishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular planshetingizda yoniq bo‘lishi va ishlashi kerak."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Bu ilova faqat faol rejimda ekanida Wi-Fi va uyali tarmoq antennalari kabi tarmoq manbalari asosida joylashuvingiz axborotini olishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular televizoringizda yoniq bo‘lishi va ishlashi kerak."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Bu ilova faqat faol rejimda ekanida Wi-Fi va uyali tarmoq antennalari kabi tarmoq manbalari asosida joylashuvingiz axborotini olishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular telefoningizda yoniq bo‘lishi va ishlashi kerak."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"fonda joylashuv axborotidan foydalanish"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Agar taxminiy yoki aniq joylashuv axborotiga qo‘shimcha tarzda ruxsat berilgan bo‘lsa, ilova ishlayotganda joylashuv axborotidan fonda foydala oladi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"audio sozlamalaringizni o‘zgartirish"</string>
@@ -1826,6 +1834,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS talabi USSD talabiga almashtirildi"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Yangi SS talabiga almashtirildi"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Ishchi profil"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Yoyish"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Yig‘ish"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"ochish yoki yopish"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 02b9ed9..00e9891 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"Wi-Fi <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Gọi qua Wi-Fi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWifi <xliff:g id="SPN">%s</xliff:g>"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Tắt"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Ưu tiên Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Ưu tiên dữ liệu di động"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Cho phép ứng dụng truy cập vào các lệnh của nhà cung cấp vị trí bổ sung. Điều này có thể cho phép ứng dụng can thiệp vào hoạt động của Hệ thống định vị toàn cầu (GPS) hoặc các nguồn vị trí khác."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"chỉ truy cập vị trí chính xác trong nền trước"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Bất cứ khi nào chạy trong nền trước, ứng dụng này có thể nhận thông tin vị trí chính xác của bạn. Để ứng dụng có thể sử các dụng dịch vụ vị trí, điện thoại của bạn phải có các dịch vụ này và dịch vụ ở trạng thái bật. Hoạt động này có thể tăng mức tiêu thụ pin."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"truy cập vị trí gần đúng (dựa vào mạng)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ứng dụng này có thể nhận thông tin vị trí của bạn dựa trên các nguồn mạng như tháp phát sóng di động và mạng Wi-Fi. Các dịch vụ vị trí này phải được bật và khả dụng trên máy tính bảng của bạn để ứng dụng có thể sử dụng chúng."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ứng dụng này có thể nhận thông tin vị trí của bạn dựa trên các nguồn mạng như tháp phát sóng di động và mạng Wi-Fi. Các dịch vụ vị trí này phải được bật và khả dụng trên TV của bạn để ứng dụng có thể sử dụng chúng."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ứng dụng này có thể nhận thông tin vị trí của bạn dựa trên các nguồn mạng như tháp phát sóng di động và mạng Wi-Fi. Các dịch vụ vị trí này phải được bật và khả dụng trên điện thoại của bạn để ứng dụng có thể sử dụng chúng."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"chỉ truy cập vị trí gần đúng (dựa trên mạng) trong nền trước"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Bất cứ khi nào chạy trong nền trước, ứng dụng này có thể nhận thông tin vị trí dựa trên nguồn mạng, chẳng hạn như trạm phát sóng di động và mạng Wi-Fi. Để ứng dụng có thể dùng các dịch vụ vị trí, máy tính bảng của bạn phải có các dịch vụ này ở trạng thái bật."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Bất cứ khi nào chạy trong nền trước, ứng dụng này có thể nhận thông tin vị trí dựa trên nguồn mạng, chẳng hạn như trạm phát sóng di động và mạng Wi-Fi. Để ứng dụng có thể dùng các dịch vụ vị trí, TV của bạn phải có các dịch vụ này ở trạng thái bật."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Bất cứ khi nào chạy trong nền trước, ứng dụng này có thể nhận thông tin vị trí dựa trên nguồn mạng, chẳng hạn như trạm phát sóng di động và mạng Wi-Fi. Để ứng dụng có thể dùng các dịch vụ vị trí, điện thoại của bạn phải có các dịch vụ này ở trạng thái bật."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"truy cập vào vị trí trong nền"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Nếu bạn cấp cho ứng dụng quyền truy cập bổ sung vào vị trị gần đúng hoặc chính xác, thì ứng dụng có thể truy cập vào vị trí đó khi chạy trong nền."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"thay đổi cài đặt âm thanh của bạn"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Yêu cầu SS đã thay đổi thành yêu cầu USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Đã thay đổi thành yêu cầu SS mới"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Hồ sơ công việc"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Mở rộng"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Thu gọn"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"chuyển đổi mở rộng"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 076d6f9..d655d32 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> WLAN"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"WLAN 通话 | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"关闭"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"首选 WLAN"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"首选移动数据网络"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"允许该应用使用其他的位置信息提供程序命令。此权限使该应用可以干扰GPS或其他位置信息源的运作。"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"只能在前台获取精确的位置信息"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"此应用只有在前台运行时才能获取您的精确位置信息。您的手机必须支持并开启这些位置信息服务,此应用才能使用这些服务。这可能会增加耗电量。"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"访问大致位置信息(以网络为依据)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"此应用可根据网络来源(例如基站和 WLAN 网络)获取您的位置信息。您的平板电脑必须支持并开启这些位置信息服务,此应用才能使用这些服务。"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"此应用可根据网络来源(例如基站和 WLAN 网络)获取您的位置信息。您的电视必须支持并开启这些位置信息服务,此应用才能使用这些服务。"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"此应用可根据网络来源(例如基站和 WLAN 网络)获取您的位置信息。您的手机必须支持并开启这些位置信息服务,此应用才能使用这些服务。"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"只能在前台获取大概位置(基于网络)"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"此应用只能在前台根据网络来源(例如手机信号塔和 WLAN 网络)获取您的位置信息。您的平板电脑必须支持并开启这些位置信息服务,此应用才能使用这些服务。"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"此应用只能在前台根据网络来源(例如手机信号塔和 WLAN 网络)获取您的位置信息。您的电视必须支持并开启这些位置信息服务,此应用才能使用这些服务。"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"此应用只能在前台根据网络来源(例如手机信号塔和 WLAN 网络)获取您的位置信息。您的手机必须支持并开启这些位置信息服务,此应用才能使用这些服务。"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"在后台使用位置信息"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"如果另外授予大致位置信息或精确位置信息访问权限,该应用便可在后台运行时使用位置信息。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"更改您的音频设置"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS 请求已更改为 USSD 请求"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"已更改为新的 SS 请求"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"工作资料"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"展开"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"收起"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"切换展开模式"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 1484006..086a068 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"WiFi 通話 | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"關閉"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"首選 Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"流動數據優先"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"允許應用程式存取額外的位置提供者指令。這項設定可能會使應用程式干擾 GPS 或其他位置來源的運作。"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"只在前景存取精確位置"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"此應用程式只可在前台運行時獲取您的確實位置資訊。您的手機必須支援並啟用這些位置資訊服務,應用程式方可使用這項功能,但這樣做可能會增加耗電量。"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"存取約略位置 (根據網絡)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"此應用程式可以根據您的網絡來源 (例如手機訊號塔和 Wi-Fi 網絡) 取得您的位置。您的平板電腦必須支援並啟用這些位置資訊服務,應用程式方可使用這項功能。"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"此應用程式可以根據您的網絡來源 (例如手機訊號塔和 Wi-Fi 網絡) 取得您的位置。您的電視必須支援並啟用這些位置資訊服務,應用程式方可使用這項功能。"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"此應用程式可以根據您的網絡來源 (例如手機訊號塔和 Wi-Fi 網絡) 取得您的位置。您的手機必須支援並啟用這些位置資訊服務,應用程式方可使用這項功能。"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"只可在前景存取大概位置 (根據網絡定位)"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"此應用程式只能在前景中根據網絡來源 (例如手機訊號發射塔和 Wi-Fi 網絡) 獲取您的位置資訊。您必須在平板電腦上開啟這些位置資訊服務,才能讓此應用程式使用位置資訊。"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"此應用程式只能在前景中根據網絡來源 (例如手機訊號發射塔和 Wi-Fi 網絡) 獲取您的位置資訊。您必須在電視上開啟這些位置資訊服務,才能讓此應用程式使用位置資訊。"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"此應用程式只能在前景中根據網絡來源 (例如手機訊號發射塔和 Wi-Fi 網絡) 獲取您的位置資訊。您必須在手機上開啟這些位置資訊服務,才能讓此應用程式使用位置資訊。"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"在背景存取位置資訊"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"如果您另外授予概略位置或精確位置的存取權,這個應用程式在背景運行時將可存取位置資訊。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"更改音效設定"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS 要求已變更為 USSD 要求"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"已變更為新的 SS 要求"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"工作設定檔"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"展開"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"收合"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"切換展開"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 608a758..e789e9a 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Wi-Fi 通話 | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"關閉"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi 優先"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"行動網路優先"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"允許應用程式存取額外位置資訊提供者指令。這項設定可能會造成應用程式干擾 GPS 或其他位置資訊來源的運作。"</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"僅可在前景中取得精確位置"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"這個應用程式只能在前景中取得你的確切位置。你必須在手機上開啟這些定位服務,才能讓這個應用程式取得確切位置。請注意,這麼做可能會增加耗電量。"</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"存取概略位置 (以網路為依據)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"這個應用程式可根據網路來源 (例如基地台和 Wi-Fi 網路) 取得你的位置資訊。你必須在平板電腦上開啟這類定位服務,才能讓這個應用程式取得位置資訊。"</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"這個應用程式可根據網路來源 (例如基地台和 Wi-Fi 網路) 取得你的位置資訊。你必須在電視上開啟這類定位服務,才能讓這個應用程式取得位置資訊。"</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"這個應用程式可根據網路來源 (例如基地台和 Wi-Fi 網路) 取得你的位置資訊。你必須在手機上開啟這類定位服務,才能讓這個應用程式取得位置資訊。"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"只有在前景執行時才能根據網路取得概略位置"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"只要這個應用程式在前景執行,就可以根據網路來源 (例如基地台和 Wi-Fi 網路) 取得你的位置資訊。如要讓這個應用程式使用定位服務,你必須在平板電腦上開啟這些服務。"</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"只要這個應用程式在前景執行,就可以根據網路來源 (例如基地台和 Wi-Fi 網路) 取得你的位置資訊。如要讓這個應用程式使用定位服務,你必須在電視上開啟這些服務。"</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"只要這個應用程式在前景執行,就可以根據網路來源 (例如基地台和 Wi-Fi 網路) 取得你的位置資訊。如要讓這個應用程式使用定位服務,你必須在手機上開啟這些服務。"</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"在背景存取位置資訊"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"除了概略位置或精確位置的存取權外,若您另外授予這項存取權,這個應用程式就能在背景執行時存取位置資訊。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"變更音訊設定"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"SS 要求已變更為 USSD 要求"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"已變更為新的 SS 要求"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"工作資料夾"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"展開"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"收合"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"切換展開模式"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 42a1ad0..2e1540f 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -136,6 +136,14 @@
     <string name="wfcSpnFormat_spn_wifi" msgid="6546481665561961938">"<xliff:g id="SPN">%s</xliff:g> Wi-Fi"</string>
     <string name="wfcSpnFormat_wifi_calling_bar_spn" msgid="1726178784338466265">"Ukushaya kwe-WiFi | <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"<xliff:g id="SPN">%s</xliff:g> VoWifi"</string>
+    <!-- no translation found for wfcSpnFormat_wifi_calling (4990486735013125329) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi (1892673884655959773) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_wifi_calling_wo_hyphen (1336669776254502831) -->
+    <skip />
+    <!-- no translation found for wfcSpnFormat_vowifi (1765176406171272629) -->
+    <skip />
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Valiwe"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Kuncanyelwa i-Wi-Fi"</string>
     <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Kuncanyelwa iselula"</string>
@@ -417,10 +425,10 @@
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Ivumela uhlelo lokusebenza ukufinyelela imiyalo eyengeziwe yabahlinzeki bendawo. Lokhu kungase kuvumele uhlelo lokusebenza ukuthi liphazamisane nomsebenzi we-GPS noma eminye imithombo yendawo."</string>
     <string name="permlab_accessFineLocation" msgid="6265109654698562427">"finyelela indawo eqondile kuphela phambili"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Lolu hlelo lokusebenza lungakutholela indawo eqondile kuphela uma liphambili. Lawa masevisi endawo kufanele avulwe futhi atholakale efonini yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa. Lokhu kungakhulisa ukusebenza kwebhethri."</string>
-    <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"finyelela kundawo elinganiselwe (esuselwa kunethiwekhi)"</string>
-    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Lolu hlelo lokusebenza lungathola indawo yakho ngokususelwe kumithombo yenethiwekhi njengamathawa eseli namanethiwekhi e-Wi-Fi. Lawa masevisi endawo kufanele avulwe futhi atholakale kuthebhulethi yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa."</string>
-    <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Lolu hlelo lokusebenza lingathola indawo yakho ngokususelwe kumithombo yenethiwekhi njengamathawa eseli namanethiwekhi e-Wi-Fi. Lawa masevisi endawo kufanele avulwe futhi atholakale ku-TV yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa."</string>
-    <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Lolu hlelo lokusebenza lungathola indawo yakho ngokususelwe kumithombo yenethiwekhi njengamathawa eseli kanye namanethiwekhi e-Wi-Fi. Lawa masevisi endawo kufanele avulwe futhi atholakale efonini yakho ukuze uhlelo lokusebenza likwazi ukuwasebenzisa."</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"finyelela indawo eseduze (esuselwa kunethiwekhi) kuphela ngaphambili"</string>
+    <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Lolu hlelo lokusebenza lungathola indawo yakho kusukela kumithombo yenethiwekhi efana nezinqaba zeselula namanethiwekhi e-Wi-Fi, kodwa kuphela uma uhlelo lokusebenza lungaphambili. Lawa masevisi endawo kumele avulwe futhi atholakale kuthebulethi yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa."</string>
+    <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Lolu hlelo lokusebenza lungathola indawo yakho kusukela kumithombo yenethiwekhi efana nezinqaba zeselula namanethiwekhi e-Wi-Fi, kodwa kuphela uma uhlelo lokusebenza lungaphambili. Lawa masevisi endawo kumele avulwe futhi atholakale ku-TV yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa."</string>
+    <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Lolu hlelo lokusebenza lungathola indawo yakho kusukela kumithombo yenethiwekhi efana nezinqaba zeselula kanye namanethiwekhi e-Wi-Fi, kodwa kuphela uma uhlelo lokusebenza lungaphambili. Lawa masevisi endawo kumele avulwe futhi atholakale kufoni yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"finyelela kundawo ngemuva"</string>
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Uma lokhu kunikezwa ngokungeziwe ekufinyeleleni okulinganiselwe noma okunembile kwendawo uhlelo lokusebenza lungafinyelela kundawo ngenkathi lusebenza ngemuva."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"shintsha izilungiselelo zakho zomsindo"</string>
@@ -1825,6 +1833,8 @@
     <string name="stk_cc_ss_to_ussd" msgid="5614626512855868785">"Isicelo se-SS sishintshele kusicelo se-USSD"</string>
     <string name="stk_cc_ss_to_ss" msgid="7716729801537709054">"Ishintshele kusicelo esisha se-SS"</string>
     <string name="notification_work_profile_content_description" msgid="4600554564103770764">"Iphrofayela yomsebenzi"</string>
+    <!-- no translation found for notification_alerted_content_description (1296617716556420585) -->
+    <skip />
     <string name="expand_button_content_description_collapsed" msgid="3609784019345534652">"Nweba"</string>
     <string name="expand_button_content_description_expanded" msgid="8520652707158554895">"Goqa"</string>
     <string name="expand_action_accessibility" msgid="5307730695723718254">"guqula ukunwebisa"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a25c998..a99b942 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2448,6 +2448,25 @@
             <flag name="noExcludeDescendants" value="0x8" />
         </attr>
 
+        <!-- Hints the Android System whether the view node associated with this View should be
+             use for content capture purposes. -->
+        <attr name="importantForContentCapture">
+            <!-- Let the Android System use its heuristics to determine if the view is important for content capture. -->
+            <flag name="auto" value="0" />
+            <!-- Hint the Android System that this view is important for content capture,
+                  and its children (if any) will be traversed.. -->
+            <flag name="yes" value="0x1" />
+            <!-- Hint the Android System that this view is *not* important for content capture,
+                  but its children (if any) will be traversed.. -->
+            <flag name="no" value="0x2" />
+            <!-- Hint the Android System that this view is important for content capture,
+                 but its children (if any) will not be traversed. -->
+            <flag name="yesExcludeDescendants" value="0x4" />
+            <!-- Hint the Android System that this view is *not* important for content capture,
+                 and its children (if any) will not be traversed. -->
+            <flag name="noExcludeDescendants" value="0x8" />
+        </attr>
+
         <!-- Boolean that controls whether a view can take focus while in touch mode.
              If this is true for a view, that view can gain focus when clicked on, and can keep
              focus if another view is clicked on that doesn't have this attribute set to true. -->
@@ -3587,11 +3606,22 @@
              {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
              android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
         <attr name="notificationTimeout" format="integer" />
-        <!-- The minimum timeout in milliseconds that UI controls need to remain on the screen.
+        <!-- A recommended timeout in milliseconds used in
+             {@link android.view.accessibility.AccessibilityManager#getRecommendedTimeoutMillis(int, int)
+             android.view.accessibility.AccessibilityManager.getRecommendedTimeoutMillis(int, int)}
+             to return a suitable value for UIs that do not include interactive controls.
              This setting can be changed at runtime by calling
              {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
              android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
-        <attr name="minimumUiTimeout" format="integer" />
+        <attr name="nonInteractiveUiTimeout" format="integer" />
+        <!-- A recommended timeout in milliseconds used in
+             {@link android.view.accessibility.AccessibilityManager#getRecommendedTimeoutMillis(int, int)
+             android.view.accessibility.AccessibilityManager.getRecommendedTimeoutMillis(int, int)}
+             to return a suitable value for interactive controls.
+             This setting can be changed at runtime by calling
+             {@link android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
+             android.accessibilityservice.AccessibilityService.setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}. -->
+        <attr name="interactiveUiTimeout" format="integer" />
         <!-- Additional flags as specified in
              {@link android.accessibilityservice.AccessibilityServiceInfo}.
              This setting can be changed at runtime by calling
diff --git a/core/res/res/values/colors_car.xml b/core/res/res/values/colors_car.xml
index 32671ac8..ea7c009 100644
--- a/core/res/res/values/colors_car.xml
+++ b/core/res/res/values/colors_car.xml
@@ -284,4 +284,8 @@
 
     <color name="car_red_500a">#ffd50000</color>
     <color name="car_red_a700">#ffd50000</color>
+
+    <color name="car_keyboard_divider_line">#38ffffff</color>
+    <color name="car_keyboard_text_primary_color">@color/car_grey_50</color>
+    <color name="car_keyboard_text_secondary_color">#8af8f9fa</color>
 </resources>
diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml
index 0fe80a1..ded916f 100644
--- a/core/res/res/values/colors_device_defaults.xml
+++ b/core/res/res/values/colors_device_defaults.xml
@@ -42,4 +42,7 @@
     <!-- Error color -->
     <color name="error_color_device_default_dark">@color/error_color_material_dark</color>
     <color name="error_color_device_default_light">@color/error_color_material_light</color>
+
+    <color name="list_divider_color_light">#64000000</color>
+    <color name="list_divider_color_dark">#85ffffff</color>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a8c78a6..829d6f5 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -55,6 +55,8 @@
         <item><xliff:g id="id">@string/status_bar_hotspot</xliff:g></item>
         <item><xliff:g id="id">@string/status_bar_mobile</xliff:g></item>
         <item><xliff:g id="id">@string/status_bar_airplane</xliff:g></item>
+        <item><xliff:g id="id">@string/status_bar_microphone</xliff:g></item>
+        <item><xliff:g id="id">@string/status_bar_camera</xliff:g></item>
         <item><xliff:g id="id">@string/status_bar_battery</xliff:g></item>
     </string-array>
 
@@ -87,6 +89,8 @@
     <string translatable="false" name="status_bar_mobile">mobile</string>
     <string translatable="false" name="status_bar_vpn">vpn</string>
     <string translatable="false" name="status_bar_ethernet">ethernet</string>
+    <string translatable="false" name="status_bar_microphone">microphone</string>
+    <string translatable="false" name="status_bar_camera">camera</string>
     <string translatable="false" name="status_bar_airplane">airplane</string>
 
     <!-- Flag indicating whether the surface flinger has limited
@@ -906,7 +910,7 @@
     <!--  Control whether to lock day/night mode change from normal application. When it is
           true, day / night mode change is only allowed to apps with MODIFY_DAY_NIGHT_MODE
           permission. -->
-    <bool name="config_lockDayNightMode">false</bool>
+    <bool name="config_lockDayNightMode">true</bool>
 
     <!-- Control the default night mode to use when there is no other mode override set.
          One of the following values (see UiModeManager.java):
@@ -2428,7 +2432,10 @@
          Can be customized for other product types -->
     <string name="config_chooseTypeAndAccountActivity" translatable="false"
             >android/android.accounts.ChooseTypeAndAccountActivity</string>
-
+    <!-- Name of the activity that will handle requests to the system to choose an activity for
+         the purposes of resolving an intent. -->
+    <string name="config_chooserActivity" translatable="false"
+            >com.android.systemui/com.android.systemui.chooser.ChooserActivity</string>
     <!-- Component name of a custom ResolverActivity (Intent resolver) to be used instead of
          the default framework version. If left empty, then the framework version will be used.
          Example: com.google.android.myapp/.resolver.MyResolverActivity  -->
@@ -2793,7 +2800,7 @@
         <item>LPP_PROFILE=0</item>
         <item>USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=1</item>
         <item>A_GLONASS_POS_PROTOCOL_SELECT=0</item>
-        <item>GPS_LOCK=0</item>
+        <item>GPS_LOCK=3</item>
     </string-array>
 
     <!-- Sprint need a 70 ms delay for 3way call -->
@@ -3528,6 +3535,9 @@
     <!-- Whether or not battery saver should be "sticky" when manually enabled. -->
     <bool name="config_batterySaverStickyBehaviourDisabled">false</bool>
 
+    <!-- Config flag to track default disable threshold for Dynamic power savings enabled battery saver. -->
+    <integer name="config_dynamicPowerSavingsDefaultDisableThreshold">80</integer>
+
     <!-- Model of potentially misprovisioned devices. If none is specified in an overlay, an
          empty string is passed in. -->
     <string name="config_misprovisionedDeviceModel" translatable="false"></string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index ba483fb..b65c0fd 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -426,6 +426,9 @@
     <!-- Size of the profile badge for notifications -->
     <dimen name="notification_badge_size">12dp</dimen>
 
+    <!-- Size of the alerted icon for notifications -->
+    <dimen name="notification_alerted_size">18dp</dimen>
+
     <!-- Keyguard dimensions -->
     <!-- TEMP -->
     <dimen name="kg_security_panel_height">600dp</dimen>
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
index a0c02ed..5014a29 100644
--- a/core/res/res/values/dimens_car.xml
+++ b/core/res/res/values/dimens_car.xml
@@ -34,7 +34,6 @@
     <!-- The diff between keyline 1 and keyline 3. -->
     <dimen name="car_keyline_1_keyline_3_diff">88dp</dimen>
     <dimen name="car_dialog_action_bar_height">@dimen/car_card_action_bar_height</dimen>
-    <dimen name="car_primary_icon_size">44dp</dimen>
 
     <!-- Text size for car -->
     <dimen name="car_title_size">32sp</dimen>
@@ -44,9 +43,10 @@
     <dimen name="car_headline3_size">24sp</dimen>
     <dimen name="car_headline4_size">20sp</dimen>
     <dimen name="car_body1_size">32sp</dimen>
-    <dimen name="car_body2_size">26sp</dimen>
-    <dimen name="car_body3_size">16sp</dimen>
-    <dimen name="car_body4_size">14sp</dimen>
+    <dimen name="car_body2_size">28sp</dimen>
+    <dimen name="car_body3_size">26sp</dimen>
+    <dimen name="car_body4_size">24sp</dimen>
+    <!-- car_body5_size is deprecated -->
     <dimen name="car_body5_size">18sp</dimen>
     <dimen name="car_label1_size">26sp</dimen>
     <dimen name="car_label2_size">64sp</dimen>
@@ -55,16 +55,19 @@
 
     <!-- Common icon size for car app -->
     <dimen name="car_icon_size">56dp</dimen>
+    <dimen name="car_primary_icon_size">44dp</dimen>
+    <dimen name="car_secondary_icon_size">36dp</dimen>
 
-    <dimen name="car_card_header_height">96dp</dimen>
-    <dimen name="car_card_action_bar_height">96dp</dimen>
+    <dimen name="car_card_header_height">76dp</dimen>
+    <dimen name="car_card_action_bar_height">76dp</dimen>
 
     <!-- Paddings -->
-    <dimen name="car_padding_1">4dp</dimen>
-    <dimen name="car_padding_2">10dp</dimen>
-    <dimen name="car_padding_3">16dp</dimen>
-    <dimen name="car_padding_4">28dp</dimen>
-    <dimen name="car_padding_5">32dp</dimen>
+    <dimen name="car_padding_0">4dp</dimen>
+    <dimen name="car_padding_1">8dp</dimen>
+    <dimen name="car_padding_2">16dp</dimen>
+    <dimen name="car_padding_3">28dp</dimen>
+    <dimen name="car_padding_4">32dp</dimen>
+    <dimen name="car_padding_5">64dp</dimen>
 
     <!-- Radius -->
     <dimen name="car_radius_1">4dp</dimen>
@@ -85,6 +88,7 @@
     <dimen name="car_borderless_button_horizontal_padding">0dp</dimen>
     <dimen name="car_button_radius">@dimen/car_radius_1</dimen>
     <dimen name="car_pill_button_size">56dp</dimen>
+    <dimen name="car_touch_target_size">76dp</dimen>
 
     <!-- Seekbar -->
     <dimen name="car_seekbar_height">6dp</dimen>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 3183169..64e5bc0 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -121,6 +121,18 @@
   <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_SCROLL_RIGHT}. -->
   <item type="id" name="accessibilityActionScrollRight" />
 
+  <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_PAGE_UP}. -->
+  <item type="id" name="accessibilityActionPageUp" />
+
+  <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_PAGE_DOWN}. -->
+  <item type="id" name="accessibilityActionPageDown" />
+
+  <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_PAGE_LEFT}. -->
+  <item type="id" name="accessibilityActionPageLeft" />
+
+  <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_PAGE_RIGHT}. -->
+  <item type="id" name="accessibilityActionPageRight" />
+
   <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_SET_PROGRESS}. -->
   <item type="id" name="accessibilityActionSetProgress" />
 
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
index 35eee6a..d6c0a10 100644
--- a/core/res/res/values/locale_config.xml
+++ b/core/res/res/values/locale_config.xml
@@ -23,80 +23,81 @@
         <item>ak-GH</item> <!-- Akan (Ghana) -->
         <item>am-ET</item> <!-- Amharic (Ethiopia) -->
         <item>ar-AE</item> <!-- Arabic (United Arab Emirates) -->
-        <item>ar-AE-u-nu-latn</item> <!-- Arabic (United Arab Emirates,Western Digits) -->
+        <item>ar-AE-u-nu-latn</item> <!-- Arabic (United Arab Emirates, Western Digits) -->
         <item>ar-BH</item> <!-- Arabic (Bahrain) -->
-        <item>ar-BH-u-nu-latn</item> <!-- Arabic (Bahrain,Western Digits) -->
+        <item>ar-BH-u-nu-latn</item> <!-- Arabic (Bahrain, Western Digits) -->
         <item>ar-DJ</item> <!-- Arabic (Djibouti) -->
-        <item>ar-DJ-u-nu-latn</item> <!-- Arabic (Djibouti,Western Digits) -->
+        <item>ar-DJ-u-nu-latn</item> <!-- Arabic (Djibouti, Western Digits) -->
         <item>ar-DZ</item> <!-- Arabic (Algeria) -->
-        <item>ar-DZ-u-nu-arab</item> <!-- Arabic (Algeria,Arabic-Indic Digits) -->
+        <item>ar-DZ-u-nu-arab</item> <!-- Arabic (Algeria, Arabic-Indic Digits) -->
         <item>ar-EG</item> <!-- Arabic (Egypt) -->
-        <item>ar-EG-u-nu-latn</item> <!-- Arabic (Egypt,Western Digits) -->
+        <item>ar-EG-u-nu-latn</item> <!-- Arabic (Egypt, Western Digits) -->
         <item>ar-EH</item> <!-- Arabic (Western Sahara) -->
-        <item>ar-EH-u-nu-arab</item> <!-- Arabic (Western Sahara,Arabic-Indic Digits) -->
+        <item>ar-EH-u-nu-arab</item> <!-- Arabic (Western Sahara, Arabic-Indic Digits) -->
         <item>ar-ER</item> <!-- Arabic (Eritrea) -->
-        <item>ar-ER-u-nu-latn</item> <!-- Arabic (Eritrea,Western Digits) -->
+        <item>ar-ER-u-nu-latn</item> <!-- Arabic (Eritrea, Western Digits) -->
         <item>ar-IL</item> <!-- Arabic (Israel) -->
-        <item>ar-IL-u-nu-latn</item> <!-- Arabic (Israel,Western Digits) -->
+        <item>ar-IL-u-nu-latn</item> <!-- Arabic (Israel, Western Digits) -->
         <item>ar-IQ</item> <!-- Arabic (Iraq) -->
-        <item>ar-IQ-u-nu-latn</item> <!-- Arabic (Iraq,Western Digits) -->
+        <item>ar-IQ-u-nu-latn</item> <!-- Arabic (Iraq, Western Digits) -->
         <item>ar-JO</item> <!-- Arabic (Jordan) -->
-        <item>ar-JO-u-nu-latn</item> <!-- Arabic (Jordan,Western Digits) -->
+        <item>ar-JO-u-nu-latn</item> <!-- Arabic (Jordan, Western Digits) -->
         <item>ar-KM</item> <!-- Arabic (Comoros) -->
-        <item>ar-KM-u-nu-latn</item> <!-- Arabic (Comoros,Western Digits) -->
+        <item>ar-KM-u-nu-latn</item> <!-- Arabic (Comoros, Western Digits) -->
         <item>ar-KW</item> <!-- Arabic (Kuwait) -->
-        <item>ar-KW-u-nu-latn</item> <!-- Arabic (Kuwait,Western Digits) -->
+        <item>ar-KW-u-nu-latn</item> <!-- Arabic (Kuwait, Western Digits) -->
         <item>ar-LB</item> <!-- Arabic (Lebanon) -->
-        <item>ar-LB-u-nu-latn</item> <!-- Arabic (Lebanon,Western Digits) -->
+        <item>ar-LB-u-nu-latn</item> <!-- Arabic (Lebanon, Western Digits) -->
         <item>ar-LY</item> <!-- Arabic (Libya) -->
-        <item>ar-LY-u-nu-arab</item> <!-- Arabic (Libya,Arabic-Indic Digits) -->
+        <item>ar-LY-u-nu-arab</item> <!-- Arabic (Libya, Arabic-Indic Digits) -->
         <item>ar-MA</item> <!-- Arabic (Morocco) -->
-        <item>ar-MA-u-nu-arab</item> <!-- Arabic (Morocco,Arabic-Indic Digits) -->
+        <item>ar-MA-u-nu-arab</item> <!-- Arabic (Morocco, Arabic-Indic Digits) -->
         <item>ar-MR</item> <!-- Arabic (Mauritania) -->
-        <item>ar-MR-u-nu-latn</item> <!-- Arabic (Mauritania,Western Digits) -->
+        <item>ar-MR-u-nu-latn</item> <!-- Arabic (Mauritania, Western Digits) -->
         <item>ar-OM</item> <!-- Arabic (Oman) -->
-        <item>ar-OM-u-nu-latn</item> <!-- Arabic (Oman,Western Digits) -->
+        <item>ar-OM-u-nu-latn</item> <!-- Arabic (Oman, Western Digits) -->
         <item>ar-PS</item> <!-- Arabic (Palestine) -->
-        <item>ar-PS-u-nu-latn</item> <!-- Arabic (Palestine,Western Digits) -->
+        <item>ar-PS-u-nu-latn</item> <!-- Arabic (Palestine, Western Digits) -->
         <item>ar-QA</item> <!-- Arabic (Qatar) -->
-        <item>ar-QA-u-nu-latn</item> <!-- Arabic (Qatar,Western Digits) -->
+        <item>ar-QA-u-nu-latn</item> <!-- Arabic (Qatar, Western Digits) -->
         <item>ar-SA</item> <!-- Arabic (Saudi Arabia) -->
-        <item>ar-SA-u-nu-latn</item> <!-- Arabic (Saudi Arabia,Western Digits) -->
+        <item>ar-SA-u-nu-latn</item> <!-- Arabic (Saudi Arabia, Western Digits) -->
         <item>ar-SD</item> <!-- Arabic (Sudan) -->
-        <item>ar-SD-u-nu-latn</item> <!-- Arabic (Sudan,Western Digits) -->
+        <item>ar-SD-u-nu-latn</item> <!-- Arabic (Sudan, Western Digits) -->
         <item>ar-SO</item> <!-- Arabic (Somalia) -->
-        <item>ar-SO-u-nu-latn</item> <!-- Arabic (Somalia,Western Digits) -->
+        <item>ar-SO-u-nu-latn</item> <!-- Arabic (Somalia, Western Digits) -->
         <item>ar-SS</item> <!-- Arabic (South Sudan) -->
-        <item>ar-SS-u-nu-latn</item> <!-- Arabic (South Sudan,Western Digits) -->
+        <item>ar-SS-u-nu-latn</item> <!-- Arabic (South Sudan, Western Digits) -->
         <item>ar-SY</item> <!-- Arabic (Syria) -->
-        <item>ar-SY-u-nu-latn</item> <!-- Arabic (Syria,Western Digits) -->
+        <item>ar-SY-u-nu-latn</item> <!-- Arabic (Syria, Western Digits) -->
         <item>ar-TD</item> <!-- Arabic (Chad) -->
-        <item>ar-TD-u-nu-latn</item> <!-- Arabic (Chad,Western Digits) -->
+        <item>ar-TD-u-nu-latn</item> <!-- Arabic (Chad, Western Digits) -->
         <item>ar-TN</item> <!-- Arabic (Tunisia) -->
-        <item>ar-TN-u-nu-arab</item> <!-- Arabic (Tunisia,Arabic-Indic Digits) -->
+        <item>ar-TN-u-nu-arab</item> <!-- Arabic (Tunisia, Arabic-Indic Digits) -->
         <item>ar-XB</item> <!-- Right-to-left pseudolocale -->
         <item>ar-YE</item> <!-- Arabic (Yemen) -->
-        <item>ar-YE-u-nu-latn</item> <!-- Arabic (Yemen,Western Digits) -->
+        <item>ar-YE-u-nu-latn</item> <!-- Arabic (Yemen, Western Digits) -->
         <item>as-IN</item> <!-- Assamese (India) -->
         <item>asa-TZ</item> <!-- Asu (Tanzania) -->
-        <item>az-Cyrl-AZ</item> <!-- Azerbaijani (Cyrillic,Azerbaijan) -->
-        <item>az-Latn-AZ</item> <!-- Azerbaijani (Latin,Azerbaijan) -->
+        <item>ast-ES</item> <!-- Asturian (Spain) -->
+        <item>az-Cyrl-AZ</item> <!-- Azerbaijani (Cyrillic, Azerbaijan) -->
+        <item>az-Latn-AZ</item> <!-- Azerbaijani (Latin, Azerbaijan) -->
         <item>bas-CM</item> <!-- Basaa (Cameroon) -->
         <item>be-BY</item> <!-- Belarusian (Belarus) -->
         <item>bem-ZM</item> <!-- Bemba (Zambia) -->
         <item>bez-TZ</item> <!-- Bena (Tanzania) -->
         <item>bg-BG</item> <!-- Bulgarian (Bulgaria) -->
         <item>bm-ML</item> <!-- Bambara (Mali) -->
-        <item>bn-BD</item> <!-- Bengali (Bangladesh) -->
-        <item>bn-BD-u-nu-latn</item> <!-- Bengali (Bangladesh,Western Digits) -->
-        <item>bn-IN</item> <!-- Bengali (India) -->
-        <item>bn-IN-u-nu-latn</item> <!-- Bengali (India,Western Digits) -->
+        <item>bn-BD</item> <!-- Bangla (Bangladesh) -->
+        <item>bn-BD-u-nu-latn</item> <!-- Bangla (Bangladesh, Western Digits) -->
+        <item>bn-IN</item> <!-- Bangla (India) -->
+        <item>bn-IN-u-nu-latn</item> <!-- Bangla (India, Western Digits) -->
         <item>bo-CN</item> <!-- Tibetan (China) -->
         <item>bo-IN</item> <!-- Tibetan (India) -->
         <item>br-FR</item> <!-- Breton (France) -->
         <item>brx-IN</item> <!-- Bodo (India) -->
-        <item>bs-Cyrl-BA</item> <!-- Bosnian (Cyrillic,Bosnia & Herzegovina) -->
-        <item>bs-Latn-BA</item> <!-- Bosnian (Latin,Bosnia & Herzegovina) -->
+        <item>bs-Cyrl-BA</item> <!-- Bosnian (Cyrillic, Bosnia & Herzegovina) -->
+        <item>bs-Latn-BA</item> <!-- Bosnian (Latin, Bosnia & Herzegovina) -->
         <item>ca-AD</item> <!-- Catalan (Andorra) -->
         <item>ca-ES</item> <!-- Catalan (Spain) -->
         <item>ca-FR</item> <!-- Catalan (France) -->
@@ -113,6 +114,7 @@
         <item>de-BE</item> <!-- German (Belgium) -->
         <item>de-CH</item> <!-- German (Switzerland) -->
         <item>de-DE</item> <!-- German (Germany) -->
+        <item>de-IT</item> <!-- German (Italy) -->
         <item>de-LI</item> <!-- German (Liechtenstein) -->
         <item>de-LU</item> <!-- German (Luxembourg) -->
         <item>dje-NE</item> <!-- Zarma (Niger) -->
@@ -230,6 +232,8 @@
         <item>en-ZW</item> <!-- English (Zimbabwe) -->
         <item>es-AR</item> <!-- Spanish (Argentina) -->
         <item>es-BO</item> <!-- Spanish (Bolivia) -->
+        <item>es-BR</item> <!-- Spanish (Brazil) -->
+        <item>es-BZ</item> <!-- Spanish (Belize) -->
         <item>es-CL</item> <!-- Spanish (Chile) -->
         <item>es-CO</item> <!-- Spanish (Colombia) -->
         <item>es-CR</item> <!-- Spanish (Costa Rica) -->
@@ -257,9 +261,9 @@
         <item>eu-ES</item> <!-- Basque (Spain) -->
         <item>ewo-CM</item> <!-- Ewondo (Cameroon) -->
         <item>fa-AF</item> <!-- Persian (Afghanistan) -->
-        <item>fa-AF-u-nu-latn</item> <!-- Persian (Afghanistan,Western Digits) -->
+        <item>fa-AF-u-nu-latn</item> <!-- Persian (Afghanistan, Western Digits) -->
         <item>fa-IR</item> <!-- Persian (Iran) -->
-        <item>fa-IR-u-nu-latn</item> <!-- Persian (Iran,Western Digits) -->
+        <item>fa-IR-u-nu-latn</item> <!-- Persian (Iran, Western Digits) -->
         <item>ff-CM</item> <!-- Fulah (Cameroon) -->
         <item>ff-GN</item> <!-- Fulah (Guinea) -->
         <item>ff-MR</item> <!-- Fulah (Mauritania) -->
@@ -274,9 +278,9 @@
         <item>fr-BJ</item> <!-- French (Benin) -->
         <item>fr-BL</item> <!-- French (St. Barthélemy) -->
         <item>fr-CA</item> <!-- French (Canada) -->
-        <item>fr-CD</item> <!-- French (Congo (DRC)) -->
+        <item>fr-CD</item> <!-- French (Congo - Kinshasa) -->
         <item>fr-CF</item> <!-- French (Central African Republic) -->
-        <item>fr-CG</item> <!-- French (Congo (Republic)) -->
+        <item>fr-CG</item> <!-- French (Congo - Brazzaville) -->
         <item>fr-CH</item> <!-- French (Switzerland) -->
         <item>fr-CI</item> <!-- French (Côte d’Ivoire) -->
         <item>fr-CM</item> <!-- French (Cameroon) -->
@@ -329,20 +333,20 @@
         <item>ha-NE</item> <!-- Hausa (Niger) -->
         <item>ha-NG</item> <!-- Hausa (Nigeria) -->
         <item>haw-US</item> <!-- Hawaiian (United States) -->
-        <item>iw-IL</item> <!-- Hebrew (Israel) -->
         <item>hi-IN</item> <!-- Hindi (India) -->
         <item>hr-BA</item> <!-- Croatian (Bosnia & Herzegovina) -->
         <item>hr-HR</item> <!-- Croatian (Croatia) -->
         <item>hsb-DE</item> <!-- Upper Sorbian (Germany) -->
         <item>hu-HU</item> <!-- Hungarian (Hungary) -->
         <item>hy-AM</item> <!-- Armenian (Armenia) -->
-        <item>in-ID</item> <!-- Indonesian (Indonesia) -->
         <item>ig-NG</item> <!-- Igbo (Nigeria) -->
         <item>ii-CN</item> <!-- Sichuan Yi (China) -->
+        <item>in-ID</item> <!-- Indonesian (Indonesia) -->
         <item>is-IS</item> <!-- Icelandic (Iceland) -->
         <item>it-CH</item> <!-- Italian (Switzerland) -->
         <item>it-IT</item> <!-- Italian (Italy) -->
         <item>it-SM</item> <!-- Italian (San Marino) -->
+        <item>iw-IL</item> <!-- Hebrew (Israel) -->
         <item>ja-JP</item> <!-- Japanese (Japan) -->
         <item>jgo-CM</item> <!-- Ngomba (Cameroon) -->
         <item>jmc-TZ</item> <!-- Machame (Tanzania) -->
@@ -372,12 +376,12 @@
         <item>lg-UG</item> <!-- Ganda (Uganda) -->
         <item>lkt-US</item> <!-- Lakota (United States) -->
         <item>ln-AO</item> <!-- Lingala (Angola) -->
-        <item>ln-CD</item> <!-- Lingala (Congo (DRC)) -->
+        <item>ln-CD</item> <!-- Lingala (Congo - Kinshasa) -->
         <item>ln-CF</item> <!-- Lingala (Central African Republic) -->
-        <item>ln-CG</item> <!-- Lingala (Congo (Republic)) -->
+        <item>ln-CG</item> <!-- Lingala (Congo - Brazzaville) -->
         <item>lo-LA</item> <!-- Lao (Laos) -->
         <item>lt-LT</item> <!-- Lithuanian (Lithuania) -->
-        <item>lu-CD</item> <!-- Luba-Katanga (Congo (DRC)) -->
+        <item>lu-CD</item> <!-- Luba-Katanga (Congo - Kinshasa) -->
         <item>luo-KE</item> <!-- Luo (Kenya) -->
         <item>luy-KE</item> <!-- Luyia (Kenya) -->
         <item>lv-LV</item> <!-- Latvian (Latvia) -->
@@ -418,11 +422,11 @@
         <item>nyn-UG</item> <!-- Nyankole (Uganda) -->
         <item>om-ET</item> <!-- Oromo (Ethiopia) -->
         <item>om-KE</item> <!-- Oromo (Kenya) -->
-        <item>or-IN</item> <!-- Oriya (India) -->
+        <item>or-IN</item> <!-- Odia (India) -->
         <item>os-GE</item> <!-- Ossetic (Georgia) -->
         <item>os-RU</item> <!-- Ossetic (Russia) -->
-        <item>pa-Arab-PK</item> <!-- Punjabi (Arabic,Pakistan) -->
-        <item>pa-Guru-IN</item> <!-- Punjabi (Gurmukhi,India) -->
+        <item>pa-Arab-PK</item> <!-- Punjabi (Arabic, Pakistan) -->
+        <item>pa-Guru-IN</item> <!-- Punjabi (Gurmukhi, India) -->
         <item>pl-PL</item> <!-- Polish (Poland) -->
         <item>ps-AF</item> <!-- Pashto (Afghanistan) -->
         <item>pt-AO</item> <!-- Portuguese (Angola) -->
@@ -471,18 +475,18 @@
         <item>sq-AL</item> <!-- Albanian (Albania) -->
         <item>sq-MK</item> <!-- Albanian (Macedonia (FYROM)) -->
         <item>sq-XK</item> <!-- Albanian (Kosovo) -->
-        <item>sr-Cyrl-BA</item> <!-- Serbian (Cyrillic,Bosnia & Herzegovina) -->
-        <item>sr-Cyrl-ME</item> <!-- Serbian (Cyrillic,Montenegro) -->
-        <item>sr-Cyrl-RS</item> <!-- Serbian (Cyrillic,Serbia) -->
-        <item>sr-Cyrl-XK</item> <!-- Serbian (Cyrillic,Kosovo) -->
-        <item>sr-Latn-BA</item> <!-- Serbian (Latin,Bosnia & Herzegovina) -->
-        <item>sr-Latn-ME</item> <!-- Serbian (Latin,Montenegro) -->
-        <item>sr-Latn-RS</item> <!-- Serbian (Latin,Serbia) -->
-        <item>sr-Latn-XK</item> <!-- Serbian (Latin,Kosovo) -->
+        <item>sr-Cyrl-BA</item> <!-- Serbian (Cyrillic, Bosnia & Herzegovina) -->
+        <item>sr-Cyrl-ME</item> <!-- Serbian (Cyrillic, Montenegro) -->
+        <item>sr-Cyrl-RS</item> <!-- Serbian (Cyrillic, Serbia) -->
+        <item>sr-Cyrl-XK</item> <!-- Serbian (Cyrillic, Kosovo) -->
+        <item>sr-Latn-BA</item> <!-- Serbian (Latin, Bosnia & Herzegovina) -->
+        <item>sr-Latn-ME</item> <!-- Serbian (Latin, Montenegro) -->
+        <item>sr-Latn-RS</item> <!-- Serbian (Latin, Serbia) -->
+        <item>sr-Latn-XK</item> <!-- Serbian (Latin, Kosovo) -->
         <item>sv-AX</item> <!-- Swedish (Åland Islands) -->
         <item>sv-FI</item> <!-- Swedish (Finland) -->
         <item>sv-SE</item> <!-- Swedish (Sweden) -->
-        <item>sw-CD</item> <!-- Swahili (Congo (DRC)) -->
+        <item>sw-CD</item> <!-- Swahili (Congo - Kinshasa) -->
         <item>sw-KE</item> <!-- Swahili (Kenya) -->
         <item>sw-TZ</item> <!-- Swahili (Tanzania) -->
         <item>sw-UG</item> <!-- Swahili (Uganda) -->
@@ -502,12 +506,12 @@
         <item>ug-CN</item> <!-- Uyghur (China) -->
         <item>uk-UA</item> <!-- Ukrainian (Ukraine) -->
         <item>ur-IN</item> <!-- Urdu (India) -->
-        <item>ur-IN-u-nu-latn</item> <!-- Urdu (India,Western Digits) -->
+        <item>ur-IN-u-nu-latn</item> <!-- Urdu (India, Western Digits) -->
         <item>ur-PK</item> <!-- Urdu (Pakistan) -->
-        <item>ur-PK-u-nu-arabext</item> <!-- Urdu (Pakistan,Extended Arabic-Indic Digits) -->
-        <item>uz-Arab-AF</item> <!-- Uzbek (Arabic,Afghanistan) -->
-        <item>uz-Cyrl-UZ</item> <!-- Uzbek (Cyrillic,Uzbekistan) -->
-        <item>uz-Latn-UZ</item> <!-- Uzbek (Latin,Uzbekistan) -->
+        <item>ur-PK-u-nu-arabext</item> <!-- Urdu (Pakistan, Extended Arabic-Indic Digits) -->
+        <item>uz-Arab-AF</item> <!-- Uzbek (Arabic, Afghanistan) -->
+        <item>uz-Cyrl-UZ</item> <!-- Uzbek (Cyrillic, Uzbekistan) -->
+        <item>uz-Latn-UZ</item> <!-- Uzbek (Latin, Uzbekistan) -->
         <item>vi-VN</item> <!-- Vietnamese (Vietnam) -->
         <item>vun-TZ</item> <!-- Vunjo (Tanzania) -->
         <item>wae-CH</item> <!-- Walser (Switzerland) -->
@@ -515,15 +519,16 @@
         <item>yav-CM</item> <!-- Yangben (Cameroon) -->
         <item>yo-BJ</item> <!-- Yoruba (Benin) -->
         <item>yo-NG</item> <!-- Yoruba (Nigeria) -->
-        <item>yue-HK</item> <!-- Cantonese (Hong Kong) -->
+        <item>yue-Hans-CN</item> <!-- Cantonese (Simplified, China) -->
+        <item>yue-Hant-HK</item> <!-- Cantonese (Traditional, Hong Kong) -->
         <item>zgh-MA</item> <!-- Standard Moroccan Tamazight (Morocco) -->
-        <item>zh-Hans-CN</item> <!-- Chinese (Simplified Han,China) -->
-        <item>zh-Hans-HK</item> <!-- Chinese (Simplified Han,Hong Kong) -->
-        <item>zh-Hans-MO</item> <!-- Chinese (Simplified Han,Macau) -->
-        <item>zh-Hans-SG</item> <!-- Chinese (Simplified Han,Singapore) -->
-        <item>zh-Hant-HK</item> <!-- Chinese (Traditional Han,Hong Kong) -->
-        <item>zh-Hant-MO</item> <!-- Chinese (Traditional Han,Macau) -->
-        <item>zh-Hant-TW</item> <!-- Chinese (Traditional Han,Taiwan) -->
+        <item>zh-Hans-CN</item> <!-- Chinese (Simplified, China) -->
+        <item>zh-Hans-HK</item> <!-- Chinese (Simplified, Hong Kong) -->
+        <item>zh-Hans-MO</item> <!-- Chinese (Simplified, Macau) -->
+        <item>zh-Hans-SG</item> <!-- Chinese (Simplified, Singapore) -->
+        <item>zh-Hant-HK</item> <!-- Chinese (Traditional, Hong Kong) -->
+        <item>zh-Hant-MO</item> <!-- Chinese (Traditional, Macau) -->
+        <item>zh-Hant-TW</item> <!-- Chinese (Traditional, Taiwan) -->
         <item>zu-ZA</item> <!-- Zulu (South Africa) -->
     </string-array>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e1c5df3..73dae08 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2912,12 +2912,14 @@
         <public name="supportsAmbientMode" />
         <!-- @hide For use by platform and tools only. Developers should not specify this value. -->
         <public name="usesNonSdkApi" />
-        <public name="minimumUiTimeout" />
+        <public name="nonInteractiveUiTimeout" />
         <public name="isLightTheme" />
         <public name="isSplitRequired" />
         <public name="textLocale" />
         <public name="settingsSliceUri" />
         <public name="shell" />
+        <public name="interactiveUiTimeout" />
+        <public name="importantForContentCapture" />
     </public-group>
 
     <public-group type="drawable" first-id="0x010800b4">
@@ -2929,6 +2931,10 @@
     </public-group>
 
     <public-group type="id" first-id="0x01020046">
+      <public name="accessibilityActionPageUp" />
+      <public name="accessibilityActionPageDown" />
+      <public name="accessibilityActionPageLeft" />
+      <public name="accessibilityActionPageRight" />
     </public-group>
 
     <public-group type="string" first-id="0x0104001b">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8b7cafb..200c35d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -248,6 +248,10 @@
         <item>@string/wfcSpnFormat_spn_wifi</item>
         <item>@string/wfcSpnFormat_wifi_calling_bar_spn</item>
         <item>@string/wfcSpnFormat_spn_vowifi</item>
+        <item>@string/wfcSpnFormat_wifi_calling</item>
+        <item>@string/wfcSpnFormat_wifi</item>
+        <item>@string/wfcSpnFormat_wifi_calling_wo_hyphen</item>
+        <item>@string/wfcSpnFormat_vowifi</item>
     </string-array>
 
     <!-- Spn during Wi-Fi Calling: "<operator>" -->
@@ -264,6 +268,14 @@
     <string name="wfcSpnFormat_wifi_calling_bar_spn">WiFi Calling | <xliff:g id="spn" example="Operator">%s</xliff:g></string>
     <!-- Spn during Wi-Fi Calling: "<operator> VoWifi" -->
     <string name="wfcSpnFormat_spn_vowifi"><xliff:g id="spn" example="Operator">%s</xliff:g> VoWifi</string>
+    <!-- Spn during Wi-Fi Calling: "Wi-Fi Calling" -->
+    <string name="wfcSpnFormat_wifi_calling">Wi-Fi Calling</string>
+    <!-- Spn during Wi-Fi Calling: "Wi-Fi" -->
+    <string name="wfcSpnFormat_wifi">Wi-Fi</string>
+    <!-- Spn during Wi-Fi Calling: "WiFi Calling" (without hyphen) -->
+    <string name="wfcSpnFormat_wifi_calling_wo_hyphen">WiFi Calling</string>
+    <!-- Spn during Wi-Fi Calling: "VoWifi" -->
+    <string name="wfcSpnFormat_vowifi">VoWifi</string>
 
     <!-- WFC, summary for Disabled -->
     <string name="wifi_calling_off_summary">Off</string>
@@ -4820,6 +4832,9 @@
     <!-- Content description of the work profile icon in the notification. -->
     <string name="notification_work_profile_content_description">Work profile</string>
 
+    <!-- Content description of the alerting icon in the notification. [CHAR_LIMIT=NONE] -->
+    <string name="notification_alerted_content_description">Alerted</string>
+
     <!-- Content description of the expand button icon in the notification when collaped.-->
     <string name="expand_button_content_description_collapsed">Expand</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 670a4a2..626206b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -215,6 +215,7 @@
   <java-symbol type="id" name="pin_error_message" />
   <java-symbol type="id" name="timePickerLayout" />
   <java-symbol type="id" name="profile_badge" />
+  <java-symbol type="id" name="alerted_icon" />
   <java-symbol type="id" name="transitionPosition" />
   <java-symbol type="id" name="selection_start_handle" />
   <java-symbol type="id" name="selection_end_handle" />
@@ -1112,6 +1113,7 @@
   <java-symbol type="string" name="owner_name" />
   <java-symbol type="string" name="config_chooseAccountActivity" />
   <java-symbol type="string" name="config_chooseTypeAndAccountActivity" />
+  <java-symbol type="string" name="config_chooserActivity" />
   <java-symbol type="string" name="config_customResolverActivity" />
   <java-symbol type="string" name="config_appsAuthorizedForSharedAccounts" />
   <java-symbol type="string" name="error_message_title" />
@@ -2806,6 +2808,8 @@
   <java-symbol type="string" name="status_bar_mobile" />
   <java-symbol type="string" name="status_bar_ethernet" />
   <java-symbol type="string" name="status_bar_vpn" />
+  <java-symbol type="string" name="status_bar_microphone" />
+  <java-symbol type="string" name="status_bar_camera" />
 
   <!-- Locale picker -->
   <java-symbol type="id" name="locale_search_menu" />
@@ -3434,6 +3438,7 @@
 
   <java-symbol type="integer" name="config_lowBatteryAutoTriggerDefaultLevel" />
   <java-symbol type="bool" name="config_batterySaverStickyBehaviourDisabled" />
+  <java-symbol type="integer" name="config_dynamicPowerSavingsDefaultDisableThreshold" />
 
   <!-- For car devices -->
   <java-symbol type="string" name="car_loading_profile" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 3385527..fa009bd 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1475,6 +1475,8 @@
 
         <!-- Toolbar attributes -->
         <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+        <item name="listDivider">@color/list_divider_color_light</item>
     </style>
 
     <!-- @hide DeviceDefault theme for a window that should use Settings theme colors
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 7b3d940..7163769 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -187,7 +187,7 @@
     <shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288" />
 
     <!-- The Netherlands, 4 digits, known premium codes listed, plus EU -->
-    <shortcode country="nl" pattern="\\d{4}" premium="4466|5040" free="116\\d{3}|2223|6225|2223" />
+    <shortcode country="nl" pattern="\\d{4}" premium="4466|5040" free="116\\d{3}|2223|6225|2223|1662" />
 
     <!-- Nigeria -->
     <shortcode country="ng" pattern="\\d{1,5}" free="2441" />
diff --git a/core/tests/coretests/src/android/app/assist/AssistStructureTest.java b/core/tests/coretests/src/android/app/assist/AssistStructureTest.java
index fe51a39..689e683 100644
--- a/core/tests/coretests/src/android/app/assist/AssistStructureTest.java
+++ b/core/tests/coretests/src/android/app/assist/AssistStructureTest.java
@@ -133,8 +133,6 @@
     private void assertStructureWithManySmallViews(AssistStructure structure, int expectedSize) {
         int i = 0;
         try {
-            assertPackageName(structure);
-
             assertThat(structure.getWindowNodeCount()).isEqualTo(1);
 
             ViewNode rootView = structure.getWindowNodeAt(0).getRootViewNode();
@@ -188,8 +186,6 @@
 
     private void assertStructureWithOneBigView(AssistStructure structure) {
         try {
-            assertPackageName(structure);
-
             assertThat(structure.getWindowNodeCount()).isEqualTo(1);
 
             ViewNode rootView = structure.getWindowNodeAt(0).getRootViewNode();
@@ -275,12 +271,6 @@
         assertThat(hint.charAt(BIG_VIEW_SIZE - 1)).isEqualTo(BIG_VIEW_CHAR);
     }
 
-    private void assertPackageName(AssistStructure structure) {
-        assertThat(structure.getActivityComponent()).isEqualTo(
-                new ComponentName("com.android.frameworks.coretests",
-                        "android.app.assist.EmptyLayoutActivity"));
-    }
-
     private AssistStructure cloneThroughParcel(AssistStructure structure) {
         Parcel parcel = Parcel.obtain();
 
diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
index c6d077d..1f047f9e 100644
--- a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
+++ b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java
@@ -16,8 +16,19 @@
 
 package android.app.usage;
 
-import static com.google.common.truth.Truth.assertThat;
+import static android.app.usage.UsageEvents.Event.CONTINUE_PREVIOUS_DAY;
+import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
+import static android.app.usage.UsageEvents.Event.END_OF_DAY;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
+import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
+import static android.app.usage.UsageEvents.Event.MOVE_TO_BACKGROUND;
+import static android.app.usage.UsageEvents.Event.MOVE_TO_FOREGROUND;
+import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import android.os.Parcel;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
@@ -46,7 +57,7 @@
 
         left.add(right);
 
-        assertThat(left.getFirstTimeStamp()).isEqualTo(99999);
+        assertEquals(left.getFirstTimeStamp(), 99999);
     }
 
     @Test
@@ -58,7 +69,7 @@
 
         left.add(right);
 
-        assertThat(left.getLastTimeStamp()).isEqualTo(100001);
+        assertEquals(left.getLastTimeStamp(), 100001);
     }
 
     @Test
@@ -72,7 +83,7 @@
 
         left.add(right);
 
-        assertThat(left.getLastTimeUsed()).isEqualTo(200001);
+        assertEquals(left.getLastTimeUsed(), 200001);
     }
 
     @Test
@@ -86,7 +97,7 @@
 
         left.add(right);
 
-        assertThat(left.getLastTimeUsed()).isEqualTo(200000);
+        assertEquals(left.getLastTimeUsed(), 200000);
     }
 
     @Test
@@ -100,6 +111,373 @@
 
         left.add(right);
 
-        assertThat(left.getTotalTimeInForeground()).isEqualTo(11);
+        assertEquals(left.getTotalTimeInForeground(), 11);
+    }
+
+    @Test
+    public void testParcelable() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+        left.mTotalTimeInForeground = 10;
+
+        left.mLastForegroundActivityEventMap.put("com.test.activity1", MOVE_TO_FOREGROUND);
+        left.mLastForegroundActivityEventMap.put("com.test.activity2", MOVE_TO_FOREGROUND);
+        left.mLastForegroundServiceEventMap.put("com.test.service1", FOREGROUND_SERVICE_START);
+        left.mLastForegroundServiceEventMap.put("com.test.service2", FOREGROUND_SERVICE_START);
+
+        Parcel p = Parcel.obtain();
+        left.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        right = UsageStats.CREATOR.createFromParcel(p);
+        compareUsageStats(left, right);
+    }
+
+    @Test
+    public void testForegroundActivity() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 200000, MOVE_TO_FOREGROUND);
+        assertEquals(left.mLastTimeUsed, 200000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mLaunchCount, 1);
+
+        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertFalse(left.mLastForegroundActivityEventMap.containsKey("com.test.activity1"));
+        assertEquals(left.mTotalTimeInForeground, 350000 - 200000);
+    }
+
+    @Test
+    public void testEvent_CONTINUE_PREVIOUS_DAY() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 350000 - 100000);
+    }
+
+    @Test
+    public void testEvent_END_OF_DAY() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update(null, 350000, END_OF_DAY);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(END_OF_DAY));
+        assertEquals(left.mTotalTimeInForeground, 350000 - 100000);
+    }
+
+    @Test
+    public void testForegroundActivityEventSequence() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 250000 /*350000 - 100000*/);
+
+        left.update("com.test.activity1", 450000, MOVE_TO_FOREGROUND);
+        assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mTotalTimeInForeground, 250000);
+
+        left.update("com.test.activity1", 500000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 500000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 250000 + 50000 /*500000 - 450000*/);
+    }
+
+    @Test
+    public void testForegroundActivityEventOutOfSequence() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.activity1", 150000, MOVE_TO_FOREGROUND);
+        assertEquals(left.mLastTimeUsed, 150000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mLaunchCount, 1);
+        assertEquals(left.mTotalTimeInForeground, 50000 /*150000 - 100000*/);
+
+        left.update("com.test.activity1", 200000, MOVE_TO_FOREGROUND);
+        assertEquals(left.mLastTimeUsed, 200000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mLaunchCount, 2);
+        assertEquals(left.mTotalTimeInForeground, 100000);
+
+        left.update("com.test.activity1", 250000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 250000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 150000);
+
+        left.update("com.test.activity1", 300000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 250000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 150000);
+
+        left.update("com.test.activity1", 350000, MOVE_TO_FOREGROUND);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(MOVE_TO_FOREGROUND));
+        assertEquals(left.mTotalTimeInForeground, 150000);
+
+        left.update("com.test.activity1", 400000, END_OF_DAY);
+        assertEquals(left.mLastTimeUsed, 400000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(END_OF_DAY));
+        assertEquals(left.mTotalTimeInForeground, 200000);
+    }
+
+    @Test
+    public void testTwoActivityEventSequence() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        left.update("com.test.activity2", 100000, CONTINUE_PREVIOUS_DAY);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 250000 /*350000 - 100000*/);
+
+        left.update("com.test.activity2", 450000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"), null);
+        assertEquals(left.mTotalTimeInForeground, 250000 + 100000 /*450000 - 350000*/);
+
+        left.update(null, 500000, END_OF_DAY);
+        assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mTotalTimeInForeground, 350000);
+    }
+
+    @Test
+    public void testForegroundService() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.service1", 200000, FOREGROUND_SERVICE_START);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 200000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(FOREGROUND_SERVICE_START));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 350000 - 200000);
+    }
+
+    @Test
+    public void testEvent_CONTINUING_FOREGROUND_SERVICE() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.service1", 100000, CONTINUING_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 350000 - 100000);
+    }
+
+    @Test
+    public void testEvent_ROLLOVER_FOREGROUND_SERVICE() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.service1", 100000,
+                CONTINUING_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update(null, 350000, ROLLOVER_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(ROLLOVER_FOREGROUND_SERVICE));
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 350000 - 100000);
+    }
+
+    @Test
+    public void testForegroundServiceEventSequence() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.service1", 100000,
+                CONTINUING_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 /*350000 - 100000*/);
+
+        left.update("com.test.service1", 450000, FOREGROUND_SERVICE_START);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 450000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(FOREGROUND_SERVICE_START));
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 250000);
+
+        left.update("com.test.service1", 500000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 500000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 + 50000 /*500000 - 450000*/);
+    }
+
+    @Test
+    public void testTwoServiceEventSequence() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.service1", 100000,
+                CONTINUING_FOREGROUND_SERVICE);
+        left.update("com.test.service2", 100000,
+                CONTINUING_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.service1", 350000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 350000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 /*350000 - 100000*/);
+
+        left.update("com.test.service2", 450000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 450000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 250000 + 100000 /*450000 - 350000*/);
+
+        left.update(null, 500000, ROLLOVER_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 450000);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 350000);
+    }
+
+    @Test
+    public void testTwoActivityAndTwoServiceEventSequence() {
+        left.mPackageName = "com.test";
+        left.mBeginTimeStamp = 100000;
+
+        left.update("com.test.activity1", 100000, CONTINUE_PREVIOUS_DAY);
+        left.update("com.test.activity2", 100000, CONTINUE_PREVIOUS_DAY);
+        left.update("com.test.service1", 100000,
+                CONTINUING_FOREGROUND_SERVICE);
+        left.update("com.test.service2", 100000,
+                CONTINUING_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeUsed, 100000);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 100000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"),
+                new Integer(CONTINUE_PREVIOUS_DAY));
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"),
+                new Integer(CONTINUING_FOREGROUND_SERVICE));
+        assertEquals(left.mLaunchCount, 0);
+
+        left.update("com.test.activity1", 350000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 350000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity1"), null);
+        assertEquals(left.mTotalTimeInForeground, 250000 /*350000 - 100000*/);
+
+        left.update("com.test.service1", 400000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 400000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service1"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 300000 /*400000 - 100000*/);
+
+        left.update("com.test.activity2", 450000, MOVE_TO_BACKGROUND);
+        assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mLastForegroundActivityEventMap.get("com.test.activity2"), null);
+        assertEquals(left.mTotalTimeInForeground, 250000 + 100000 /*450000 - 350000*/);
+
+        left.update("com.test.service2", 500000, FOREGROUND_SERVICE_STOP);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 500000);
+        assertEquals(left.mLastForegroundServiceEventMap.get("com.test.service2"), null);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 300000 + 100000 /*500000 - 400000*/);
+
+
+        left.update(null, 550000, END_OF_DAY);
+        assertEquals(left.mLastTimeUsed, 450000);
+        assertEquals(left.mTotalTimeInForeground, 350000);
+        left.update(null, 550000, ROLLOVER_FOREGROUND_SERVICE);
+        assertEquals(left.mLastTimeForegroundServiceUsed, 500000);
+        assertEquals(left.mTotalTimeForegroundServiceUsed, 400000);
+    }
+
+    void compareUsageStats(UsageStats us1, UsageStats us2) {
+        assertEquals(us1.mPackageName, us2.mPackageName);
+        assertEquals(us1.mBeginTimeStamp, us2.mBeginTimeStamp);
+        assertEquals(us1.mLastTimeUsed, us2.mLastTimeUsed);
+        assertEquals(us1.mLastTimeForegroundServiceUsed, us2.mLastTimeForegroundServiceUsed);
+        assertEquals(us1.mTotalTimeInForeground, us2.mTotalTimeInForeground);
+        assertEquals(us1.mTotalTimeForegroundServiceUsed, us2.mTotalTimeForegroundServiceUsed);
+        assertEquals(us1.mAppLaunchCount, us2.mAppLaunchCount);
+        assertEquals(us1.mLastForegroundActivityEventMap.size(),
+                us2.mLastForegroundActivityEventMap.size());
+        for (int i = 0; i < us1.mLastForegroundActivityEventMap.size(); i++) {
+            assertEquals(us1.mLastForegroundActivityEventMap.keyAt(i),
+                    us2.mLastForegroundActivityEventMap.keyAt(i));
+            assertEquals(us1.mLastForegroundActivityEventMap.valueAt(i),
+                    us2.mLastForegroundActivityEventMap.valueAt(i));
+        }
+        assertEquals(us1.mLastForegroundServiceEventMap.size(),
+                us2.mLastForegroundServiceEventMap.size());
+        for (int i = 0; i < us1.mLastForegroundServiceEventMap.size(); i++) {
+            assertEquals(us1.mLastForegroundServiceEventMap.keyAt(i),
+                    us2.mLastForegroundServiceEventMap.keyAt(i));
+            assertEquals(us1.mLastForegroundServiceEventMap.valueAt(i),
+                    us2.mLastForegroundServiceEventMap.valueAt(i));
+        }
+        assertEquals(us1.mChooserCounts, us2.mChooserCounts);
     }
 }
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 4980210..002b6a8 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -124,6 +124,7 @@
                     Settings.Global.AUTOFILL_LOGGING_LEVEL,
                     Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
                     Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
+                    Settings.Global.AUTOMATIC_POWER_SAVER_MODE,
                     Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
                     Settings.Global.BATTERY_DISCHARGE_THRESHOLD,
                     Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS,
@@ -197,6 +198,7 @@
                     Settings.Global.DESK_DOCK_SOUND,
                     Settings.Global.DESK_UNDOCK_SOUND,
                     Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT,
+                    Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS,
                     Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES,
                     Settings.Global.DEVELOPMENT_FORCE_RTL,
                     Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
@@ -234,6 +236,8 @@
                     Settings.Global.ENABLE_DELETION_HELPER_NO_THRESHOLD_TOGGLE,
                     Settings.Global.ENABLE_DISKSTATS_LOGGING,
                     Settings.Global.ENABLE_EPHEMERAL_FEATURE,
+                    Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
+                    Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
                     Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
                     Settings.Global.ENHANCED_4G_MODE_ENABLED,
                     Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
@@ -260,8 +264,7 @@
                     Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
                     Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
                     Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE,
-                    Settings.Global.HIDDEN_API_POLICY_P_APPS,
-                    Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS,
+                    Settings.Global.HIDDEN_API_POLICY,
                     Settings.Global.HIDE_ERROR_DIALOGS,
                     Settings.Global.HTTP_PROXY,
                     HYBRID_SYSUI_BATTERY_WARNING_FLAGS,
@@ -370,6 +373,7 @@
                     Settings.Global.PRIVATE_DNS_DEFAULT_MODE,
                     Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_CHECK_ENABLED,
                     Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_TARGET_Q_BEHAVIOR_ENABLED,
+                    Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_3P_CHECK_RELAXED,
                     Settings.Global.PROVISIONING_APN_ALARM_DELAY_IN_MS,
                     Settings.Global.RADIO_BLUETOOTH,
                     Settings.Global.RADIO_CELL,
@@ -393,7 +397,9 @@
                     Settings.Global.SETTINGS_USE_PSD_API,
                     Settings.Global.SHORTCUT_MANAGER_CONSTANTS,
                     Settings.Global.SHOW_FIRST_CRASH_DIALOG,
+                    Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED,
                     Settings.Global.SHOW_MUTE_IN_CRASH_DIALOG,
+                    Settings.Global.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED,
                     Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
                     Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG,
                     Settings.Global.SHOW_TEMPERATURE_WARNING,
@@ -453,6 +459,7 @@
                     Settings.Global.GPU_DEBUG_LAYERS,
                     Settings.Global.GPU_DEBUG_LAYERS_GLES,
                     Settings.Global.ANGLE_ENABLED_APP,
+                    Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP,
                     Settings.Global.GPU_DEBUG_LAYER_APP,
                     Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
                     Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT,
@@ -487,6 +494,7 @@
                     Settings.Global.WIFI_IS_UNUSABLE_EVENT_METRICS_ENABLED,
                     Settings.Global.WIFI_LINK_SPEED_METRICS_ENABLED,
                     Settings.Global.WIFI_PNO_FREQUENCY_CULLING_ENABLED,
+                    Settings.Global.WIFI_PNO_RECENCY_SORTING_ENABLED,
                     Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
                     Settings.Global.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS,
                     Settings.Global.WIFI_NETWORK_SHOW_RSSI,
@@ -494,6 +502,7 @@
                     Settings.Global.WIFI_NUM_OPEN_NETWORKS_KEPT,
                     Settings.Global.WIFI_ON,
                     Settings.Global.WIFI_P2P_DEVICE_NAME,
+                    Settings.Global.WIFI_P2P_PENDING_FACTORY_RESET,
                     Settings.Global.WIFI_REENABLE_DELAY_MS,
                     Settings.Global.WIFI_RTT_BACKGROUND_EXEC_GAP_MS,
                     Settings.Global.WIFI_SAVED_STATE,
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index c8e46fc..ca6d6cf 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertThat;
 
 import android.content.Context;
+import android.graphics.Insets;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.InstrumentationRegistry;
@@ -57,9 +58,8 @@
         mViewRootImpl.getAttachInfo().getStableInsets().set(-10, -20, -30 , -40);
         final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
 
-        assertThat(insets.getSystemWindowInsets(), equalTo(new Rect()));
-        assertThat(new Rect(insets.getStableInsetLeft(), insets.getStableInsetTop(),
-                insets.getStableInsetRight(), insets.getStableInsetBottom()), equalTo(new Rect()));
+        assertThat(insets.getSystemWindowInsets(), equalTo(Insets.NONE));
+        assertThat(insets.getStableInsets(), equalTo(Insets.NONE));
     }
 
     @Test
@@ -68,10 +68,8 @@
         mViewRootImpl.getAttachInfo().getStableInsets().set(10, -20, 30 , -40);
         final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
 
-        assertThat(insets.getSystemWindowInsets(), equalTo(new Rect(0, 20, 0, 40)));
-        assertThat(new Rect(insets.getStableInsetLeft(), insets.getStableInsetTop(),
-                insets.getStableInsetRight(), insets.getStableInsetBottom()),
-                equalTo(new Rect(10, 0, 30, 0)));
+        assertThat(insets.getSystemWindowInsets(), equalTo(Insets.of(0, 20, 0, 40)));
+        assertThat(insets.getStableInsets(), equalTo(Insets.of(10, 0, 30, 0)));
     }
 
     @Test
@@ -80,10 +78,8 @@
         mViewRootImpl.getAttachInfo().getStableInsets().set(10, 20, 30 , 40);
         final WindowInsets insets = mViewRootImpl.getWindowInsets(true /* forceConstruct */);
 
-        assertThat(insets.getSystemWindowInsets(), equalTo(new Rect(10, 20, 30, 40)));
-        assertThat(new Rect(insets.getStableInsetLeft(), insets.getStableInsetTop(),
-                insets.getStableInsetRight(), insets.getStableInsetBottom()),
-                equalTo(new Rect(10, 20, 30, 40)));
+        assertThat(insets.getSystemWindowInsets(), equalTo(Insets.of(10, 20, 30, 40)));
+        assertThat(insets.getStableInsets(), equalTo(Insets.of(10, 20, 30, 40)));
     }
 
     private static class ViewRootImplAccessor {
diff --git a/core/tests/coretests/src/android/view/WindowInsetsTest.java b/core/tests/coretests/src/android/view/WindowInsetsTest.java
new file mode 100644
index 0000000..1c2df2c
--- /dev/null
+++ b/core/tests/coretests/src/android/view/WindowInsetsTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class WindowInsetsTest {
+
+    @Test
+    public void systemWindowInsets_afterConsuming_isConsumed() {
+        assertTrue(new WindowInsets(new Rect(1, 2, 3, 4), null, null, false, false, null)
+                .consumeSystemWindowInsets().isConsumed());
+    }
+
+    @Test
+    public void multiNullConstructor_isConsumed() {
+        assertTrue(new WindowInsets(null, null, null, false, false, null).isConsumed());
+    }
+
+    @Test
+    public void singleNullConstructor_isConsumed() {
+        assertTrue(new WindowInsets((Rect) null).isConsumed());
+    }
+
+}
diff --git a/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java
index 51e5aec..88d162b 100644
--- a/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java
@@ -43,7 +43,7 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class ModelFileManagerTest {
-
+    private static final Locale DEFAULT_LOCALE = Locale.forLanguageTag("en-US");
     @Mock
     private Supplier<List<ModelFileManager.ModelFile>> mModelFileSupplier;
     private ModelFileManager.ModelFileSupplierImpl mModelFileSupplierImpl;
@@ -71,6 +71,8 @@
 
         mRootTestDir.mkdirs();
         mFactoryModelDir.mkdirs();
+
+        Locale.setDefault(DEFAULT_LOCALE);
     }
 
     @After
@@ -134,7 +136,7 @@
     }
 
     @Test
-    public void findBestModel_useIndependentWhenNoLanguageModelMatch() {
+    public void findBestModel_noMatchedLanguageModel() {
         Locale locale = Locale.forLanguageTag("ja");
         ModelFileManager.ModelFile languageIndependentModelFile =
                 new ModelFileManager.ModelFile(
@@ -157,6 +159,28 @@
     }
 
     @Test
+    public void findBestModel_noMatchedLanguageModel_defaultLocaleModelExists() {
+        ModelFileManager.ModelFile languageIndependentModelFile =
+                new ModelFileManager.ModelFile(
+                        new File("/path/a"), 1,
+                        Collections.emptyList(), true);
+
+        ModelFileManager.ModelFile languageDependentModelFile =
+                new ModelFileManager.ModelFile(
+                        new File("/path/b"), 1,
+                        Collections.singletonList(DEFAULT_LOCALE), false);
+
+        when(mModelFileSupplier.get())
+                .thenReturn(
+                        Arrays.asList(languageIndependentModelFile, languageDependentModelFile));
+
+        ModelFileManager.ModelFile bestModelFile =
+                mModelFileManager.findBestModelFile(
+                        LocaleList.forLanguageTags("zh-hk"));
+        assertThat(bestModelFile).isEqualTo(languageIndependentModelFile);
+    }
+
+    @Test
     public void findBestModel_languageIsMoreImportantThanVersion() {
         ModelFileManager.ModelFile matchButOlderModel =
                 new ModelFileManager.ModelFile(
@@ -179,6 +203,28 @@
     }
 
     @Test
+    public void findBestModel_languageIsMoreImportantThanVersion_bestModelComesFirst() {
+        ModelFileManager.ModelFile matchLocaleModel =
+                new ModelFileManager.ModelFile(
+                        new File("/path/b"), 1,
+                        Collections.singletonList(Locale.forLanguageTag("ja")), false);
+
+        ModelFileManager.ModelFile languageIndependentModel =
+                new ModelFileManager.ModelFile(
+                        new File("/path/a"), 2,
+                        Collections.emptyList(), true);
+        when(mModelFileSupplier.get())
+                .thenReturn(
+                        Arrays.asList(matchLocaleModel, languageIndependentModel));
+
+        ModelFileManager.ModelFile bestModelFile =
+                mModelFileManager.findBestModelFile(
+                        LocaleList.forLanguageTags("ja"));
+
+        assertThat(bestModelFile).isEqualTo(matchLocaleModel);
+    }
+
+    @Test
     public void modelFileEquals() {
         ModelFileManager.ModelFile modelA =
                 new ModelFileManager.ModelFile(
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
index 8646c68..3a33d57 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -19,6 +19,7 @@
 import static org.hamcrest.CoreMatchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
@@ -325,6 +326,33 @@
     }
 
     @Test
+    public void testSuggestConversationActions_textReplyOnly_maxThree() {
+        if (isTextClassifierDisabled()) return;
+        ConversationActions.Message message =
+                new ConversationActions.Message.Builder().setText("Hello").build();
+        ConversationActions.TypeConfig typeConfig =
+                new ConversationActions.TypeConfig.Builder().includeTypesFromTextClassifier(false)
+                        .setIncludedTypes(
+                                Collections.singletonList(ConversationActions.TYPE_TEXT_REPLY))
+                        .build();
+        ConversationActions.Request request =
+                new ConversationActions.Request.Builder(Collections.singletonList(message))
+                        .setMaxSuggestions(1)
+                        .setTypeConfig(typeConfig)
+                        .build();
+
+        ConversationActions conversationActions = mClassifier.suggestConversationActions(request);
+        assertTrue(conversationActions.getConversationActions().size() <= 1);
+        for (ConversationActions.ConversationAction conversationAction :
+                conversationActions.getConversationActions()) {
+            assertEquals(conversationAction.getType(), ConversationActions.TYPE_TEXT_REPLY);
+            assertNotNull(conversationAction.getTextReply());
+            assertTrue(conversationAction.getConfidenceScore() > 0);
+            assertTrue(conversationAction.getConfidenceScore() <= 1);
+        }
+    }
+
+    @Test
     public void testSetTextClassifier() {
         TextClassifier classifier = mock(TextClassifier.class);
         mTcm.setTextClassifier(classifier);
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
index fff723f..f6ec0e6 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
@@ -38,6 +39,12 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TextLinksTest {
+    private static final String BUNDLE_KEY = "key";
+    private static final String BUNDLE_VALUE = "value";
+    private static final Bundle BUNDLE = new Bundle();
+    static {
+        BUNDLE.putString(BUNDLE_KEY, BUNDLE_VALUE);
+    }
 
     private Map<String, Float> getEntityScores(float address, float phone, float other) {
         final Map<String, Float> result = new ArrayMap<>();
@@ -59,6 +66,7 @@
         final TextLinks reference = new TextLinks.Builder(fullText)
                 .addLink(0, 4, getEntityScores(0.f, 0.f, 1.f))
                 .addLink(5, 12, getEntityScores(.8f, .1f, .5f))
+                .setExtras(BUNDLE)
                 .build();
 
         // Parcel and unparcel.
@@ -83,6 +91,7 @@
         assertEquals(.8f, resultList.get(1).getConfidenceScore(TextClassifier.TYPE_ADDRESS), 1e-7f);
         assertEquals(.5f, resultList.get(1).getConfidenceScore(TextClassifier.TYPE_OTHER), 1e-7f);
         assertEquals(.1f, resultList.get(1).getConfidenceScore(TextClassifier.TYPE_PHONE), 1e-7f);
+        assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
     }
 
     @Test
@@ -94,6 +103,7 @@
         final TextLinks.Request reference = new TextLinks.Request.Builder("text")
                 .setDefaultLocales(new LocaleList(Locale.US, Locale.GERMANY))
                 .setEntityConfig(entityConfig)
+                .setExtras(BUNDLE)
                 .build();
 
         // Parcel and unparcel.
@@ -108,5 +118,6 @@
                 result.getEntityConfig().getHints().toArray());
         assertEquals(new HashSet<String>(Arrays.asList("a", "c")),
                 result.getEntityConfig().resolveEntityListModifications(Collections.emptyList()));
+        assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
     }
 }
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
index 4855dad..7ea5108b 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextSelectionTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
@@ -31,6 +32,12 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TextSelectionTest {
+    private static final String BUNDLE_KEY = "key";
+    private static final String BUNDLE_VALUE = "value";
+    private static final Bundle BUNDLE = new Bundle();
+    static {
+        BUNDLE.putString(BUNDLE_KEY, BUNDLE_VALUE);
+    }
 
     @Test
     public void testParcel() {
@@ -42,6 +49,7 @@
                 .setEntityType(TextClassifier.TYPE_PHONE, 0.7f)
                 .setEntityType(TextClassifier.TYPE_URL, 0.1f)
                 .setId(id)
+                .setExtras(BUNDLE)
                 .build();
 
         // Parcel and unparcel
@@ -61,6 +69,7 @@
         assertEquals(0.7f, result.getConfidenceScore(TextClassifier.TYPE_PHONE), 1e-7f);
         assertEquals(0.3f, result.getConfidenceScore(TextClassifier.TYPE_ADDRESS), 1e-7f);
         assertEquals(0.1f, result.getConfidenceScore(TextClassifier.TYPE_URL), 1e-7f);
+        assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
     }
 
     @Test
@@ -69,6 +78,7 @@
         final TextSelection.Request reference =
                 new TextSelection.Request.Builder(text, 0, text.length())
                         .setDefaultLocales(new LocaleList(Locale.US, Locale.GERMANY))
+                        .setExtras(BUNDLE)
                         .build();
 
         // Parcel and unparcel.
@@ -81,5 +91,6 @@
         assertEquals(0, result.getStartIndex());
         assertEquals(text.length(), result.getEndIndex());
         assertEquals("en-US,de-DE", result.getDefaultLocales().toLanguageTags());
+        assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
index a2a40e6..cfb6bdd 100644
--- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
@@ -19,6 +19,7 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -41,14 +42,14 @@
 import android.content.pm.UserInfo;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
-import java.util.ArrayList;
-import java.util.List;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -57,6 +58,9 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @RunWith(AndroidJUnit4.class)
 public class IntentForwarderActivityTest {
 
@@ -549,8 +553,8 @@
         }
 
         @Override
-        public void startActivityAsCaller(Intent intent, @Nullable Bundle options, boolean
-                ignoreTargetSecurity, int userId) {
+        public void startActivityAsCaller(Intent intent, @Nullable Bundle options,
+                IBinder permissionToken, boolean ignoreTargetSecurity, int userId) {
             mStartActivityIntent = intent;
             mUserIdActivityLaunchedIn = userId;
         }
@@ -589,4 +593,4 @@
         @Override
         public void showToast(int messageId, int duration) {}
     }
-}
\ No newline at end of file
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java
index e81f678..7467114 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java
@@ -41,6 +41,7 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.text.format.DateUtils;
+import android.util.StatsLog;
 
 import junit.framework.TestCase;
 
@@ -258,6 +259,36 @@
         assertThat(time).isEqualTo(TIME_STATE_FOREGROUND_MS);
     }
 
+    @Test
+    public void testDrainTypesSyncedWithProto() {
+        assertEquals(BatterySipper.DrainType.AMBIENT_DISPLAY.ordinal(),
+                StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__AMBIENT_DISPLAY);
+        // AtomsProto has no "APP"
+        assertEquals(BatterySipper.DrainType.BLUETOOTH.ordinal(),
+                StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__BLUETOOTH);
+        assertEquals(BatterySipper.DrainType.CAMERA.ordinal(),
+                StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__CAMERA);
+        assertEquals(BatterySipper.DrainType.CELL.ordinal(),
+                StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__CELL);
+        assertEquals(BatterySipper.DrainType.FLASHLIGHT.ordinal(),
+                StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__FLASHLIGHT);
+        assertEquals(BatterySipper.DrainType.IDLE.ordinal(),
+                StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__IDLE);
+        assertEquals(BatterySipper.DrainType.MEMORY.ordinal(),
+                StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__MEMORY);
+        assertEquals(BatterySipper.DrainType.OVERCOUNTED.ordinal(),
+                StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__OVERCOUNTED);
+        assertEquals(BatterySipper.DrainType.PHONE.ordinal(),
+                StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__PHONE);
+        assertEquals(BatterySipper.DrainType.SCREEN.ordinal(),
+                StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__SCREEN);
+        assertEquals(BatterySipper.DrainType.UNACCOUNTED.ordinal(),
+                StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__UNACCOUNTED);
+        // AtomsProto has no "USER"
+        assertEquals(BatterySipper.DrainType.WIFI.ordinal(),
+                StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__WIFI);
+    }
+
     private BatterySipper createTestSmearBatterySipper(long activityTime, double totalPowerMah,
             int uidCode, boolean isUidNull) {
         final BatterySipper sipper = mock(BatterySipper.class);
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index b798042..3cfc644 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -38,6 +38,7 @@
         BatteryStatsUidTest.class,
         BatteryStatsUserLifecycleTests.class,
         KernelCpuProcReaderTest.class,
+        KernelCpuProcStringReaderTest.class,
         KernelMemoryBandwidthStatsTest.class,
         KernelSingleUidTimeReaderTest.class,
         KernelUidCpuFreqTimeReaderTest.class,
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java
new file mode 100644
index 0000000..dae9eb5
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuProcStringReaderTest.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2018 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.os;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.os.FileUtils;
+import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.IntStream;
+
+/**
+ * Test class for {@link KernelCpuProcStringReader}.
+ *
+ * $ atest FrameworksCoreTests:com.android.internal.os.KernelCpuProcStringReaderTest
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class KernelCpuProcStringReaderTest {
+    private File mRoot;
+    private File mTestDir;
+    private File mTestFile;
+    private Random mRand = new Random(12345);
+    private KernelCpuProcStringReader mReader;
+
+    private Context getContext() {
+        return InstrumentationRegistry.getContext();
+    }
+
+    @Before
+    public void setUp() {
+        mTestDir = getContext().getDir("test", Context.MODE_PRIVATE);
+        mRoot = getContext().getFilesDir();
+        mTestFile = new File(mTestDir, "test.file");
+        mReader = new KernelCpuProcStringReader(mTestFile.getAbsolutePath());
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        FileUtils.deleteContents(mTestDir);
+        FileUtils.deleteContents(mRoot);
+    }
+
+
+    /**
+     * Tests that reading will return null if the file does not exist.
+     */
+    @Test
+    public void testReadInvalidFile() throws Exception {
+        assertEquals(null, mReader.open());
+    }
+
+    /**
+     * Tests that reading will always return null after 5 failures.
+     */
+    @Test
+    public void testReadErrorsLimit() throws Exception {
+        for (int i = 0; i < 3; i++) {
+            try (KernelCpuProcStringReader.ProcFileIterator iter = mReader.open()) {
+                assertNull(iter);
+            }
+            SystemClock.sleep(50);
+        }
+        final String data = "018n9x134yrm9sry01298yMF1X980Ym908u98weruwe983^(*)0N)&tu09281my\n";
+        try (BufferedWriter w = Files.newBufferedWriter(mTestFile.toPath())) {
+            w.write(data);
+        }
+        try (KernelCpuProcStringReader.ProcFileIterator iter = mReader.open()) {
+            assertEquals(data.length(), iter.size());
+            assertEquals(data, iter.nextLine().toString() + '\n');
+        }
+        assertTrue(mTestFile.delete());
+        for (int i = 0; i < 3; i++) {
+            try (KernelCpuProcStringReader.ProcFileIterator iter = mReader.open(true)) {
+                assertNull(iter);
+            }
+            SystemClock.sleep(50);
+        }
+        try (BufferedWriter w = Files.newBufferedWriter(mTestFile.toPath())) {
+            w.write(data);
+        }
+        try (KernelCpuProcStringReader.ProcFileIterator iter = mReader.open(true)) {
+            assertNull(iter);
+        }
+    }
+
+    /** Tests nextLine functionality. */
+    @Test
+    public void testReadLine() throws Exception {
+        final String data = "10103: 0 0 0 1 5 3 1 2 0 0 3 0 0 0 0 2 2 330 0 0 0 0 1 0 0 0 0 0 0 0"
+                + " 0 0 0 0 0 0 0 0 0 0 0 13\n"
+                + "50083: 0 0 0 29 0 13 0 4 5 0 0 0 0 0 1 0 0 15 0 0 0 0 0 0 1 0 0 0 0 1 0 1 7 0 "
+                + "0 1 1 1 0 2 0 221\n"
+                + "50227: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 196 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"
+                + " 0 2 0 0 0 2 721\n"
+                + "10158: 0 0 0 0 19 3 9 1 0 7 4 3 3 3 1 3 10 893 2 0 3 0 0 0 0 0 0 0 0 1 0 2 0 0"
+                + " 1 2 10 0 0 0 1 58\n"
+                + "50138: 0 0 0 8 7 0 0 0 0 0 0 0 0 0 0 0 0 322 0 0 0 3 0 5 0 0 3 0 0 0 0 1 0 0 0"
+                + " 0 0 2 0 0 7 707\n";
+        try (BufferedWriter w = Files.newBufferedWriter(mTestFile.toPath())) {
+            w.write(data);
+        }
+        try (KernelCpuProcStringReader.ProcFileIterator iter = mReader.open()) {
+            assertEquals(
+                    "10103: 0 0 0 1 5 3 1 2 0 0 3 0 0 0 0 2 2 330 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0"
+                            + " 0 0 0 0 0 0 0 13",
+                    iter.nextLine().toString());
+            assertEquals(
+                    "50083: 0 0 0 29 0 13 0 4 5 0 0 0 0 0 1 0 0 15 0 0 0 0 0 0 1 0 0 0 0 1 0 1 7 "
+                            + "0 0 1 1 1 0 2 0 221",
+                    iter.nextLine().toString());
+            long[] actual = new long[43];
+            iter.nextLineAsArray(actual);
+            assertArrayEquals(
+                    new long[]{50227, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 0, 0,
+                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 721},
+                    actual);
+            assertEquals(
+                    "10158: 0 0 0 0 19 3 9 1 0 7 4 3 3 3 1 3 10 893 2 0 3 0 0 0 0 0 0 0 0 1 0 2 0"
+                            + " 0 1 2 10 0 0 0 1 58",
+                    iter.nextLine().toString());
+            assertEquals(
+                    "50138: 0 0 0 8 7 0 0 0 0 0 0 0 0 0 0 0 0 322 0 0 0 3 0 5 0 0 3 0 0 0 0 1 0 0"
+                            + " 0 0 0 2 0 0 7 707",
+                    iter.nextLine().toString());
+        }
+    }
+
+    /** Stress tests read functionality. */
+    @Test
+    public void testMultipleRead() throws Exception {
+        for (int i = 0; i < 100; i++) {
+            final String data = getTestString(600, 150);
+            try (BufferedWriter w = Files.newBufferedWriter(mTestFile.toPath())) {
+                w.write(data);
+            }
+            String[] lines = data.split("\n");
+            try (KernelCpuProcStringReader.ProcFileIterator iter = mReader.open(true)) {
+                for (String line : lines) {
+                    assertEquals(line, iter.nextLine().toString());
+                }
+            }
+            assertTrue(mTestFile.delete());
+        }
+    }
+
+    /** Tests nextLineToArray functionality. */
+    @Test
+    public void testReadLineToArray() throws Exception {
+        final long[][] data = getTestArray(800, 50);
+        try (BufferedWriter w = Files.newBufferedWriter(mTestFile.toPath())) {
+            w.write(arrayToString(data));
+        }
+        long[] actual = new long[50];
+        try (KernelCpuProcStringReader.ProcFileIterator iter = mReader.open()) {
+            for (long[] expected : data) {
+                assertEquals(50, iter.nextLineAsArray(actual));
+                assertArrayEquals(expected, actual);
+            }
+        }
+    }
+
+    /**
+     * Tests that reading a file over the limit (1MB) will return null.
+     */
+    @Test
+    public void testReadOverLimit() throws Exception {
+        final String data = getTestString(1, 1024 * 1024 + 1);
+        try (BufferedWriter w = Files.newBufferedWriter(mTestFile.toPath())) {
+            w.write(data);
+        }
+        try (KernelCpuProcStringReader.ProcFileIterator iter = mReader.open()) {
+            assertNull(iter);
+        }
+    }
+
+    /**
+     * Tests concurrent reading with 5 threads.
+     */
+    @Test
+    public void testConcurrent() throws Exception {
+        final String data = getTestString(200, 150);
+        final String data1 = getTestString(180, 120);
+        final String[] lines = data.split("\n");
+        final String[] lines1 = data1.split("\n");
+        final List<Throwable> errs = Collections.synchronizedList(new ArrayList<>());
+        try (BufferedWriter w = Files.newBufferedWriter(mTestFile.toPath())) {
+            w.write(data);
+        }
+        // An additional thread for modifying the file content.
+        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(11);
+        final CountDownLatch ready = new CountDownLatch(10);
+        final CountDownLatch start = new CountDownLatch(1);
+        final CountDownLatch modify = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(10);
+
+        // Schedules 5 threads to be executed together now, and 5 to be executed after file is
+        // modified.
+        for (int i = 0; i < 5; i++) {
+            threadPool.submit(() -> {
+                ready.countDown();
+                try {
+                    start.await();
+                    try (KernelCpuProcStringReader.ProcFileIterator iter = mReader.open()) {
+                        for (String line : lines) {
+                            assertEquals(line, iter.nextLine().toString());
+                        }
+                    }
+                } catch (Throwable e) {
+                    errs.add(e);
+                } finally {
+                    done.countDown();
+                }
+            });
+            threadPool.submit(() -> {
+                ready.countDown();
+                try {
+                    start.await();
+                    // Wait for file modification.
+                    modify.await();
+                    try (KernelCpuProcStringReader.ProcFileIterator iter = mReader.open()) {
+                        for (String line : lines1) {
+                            assertEquals(line, iter.nextLine().toString());
+                        }
+                    }
+                } catch (Throwable e) {
+                    errs.add(e);
+                } finally {
+                    done.countDown();
+                }
+            });
+        }
+
+        assertTrue("Prep timed out", ready.await(100, TimeUnit.MILLISECONDS));
+        start.countDown();
+
+        threadPool.schedule(() -> {
+            assertTrue(mTestFile.delete());
+            try (BufferedWriter w = Files.newBufferedWriter(mTestFile.toPath())) {
+                w.write(data1);
+                modify.countDown();
+            } catch (Throwable e) {
+                errs.add(e);
+            }
+        }, 600, TimeUnit.MILLISECONDS);
+
+        assertTrue("Execution timed out", done.await(3, TimeUnit.SECONDS));
+        threadPool.shutdownNow();
+
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        errs.forEach(e -> e.printStackTrace(pw));
+
+        assertTrue("All Exceptions:\n" + sw.toString(), errs.isEmpty());
+    }
+
+    private String getTestString(int lines, int charsPerLine) {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < lines; i++) {
+            for (int j = 0; j < charsPerLine; j++) {
+                sb.append((char) (mRand.nextInt(93) + 32));
+            }
+            sb.append('\n');
+        }
+        return sb.toString();
+    }
+
+    private long[][] getTestArray(int lines, int numPerLine) {
+        return IntStream.range(0, lines).mapToObj(
+                (i) -> mRand.longs(numPerLine, 0, Long.MAX_VALUE).toArray()).toArray(long[][]::new);
+    }
+
+    private String arrayToString(long[][] array) {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < array.length; i++) {
+            sb.append(array[i][0]).append(':');
+            for (int j = 1; j < array[0].length; j++) {
+                sb.append(' ').append(array[i][j]);
+            }
+            sb.append('\n');
+        }
+        return sb.toString();
+    }
+}
diff --git a/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java b/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
index 01382aa..4e0f2a8 100644
--- a/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
+++ b/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
@@ -81,7 +81,7 @@
 
     @Test
     public void testSharedInstalledPrimary() throws Exception {
-        assertEquals("1001", getContent(getKernelPackageFile("shared:android.uid.phone", "appid")));
+        assertEquals("1001", getContent(getKernelPackageFile("shared-android.uid.phone", "appid")));
     }
 
     @Test
@@ -92,7 +92,7 @@
 
     @Test
     public void testSharedInstalledAll() throws Exception {
-        assertEquals("", getContent(getKernelPackageFile("shared:android.uid.phone",
+        assertEquals("", getContent(getKernelPackageFile("shared-android.uid.phone",
                 "excluded_userids")));
     }
 
diff --git a/data/etc/Android.mk b/data/etc/Android.mk
index 936ad22..d24c140a 100644
--- a/data/etc/Android.mk
+++ b/data/etc/Android.mk
@@ -47,3 +47,11 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/sysconfig
 LOCAL_SRC_FILES := $(LOCAL_MODULE)
 include $(BUILD_PREBUILT)
+
+########################
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.timezone.updater.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_RELATIVE_PATH := permissions
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
diff --git a/data/etc/com.android.timezone.updater.xml b/data/etc/com.android.timezone.updater.xml
new file mode 100644
index 0000000..60a66e2
--- /dev/null
+++ b/data/etc/com.android.timezone.updater.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2018 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
+  -->
+<permissions>
+    <privapp-permissions package="com.android.timezone.updater">
+        <permission name="android.permission.QUERY_TIME_ZONE_RULES" />
+        <permission name="android.permission.UPDATE_TIME_ZONE_RULES" />
+    </privapp-permissions>
+</permissions>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 68f24fb..a4c5ed2 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -173,6 +173,7 @@
     <assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" />
     <assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" />
 
+    <assign-permission name="android.permission.BATTERY_STATS" uid="statsd" />
     <assign-permission name="android.permission.DUMP" uid="statsd" />
     <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="statsd" />
     <assign-permission name="android.permission.STATSCOMPANION" uid="statsd" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 2604365..84cb5f8 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -194,6 +194,8 @@
 
     <privapp-permissions package="com.android.providers.calendar">
         <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
+        <permission name="android.permission.INTERACT_ACROSS_USERS" />
+        <permission name="android.permission.MANAGE_USERS" />
         <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
         <permission name="android.permission.USE_RESERVED_DISK"/>
     </privapp-permissions>
@@ -324,6 +326,7 @@
         <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
         <permission name="android.permission.MOVE_PACKAGE"/>
         <permission name="android.permission.PACKAGE_USAGE_STATS" />
+        <permission name="android.permission.POWER_SAVER" />
         <permission name="android.permission.READ_FRAME_BUFFER"/>
         <permission name="android.permission.READ_LOWPAN_CREDENTIAL"/>
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
@@ -391,6 +394,7 @@
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.REAL_GET_TASKS"/>
         <permission name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE"/>
+        <permission name="android.permission.START_ACTIVITY_AS_CALLER"/>
         <permission name="android.permission.START_TASKS_FROM_RECENTS"/>
         <permission name="android.permission.STATUS_BAR"/>
         <permission name="android.permission.STOP_APP_SWITCHES"/>
diff --git a/core/java/android/view/FrameInfo.java b/graphics/java/android/graphics/FrameInfo.java
similarity index 70%
rename from core/java/android/view/FrameInfo.java
rename to graphics/java/android/graphics/FrameInfo.java
index 6c5e048..42a5cc4 100644
--- a/core/java/android/view/FrameInfo.java
+++ b/graphics/java/android/graphics/FrameInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.view;
+package android.graphics;
 
 import android.annotation.LongDef;
 
@@ -33,14 +33,14 @@
  * long layout & measure took it's displayListRecordStart - performTraversalsStart.
  *
  * These constants must be kept in sync with FrameInfo.h in libhwui and are
- * used for indexing into AttachInfo's mFrameInfo long[], which is intended
+ * used for indexing into AttachInfo's frameInfo long[], which is intended
  * to be quick to pass down to native via JNI, hence a pre-packed format
  *
  * @hide
  */
-final class FrameInfo {
+public final class FrameInfo {
 
-    long[] mFrameInfo = new long[9];
+    public long[] frameInfo = new long[9];
 
     // Various flags set to provide extra metadata about the current frame
     private static final int FLAGS = 0;
@@ -48,8 +48,11 @@
     // Is this the first-draw following a window layout?
     public static final long FLAG_WINDOW_LAYOUT_CHANGED = 1;
 
+    // A renderer associated with just a Surface, not with a ViewRootImpl instance.
+    public static final long FLAG_SURFACE_CANVAS = 1 << 2;
+
     @LongDef(flag = true, value = {
-            FLAG_WINDOW_LAYOUT_CHANGED })
+            FLAG_WINDOW_LAYOUT_CHANGED, FLAG_SURFACE_CANVAS })
     @Retention(RetentionPolicy.SOURCE)
     public @interface FrameInfoFlags {}
 
@@ -78,41 +81,48 @@
     // When View:draw() started
     private static final int DRAW_START = 8;
 
+    /** checkstyle */
     public void setVsync(long intendedVsync, long usedVsync) {
-        mFrameInfo[INTENDED_VSYNC] = intendedVsync;
-        mFrameInfo[VSYNC] = usedVsync;
-        mFrameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
-        mFrameInfo[NEWEST_INPUT_EVENT] = 0;
-        mFrameInfo[FLAGS] = 0;
+        frameInfo[INTENDED_VSYNC] = intendedVsync;
+        frameInfo[VSYNC] = usedVsync;
+        frameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
+        frameInfo[NEWEST_INPUT_EVENT] = 0;
+        frameInfo[FLAGS] = 0;
     }
 
+    /** checkstyle */
     public void updateInputEventTime(long inputEventTime, long inputEventOldestTime) {
-        if (inputEventOldestTime < mFrameInfo[OLDEST_INPUT_EVENT]) {
-            mFrameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
+        if (inputEventOldestTime < frameInfo[OLDEST_INPUT_EVENT]) {
+            frameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
         }
-        if (inputEventTime > mFrameInfo[NEWEST_INPUT_EVENT]) {
-            mFrameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
+        if (inputEventTime > frameInfo[NEWEST_INPUT_EVENT]) {
+            frameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
         }
     }
 
+    /** checkstyle */
     public void markInputHandlingStart() {
-        mFrameInfo[HANDLE_INPUT_START] = System.nanoTime();
+        frameInfo[HANDLE_INPUT_START] = System.nanoTime();
     }
 
+    /** checkstyle */
     public void markAnimationsStart() {
-        mFrameInfo[ANIMATION_START] = System.nanoTime();
+        frameInfo[ANIMATION_START] = System.nanoTime();
     }
 
+    /** checkstyle */
     public void markPerformTraversalsStart() {
-        mFrameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
+        frameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
     }
 
+    /** checkstyle */
     public void markDrawStart() {
-        mFrameInfo[DRAW_START] = System.nanoTime();
+        frameInfo[DRAW_START] = System.nanoTime();
     }
 
+    /** checkstyle */
     public void addFlags(@FrameInfoFlags long flags) {
-        mFrameInfo[FLAGS] |= flags;
+        frameInfo[FLAGS] |= flags;
     }
 
 }
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
new file mode 100644
index 0000000..e402055
--- /dev/null
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -0,0 +1,1030 @@
+/*
+ * Copyright (C) 2018 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.graphics;
+
+import android.annotation.FloatRange;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.view.FrameMetricsObserver;
+import android.view.IGraphicsStats;
+import android.view.IGraphicsStatsCallback;
+import android.view.NativeVectorDrawableAnimator;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.TextureLayer;
+
+import com.android.internal.util.VirtualRefBasePtr;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import sun.misc.Cleaner;
+
+/**
+ * <p>Creates an instance of a hardware-accelerated renderer. This is used to render a scene built
+ * from {@link RenderNode}'s to an output {@link android.view.Surface}. There can be as many
+ * HardwareRenderer instances as desired.</p>
+ *
+ * <h3>Threading</h3>
+ * <p>HardwareRenderer is not thread safe. An instance of a HardwareRenderer must only be
+ * created & used from a single thread. It does not matter what thread is used, however
+ * it must have a {@link android.os.Looper}. Multiple instances do not have to share the same
+ * thread, although they can.</p>
+ *
+ * <h3>Resources & lifecycle</h3>
+ * <p>All HardwareRenderer instances share a common render thread. The render thread contains
+ * the GPU context & resources necessary to do GPU-accelerated rendering. As such, the first
+ * HardwareRenderer created comes with the cost of also creating the associated GPU contexts,
+ * however each incremental HardwareRenderer thereafter is fairly cheap. The expected usage
+ * is to have a HardwareRenderer instance for every active {@link Surface}. For example
+ * when an Activity shows a Dialog the system internally will use 2 hardware renderers, both
+ * of which may be drawing at the same time.</p>
+ * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
+ * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
+ * consumers such as {@link android.view.SurfaceView},
+ * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
+ * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
+ * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
+ * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
+ * Failure to do so will cause the render thread to stall on that surface, blocking all
+ * HardwareRenderer instances.</p>
+ *
+ * @hide
+ */
+public class HardwareRenderer {
+    private static final String LOG_TAG = "HardwareRenderer";
+
+    // Keep in sync with DrawFrameTask.h SYNC_* flags
+    /**
+     * Nothing interesting to report. Sync & draw kicked off
+     */
+    public static final int SYNC_OK = 0;
+
+    /**
+     * The renderer is requesting a redraw. This can occur if there's an animation that's running
+     * in the RenderNode tree and the hardware renderer is unable to self-animate.
+     *
+     * If this is returned from syncAndDrawFrame the expectation is that syncAndDrawFrame
+     * will be called again on the next vsync signal.
+     */
+    public static final int SYNC_REDRAW_REQUESTED = 1 << 0;
+
+    /**
+     * The hardware renderer no longer has a valid {@link android.view.Surface} to render to.
+     * This can happen if {@link Surface#destroy()} was called. The user should no longer
+     * attempt to call syncAndDrawFrame until a new surface has been provided by calling
+     * setSurface.
+     *
+     * Spoiler: the reward is GPU-accelerated drawing, better find that Surface!
+     */
+    public static final int SYNC_LOST_SURFACE_REWARD_IF_FOUND = 1 << 1;
+
+    /**
+     * The hardware renderer has been set to a "stopped" state. If this is returned then the
+     * rendering content has been synced, however a frame was not produced.
+     */
+    public static final int SYNC_CONTEXT_IS_STOPPED = 1 << 2;
+
+    /**
+     * The content was synced but the renderer has declined to produce a frame in this vsync
+     * interval. This can happen if a frame was already drawn in this vsync or if the renderer
+     * is outrunning the frame consumer. The renderer will internally re-schedule itself
+     * to render a frame in the next vsync signal, so the caller does not need to do anything
+     * in response to this signal.
+     */
+    public static final int SYNC_FRAME_DROPPED = 1 << 3;
+
+    @IntDef(value = {
+            SYNC_OK, SYNC_REDRAW_REQUESTED, SYNC_LOST_SURFACE_REWARD_IF_FOUND,
+            SYNC_CONTEXT_IS_STOPPED, SYNC_FRAME_DROPPED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SyncAndDrawResult {
+    }
+
+    /** @hide */
+    public static final int FLAG_DUMP_FRAMESTATS = 1 << 0;
+    /** @hide */
+    public static final int FLAG_DUMP_RESET = 1 << 1;
+    /** @hide */
+    public static final int FLAG_DUMP_ALL = FLAG_DUMP_FRAMESTATS;
+
+    /** @hide */
+    @IntDef(flag = true, prefix = {"FLAG_DUMP_"}, value = {
+            FLAG_DUMP_FRAMESTATS,
+            FLAG_DUMP_RESET
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DumpFlags {
+    }
+
+    /**
+     * Name of the file that holds the shaders cache.
+     */
+    private static final String CACHE_PATH_SHADERS = "com.android.opengl.shaders_cache";
+    private static final String CACHE_PATH_SKIASHADERS = "com.android.skia.shaders_cache";
+
+    private final long mNativeProxy;
+    /** @hide */
+    protected RenderNode mRootNode;
+    private boolean mOpaque = true;
+    private boolean mForceDark = false;
+    private FrameInfo mScratchInfo;
+
+    /**
+     * Creates a new instance of a HardwareRenderer. The HardwareRenderer will default
+     * to opaque with no light source configured.
+     */
+    public HardwareRenderer() {
+        mRootNode = RenderNode.adopt(nCreateRootRenderNode());
+        mRootNode.setClipToBounds(false);
+        mNativeProxy = nCreateProxy(!mOpaque, mRootNode.mNativeRenderNode);
+        if (mNativeProxy == 0) {
+            throw new OutOfMemoryError("Unable to create hardware renderer");
+        }
+        Cleaner.create(this, new DestroyContextRunnable(mNativeProxy));
+        ProcessInitializer.sInstance.init(mNativeProxy);
+    }
+
+    /**
+     * Destroys the rendering context of this HardwareRenderer. This destroys the resources
+     * associated with this renderer and releases the currently set {@link Surface}.
+     *
+     * The renderer may be restored from this state by setting a new {@link Surface}, setting
+     * new rendering content with {@link #setContentRoot(RenderNode)}, and resuming
+     * rendering with {@link #syncAndDrawFrame(long)}.
+     *
+     * It is suggested to call this in response to callbacks such as
+     * {@link android.view.SurfaceHolder.Callback#surfaceDestroyed(SurfaceHolder)}.
+     *
+     * Note that if there are any outstanding frame commit callbacks they may end up never being
+     * invoked if the frame was deferred to a later vsync.
+     */
+    public void destroy() {
+        nDestroy(mNativeProxy, mRootNode.mNativeRenderNode);
+    }
+
+    /**
+     * Sets a name for this renderer. This is used to identify this renderer instance
+     * when reporting debug information such as the per-window frame time metrics
+     * reported by 'adb shell dumpsys gfxinfo [package] framestats'
+     *
+     * @param name The debug name to use for this HardwareRenderer instance
+     */
+    public void setName(String name) {
+        nSetName(mNativeProxy, name);
+    }
+
+    /**
+     * Sets the center of the light source. The light source point controls the directionality
+     * and shape of shadows rendered by RenderNode Z & elevation.
+     *
+     * The platform's recommendation is to set lightX to 'displayWidth / 2f - windowLeft', set
+     * lightY to 0 - windowTop, lightZ set to 600dp, and lightRadius to 800dp.
+     *
+     * The light source should be setup both as part of initial configuration, and whenever
+     * the window moves to ensure the light source stays anchored in display space instead
+     * of in window space.
+     *
+     * This must be set at least once along with {@link #setLightSourceAlpha(float, float)}
+     * before shadows will work.
+     *
+     * @param lightX      The X position of the light source
+     * @param lightY      The Y position of the light source
+     * @param lightZ      The Z position of the light source. Must be >= 0.
+     * @param lightRadius The radius of the light source. Smaller radius will have sharper edges,
+     *                    larger radius will have softer shadows.
+     */
+    public void setLightSourceGeometry(float lightX, float lightY, float lightZ,
+            float lightRadius) {
+        validateFinite(lightX, "lightX");
+        validateFinite(lightY, "lightY");
+        validatePositive(lightZ, "lightZ");
+        validatePositive(lightRadius, "lightRadius");
+        nSetLightGeometry(mNativeProxy, lightX, lightY, lightZ, lightRadius);
+    }
+
+    /**
+     * Configures the ambient & spot shadow alphas. This is the alpha used when the shadow
+     * has max alpha, and ramps down from the values provided to zero.
+     *
+     * These values are typically provided by the current theme, see
+     * {@link android.R.attr#spotShadowAlpha} and {@link android.R.attr#ambientShadowAlpha}.
+     *
+     * This must be set at least once along with
+     * {@link #setLightSourceGeometry(float, float, float, float)} before shadows will work.
+     *
+     * @param ambientShadowAlpha The alpha for the ambient shadow. If unsure, a reasonable default
+     *                           is 0.039f.
+     * @param spotShadowAlpha    The alpha for the spot shadow. If unsure, a reasonable default is
+     *                           0.19f.
+     */
+    public void setLightSourceAlpha(@FloatRange(from = 0.0f, to = 1.0f) float ambientShadowAlpha,
+            @FloatRange(from = 0.0f, to = 1.0f) float spotShadowAlpha) {
+        validateAlpha(ambientShadowAlpha, "ambientShadowAlpha");
+        validateAlpha(spotShadowAlpha, "spotShadowAlpha");
+        nSetLightAlpha(mNativeProxy, ambientShadowAlpha, spotShadowAlpha);
+    }
+
+    /**
+     * Sets the content root to render. It is not necessary to call this whenever the content
+     * recording changes. Any mutations to the RenderNode content, or any of the RenderNode's
+     * contained within the content node, will be applied whenever {@link #syncAndDrawFrame(long)}
+     * is called.
+     *
+     * @param content The content to set as the root RenderNode. If null the content root is removed
+     *                and the renderer will draw nothing.
+     */
+    public void setContentRoot(@Nullable RenderNode content) {
+        RecordingCanvas canvas = mRootNode.startRecording();
+        if (content != null) {
+            canvas.drawRenderNode(content);
+        }
+        mRootNode.endRecording();
+    }
+
+    /**
+     * <p>The surface to render into. The surface is assumed to be associated with the display and
+     * as such is still driven by vsync signals such as those from
+     * {@link android.view.Choreographer} and that it has a native refresh rate matching that of
+     * the display's (typically 60hz).</p>
+     *
+     * <p>NOTE: Due to the shared, cooperative nature of the render thread it is critical that
+     * any {@link Surface} used must have a prompt, reliable consuming side. System-provided
+     * consumers such as {@link android.view.SurfaceView},
+     * {@link android.view.Window#takeSurface(SurfaceHolder.Callback2)},
+     * or {@link android.view.TextureView} all fit this requirement. However if custom consumers
+     * are used such as when using {@link SurfaceTexture} or {@link android.media.ImageReader}
+     * it is the app's responsibility to ensure that they consume updates promptly and rapidly.
+     * Failure to do so will cause the render thread to stall on that surface, blocking all
+     * HardwareRenderer instances.</p>
+     *
+     * @param surface The surface to render into. If null then rendering will be stopped. If
+     *                non-null then {@link Surface#isValid()} must be true.
+     */
+    public void setSurface(@Nullable Surface surface) {
+        if (surface != null && !surface.isValid()) {
+            throw new IllegalArgumentException("Surface is invalid. surface.isValid() == false.");
+        }
+        nSetSurface(mNativeProxy, surface);
+    }
+
+    /**
+     * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+     *
+     * @hide
+     */
+    @SyncAndDrawResult
+    public int syncAndDrawFrame(@NonNull FrameInfo frameInfo) {
+        return nSyncAndDrawFrame(mNativeProxy, frameInfo.frameInfo, frameInfo.frameInfo.length);
+    }
+
+    /**
+     * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+     *
+     * @param vsyncTime The vsync timestamp for this frame. Typically this comes from
+     *                  {@link android.view.Choreographer.FrameCallback}. Must be set and be valid
+     *                  as the renderer uses this time internally to drive animations.
+     * @return The result of the sync operation. See {@link SyncAndDrawResult}.
+     */
+    @SyncAndDrawResult
+    public int syncAndDrawFrame(long vsyncTime) {
+        if (mScratchInfo == null) {
+            mScratchInfo = new FrameInfo();
+        }
+        mScratchInfo.setVsync(vsyncTime, vsyncTime);
+        mScratchInfo.addFlags(FrameInfo.FLAG_SURFACE_CANVAS);
+        return syncAndDrawFrame(mScratchInfo);
+    }
+
+    /**
+     * Syncs the RenderNode tree to the render thread and requests a frame to be drawn.
+     * frameCommitCallback callback will be invoked when the current rendering content has been
+     * rendered into a frame and submitted to the swap chain.
+     *
+     * @param vsyncTime           The vsync timestamp for this frame. Typically this comes from
+     *                            {@link android.view.Choreographer.FrameCallback}. Must be set and
+     *                            be valid as the renderer uses this time internally to drive
+     *                            animations.
+     * @param frameCommitCallback The callback to invoke when the frame content has been drawn.
+     *                            Will be invoked on the current {@link android.os.Looper} thread.
+     * @return The result of the sync operation. See {@link SyncAndDrawResult}.
+     */
+    @SyncAndDrawResult
+    public int syncAndDrawFrame(long vsyncTime,
+            @Nullable Runnable frameCommitCallback) {
+        if (frameCommitCallback != null) {
+            setFrameCompleteCallback(frameNr -> frameCommitCallback.run());
+        }
+        return syncAndDrawFrame(vsyncTime);
+    }
+
+    /**
+     * Suspends any current rendering into the surface but do not do any destruction. This
+     * is useful to temporarily suspend using the active Surface in order to do any Surface
+     * mutations necessary.
+     *
+     * Any subsequent draws will override the pause, resuming normal operation.
+     *
+     * @return true if there was an outstanding render request, false otherwise. If this is true
+     * the caller should ensure that {@link #syncAndDrawFrame(long)} is called at the soonest
+     * possible time to resume normal operation.
+     *
+     * TODO Should this be exposed? ViewRootImpl needs it because it destroys the old
+     * Surface before getting a new one. However things like SurfaceView will ensure that
+     * the old surface remains un-destroyed until after a new frame has been produced with
+     * the new surface.
+     * @hide
+     */
+    public boolean pause() {
+        return nPause(mNativeProxy);
+    }
+
+    /**
+     * Hard stops rendering into the surface. If the renderer is stopped it will
+     * block any attempt to render. Calls to {@link #syncAndDrawFrame(long)} will still
+     * sync over the latest rendering content, however they will not render and instead
+     * {@link #SYNC_CONTEXT_IS_STOPPED} will be returned.
+     *
+     * If false is passed then rendering will resume as normal. Any pending rendering requests
+     * will produce a new frame at the next vsync signal.
+     *
+     * This is useful in combination with lifecycle events such as {@link Activity#onStop()}
+     * and {@link Activity#onStart()}.
+     *
+     * @param stopped true to stop all rendering, false to resume
+     */
+    public void setStopped(boolean stopped) {
+        nSetStopped(mNativeProxy, stopped);
+    }
+
+    /**
+     * Destroys all hardware rendering resources associated with the current rendering content.
+     * This includes releasing a reference to the current content root RenderNode. It will
+     * therefore be necessary to call {@link #setContentRoot(RenderNode)} in order to resume
+     * rendering after calling this.
+     *
+     * It is recommended, but not necessary, to use this in combination with lifecycle events
+     * such as {@link Activity#onStop()} and {@link Activity#onStart()} or in response to
+     * {@link android.content.ComponentCallbacks2#onTrimMemory(int)} signals such as
+     * {@link android.content.ComponentCallbacks2#TRIM_MEMORY_UI_HIDDEN}
+     *
+     * See also {@link #setStopped(boolean)}
+     */
+    public void destroyHardwareResources() {
+        nDestroyHardwareResources(mNativeProxy);
+    }
+
+    /**
+     * Whether or not the force-dark feature should be used for this renderer.
+     */
+    public boolean setForceDark(boolean enable) {
+        if (mForceDark != enable) {
+            mForceDark = enable;
+            nSetForceDark(mNativeProxy, enable);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Allocate buffers ahead of time to avoid allocation delays during rendering.
+     *
+     * Typically a Surface will allocate buffers lazily. This is usually fine and reduces the
+     * memory usage of Surfaces that render rarely or never hit triple buffering. However
+     * for UI it can result in a slight bit of jank on first launch. This hint will
+     * tell the HardwareRenderer that now is a good time to allocate the 3 buffers
+     * necessary for typical rendering.
+     *
+     * Must be called after a {@link Surface} has been set.
+     */
+    public void allocateBuffers() {
+        nAllocateBuffers(mNativeProxy);
+    }
+
+    /**
+     * Notifies the hardware renderer that a call to {@link #syncAndDrawFrame(long)} will
+     * be coming soon. This is used to help schedule when RenderThread-driven animations will
+     * happen as the renderer wants to avoid producing more than one frame per vsync signal.
+     */
+    public void notifyFramePending() {
+        nNotifyFramePending(mNativeProxy);
+    }
+
+    /**
+     * Change the HardwareRenderer's opacity. Will take effect on the next frame produced.
+     *
+     * If the renderer is set to opaque it is the app's responsibility to ensure that the
+     * content renders to every pixel of the Surface, otherwise corruption may result. Note that
+     * this includes ensuring that the first draw of any given pixel does not attempt to blend
+     * against the destination. If this is false then the hardware renderer will clear to
+     * transparent at the start of every frame.
+     *
+     * @param opaque true if the content rendered is opaque, false if the renderer should clear
+     *               to transparent before rendering
+     */
+    public void setOpaque(boolean opaque) {
+        if (mOpaque != opaque) {
+            mOpaque = opaque;
+            nSetOpaque(mNativeProxy, mOpaque);
+        }
+    }
+
+    /**
+     * Whether or not the renderer is set to be opaque. See {@link #setOpaque(boolean)}
+     *
+     * @return true if the renderer is opaque, false otherwise
+     */
+    public boolean isOpaque() {
+        return mOpaque;
+    }
+
+    /** @hide */
+    public void setFrameCompleteCallback(FrameCompleteCallback callback) {
+        nSetFrameCompleteCallback(mNativeProxy, callback);
+    }
+
+    /**
+     * TODO: Public API this?
+     *
+     * @hide
+     */
+    public void addFrameMetricsObserver(FrameMetricsObserver observer) {
+        long nativeObserver = nAddFrameMetricsObserver(mNativeProxy, observer);
+        observer.mNative = new VirtualRefBasePtr(nativeObserver);
+    }
+
+    /**
+     * TODO: Public API this?
+     *
+     * @hide
+     */
+    public void removeFrameMetricsObserver(FrameMetricsObserver observer) {
+        nRemoveFrameMetricsObserver(mNativeProxy, observer.mNative.get());
+        observer.mNative = null;
+    }
+
+    /**
+     * Enable/disable wide gamut rendering on this renderer. Whether or not the actual rendering
+     * will be wide gamut depends on the hardware support for such rendering.
+     *
+     * @param wideGamut true if this renderer should render in wide gamut, false if it should
+     *                  render in sRGB
+     *                  TODO: Figure out color...
+     * @hide
+     */
+    public void setWideGamut(boolean wideGamut) {
+        nSetWideGamut(mNativeProxy, wideGamut);
+    }
+
+    /**
+     * Blocks until all previously queued work has completed.
+     *
+     * TODO: Only used for draw finished listeners, but the FrameCompleteCallback does that
+     * better
+     *
+     * @hide
+     */
+    public void fence() {
+        nFence(mNativeProxy);
+    }
+
+    /** @hide */
+    public void registerAnimatingRenderNode(RenderNode animator) {
+        nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode);
+    }
+
+    /** @hide */
+    public void registerVectorDrawableAnimator(NativeVectorDrawableAnimator animator) {
+        nRegisterVectorDrawableAnimator(mRootNode.mNativeRenderNode,
+                animator.getAnimatorNativePtr());
+    }
+
+    /**
+     * Prevents any further drawing until {@link #syncAndDrawFrame(long)} is called.
+     * This is a signal that the contents of the RenderNode tree are no longer safe to play back.
+     * In practice this usually means that there are Functor pointers in the
+     * display list that are no longer valid.
+     *
+     * TODO: Can we get webview off of this?
+     *
+     * @hide
+     */
+    public void stopDrawing() {
+        nStopDrawing(mNativeProxy);
+    }
+
+    /**
+     * Creates a new hardware layer. A hardware layer built by calling this
+     * method will be treated as a texture layer, instead of as a render target.
+     *
+     * @return A hardware layer
+     * @hide
+     */
+    public TextureLayer createTextureLayer() {
+        long layer = nCreateTextureLayer(mNativeProxy);
+        return TextureLayer.adoptTextureLayer(this, layer);
+    }
+
+    /**
+     * Detaches the layer's surface texture from the GL context and releases
+     * the texture id
+     *
+     * @hide
+     */
+    public void detachSurfaceTexture(long hardwareLayer) {
+        nDetachSurfaceTexture(mNativeProxy, hardwareLayer);
+    }
+
+
+    /** @hide */
+    public void buildLayer(RenderNode node) {
+        if (node.hasDisplayList()) {
+            nBuildLayer(mNativeProxy, node.mNativeRenderNode);
+        }
+    }
+
+    /** @hide */
+    public boolean copyLayerInto(final TextureLayer layer, final Bitmap bitmap) {
+        return nCopyLayerInto(mNativeProxy,
+                layer.getDeferredLayerUpdater(), bitmap);
+    }
+
+    /**
+     * Indicates that the specified hardware layer needs to be updated
+     * as soon as possible.
+     *
+     * @param layer The hardware layer that needs an update
+     * @hide
+     */
+    public void pushLayerUpdate(TextureLayer layer) {
+        nPushLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
+    }
+
+    /**
+     * Tells the HardwareRenderer that the layer is destroyed. The renderer
+     * should remove the layer from any update queues.
+     *
+     * @hide
+     */
+    public void onLayerDestroyed(TextureLayer layer) {
+        nCancelLayerUpdate(mNativeProxy, layer.getDeferredLayerUpdater());
+    }
+
+    /** @hide */
+    public void setFrameCallback(FrameDrawingCallback callback) {
+        nSetFrameCallback(mNativeProxy, callback);
+    }
+
+    /**
+     * Adds a rendernode to the renderer which can be drawn and changed asynchronously to the
+     * rendernode of the UI thread.
+     *
+     * @param node       The node to add.
+     * @param placeFront If true, the render node will be placed in front of the content node,
+     *                   otherwise behind the content node.
+     * @hide
+     */
+    public void addRenderNode(RenderNode node, boolean placeFront) {
+        nAddRenderNode(mNativeProxy, node.mNativeRenderNode, placeFront);
+    }
+
+    /**
+     * Only especially added render nodes can be removed.
+     *
+     * @param node The node which was added via addRenderNode which should get removed again.
+     * @hide
+     */
+    public void removeRenderNode(RenderNode node) {
+        nRemoveRenderNode(mNativeProxy, node.mNativeRenderNode);
+    }
+
+    /**
+     * Draws a particular render node. If the node is not the content node, only the additional
+     * nodes will get drawn and the content remains untouched.
+     *
+     * @param node The node to be drawn.
+     * @hide
+     */
+    public void drawRenderNode(RenderNode node) {
+        nDrawRenderNode(mNativeProxy, node.mNativeRenderNode);
+    }
+
+    /**
+     * Loads system properties used by the renderer. This method is invoked
+     * whenever system properties are modified. Implementations can use this
+     * to trigger live updates of the renderer based on properties.
+     *
+     * @return True if a property has changed.
+     * @hide
+     */
+    public boolean loadSystemProperties() {
+        return nLoadSystemProperties(mNativeProxy);
+    }
+
+    /**
+     * @hide
+     */
+    public void dumpProfileInfo(FileDescriptor fd, @DumpFlags int dumpFlags) {
+        nDumpProfileInfo(mNativeProxy, fd, dumpFlags);
+    }
+
+    /**
+     * To avoid unnecessary overdrawing of the main content all additionally passed render nodes
+     * will be prevented to overdraw this area. It will be synchronized with the draw call.
+     * This should be updated in the content view's draw call.
+     *
+     * @param left   The left side of the protected bounds.
+     * @param top    The top side of the protected bounds.
+     * @param right  The right side of the protected bounds.
+     * @param bottom The bottom side of the protected bounds.
+     * @hide
+     */
+    public void setContentDrawBounds(int left, int top, int right, int bottom) {
+        nSetContentDrawBounds(mNativeProxy, left, top, right, bottom);
+    }
+
+    /**
+     * Interface used to receive callbacks when a frame is being drawn.
+     *
+     * @hide
+     */
+    public interface FrameDrawingCallback {
+        /**
+         * Invoked during a frame drawing.
+         *
+         * @param frame The id of the frame being drawn.
+         */
+        void onFrameDraw(long frame);
+    }
+
+    /**
+     * Interface used to be notified when a frame has finished rendering
+     *
+     * @hide
+     */
+    public interface FrameCompleteCallback {
+        /**
+         * Invoked after a frame draw
+         *
+         * @param frameNr The id of the frame that was drawn.
+         */
+        void onFrameComplete(long frameNr);
+    }
+
+    private static void validateAlpha(float alpha, String argumentName) {
+        if (!(alpha >= 0.0f && alpha <= 1.0f)) {
+            throw new IllegalArgumentException(argumentName + " must be a valid alpha, "
+                    + alpha + " is not in the range of 0.0f to 1.0f");
+        }
+    }
+
+    private static void validatePositive(float f, String argumentName) {
+        if (!(Float.isFinite(f) && f >= 0.0f)) {
+            throw new IllegalArgumentException(argumentName
+                    + " must be a finite positive, given=" + f);
+        }
+    }
+
+    private static void validateFinite(float f, String argumentName) {
+        if (!Float.isFinite(f)) {
+            throw new IllegalArgumentException(argumentName + " must be finite, given=" + f);
+        }
+    }
+
+    /** @hide */
+    public static void invokeFunctor(long functor, boolean waitForCompletion) {
+        nInvokeFunctor(functor, waitForCompletion);
+    }
+
+    /**
+     * b/68769804: For low FPS experiments.
+     *
+     * @hide
+     */
+    public static void setFPSDivisor(int divisor) {
+        nHackySetRTAnimationsEnabled(divisor <= 1);
+    }
+
+    /**
+     * Changes the OpenGL context priority if IMG_context_priority extension is available. Must be
+     * called before any OpenGL context is created.
+     *
+     * @param priority The priority to use. Must be one of EGL_CONTEXT_PRIORITY_* values.
+     * @hide
+     */
+    public static void setContextPriority(int priority) {
+        nSetContextPriority(priority);
+    }
+
+    /**
+     * Sets whether or not high contrast text rendering is enabled. The setting is global
+     * but only affects content rendered after the change is made.
+     *
+     * @hide
+     */
+    public static void setHighContrastText(boolean highContrastText) {
+        nSetHighContrastText(highContrastText);
+    }
+
+    /**
+     * If set RenderThread will avoid doing any IPC using instead a fake vsync & DisplayInfo source
+     *
+     * @hide
+     */
+    public static void setIsolatedProcess(boolean isIsolated) {
+        nSetIsolatedProcess(isIsolated);
+    }
+
+    /**
+     * If set extra graphics debugging abilities will be enabled such as dumping skp
+     *
+     * @hide
+     */
+    public static void setDebuggingEnabled(boolean enable) {
+        nSetDebuggingEnabled(enable);
+    }
+
+    /** @hide */
+    public static int copySurfaceInto(Surface surface, Rect srcRect, Bitmap bitmap) {
+        if (srcRect == null) {
+            // Empty rect means entire surface
+            return nCopySurfaceInto(surface, 0, 0, 0, 0, bitmap);
+        } else {
+            return nCopySurfaceInto(surface, srcRect.left, srcRect.top,
+                    srcRect.right, srcRect.bottom, bitmap);
+        }
+    }
+
+    /**
+     * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
+     * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
+     * not the RenderNode from a View.
+     *
+     * @hide
+     **/
+    public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
+        return nCreateHardwareBitmap(node.mNativeRenderNode, width, height);
+    }
+
+    /**
+     * Invoke this method when the system is running out of memory. This
+     * method will attempt to recover as much memory as possible, based on
+     * the specified hint.
+     *
+     * @param level Hint about the amount of memory that should be trimmed,
+     *              see {@link android.content.ComponentCallbacks}
+     * @hide
+     */
+    public static void trimMemory(int level) {
+        nTrimMemory(level);
+    }
+
+    /** @hide */
+    public static void overrideProperty(@NonNull String name, @NonNull String value) {
+        if (name == null || value == null) {
+            throw new IllegalArgumentException("name and value must be non-null");
+        }
+        nOverrideProperty(name, value);
+    }
+
+    /**
+     * Sets the directory to use as a persistent storage for threaded rendering
+     * resources.
+     *
+     * @param cacheDir A directory the current process can write to
+     * @hide
+     */
+    public static void setupDiskCache(File cacheDir) {
+        setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath(),
+                new File(cacheDir, CACHE_PATH_SKIASHADERS).getAbsolutePath());
+    }
+
+    /** @hide */
+    public static void setPackageName(String packageName) {
+        ProcessInitializer.sInstance.setPackageName(packageName);
+    }
+
+    private static final class DestroyContextRunnable implements Runnable {
+        private final long mNativeInstance;
+
+        DestroyContextRunnable(long nativeInstance) {
+            mNativeInstance = nativeInstance;
+        }
+
+        @Override
+        public void run() {
+            nDeleteProxy(mNativeInstance);
+        }
+    }
+
+    private static class ProcessInitializer {
+        static ProcessInitializer sInstance = new ProcessInitializer();
+
+        private boolean mInitialized = false;
+
+        private String mPackageName;
+        private IGraphicsStats mGraphicsStatsService;
+        private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
+            @Override
+            public void onRotateGraphicsStatsBuffer() throws RemoteException {
+                rotateBuffer();
+            }
+        };
+
+        private ProcessInitializer() {
+        }
+
+        synchronized void setPackageName(String name) {
+            if (mInitialized) return;
+            mPackageName = name;
+        }
+
+        synchronized void init(long renderProxy) {
+            if (mInitialized) return;
+            mInitialized = true;
+
+            initSched(renderProxy);
+            initGraphicsStats();
+        }
+
+        private void initSched(long renderProxy) {
+            try {
+                int tid = nGetRenderThreadTid(renderProxy);
+                ActivityManager.getService().setRenderThread(tid);
+            } catch (Throwable t) {
+                Log.w(LOG_TAG, "Failed to set scheduler for RenderThread", t);
+            }
+        }
+
+        private void initGraphicsStats() {
+            if (mPackageName == null) return;
+
+            try {
+                IBinder binder = ServiceManager.getService("graphicsstats");
+                if (binder == null) return;
+                mGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder);
+                requestBuffer();
+            } catch (Throwable t) {
+                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
+            }
+        }
+
+        private void rotateBuffer() {
+            nRotateProcessStatsBuffer();
+            requestBuffer();
+        }
+
+        private void requestBuffer() {
+            try {
+                ParcelFileDescriptor pfd = mGraphicsStatsService
+                        .requestBufferForProcess(mPackageName, mGraphicsStatsCallback);
+                nSetProcessStatsBuffer(pfd.getFd());
+                pfd.close();
+            } catch (Throwable t) {
+                Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t);
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public static native void disableVsync();
+
+    /** @hide */
+    protected static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
+
+    private static native void nRotateProcessStatsBuffer();
+
+    private static native void nSetProcessStatsBuffer(int fd);
+
+    private static native int nGetRenderThreadTid(long nativeProxy);
+
+    private static native long nCreateRootRenderNode();
+
+    private static native long nCreateProxy(boolean translucent, long rootRenderNode);
+
+    private static native void nDeleteProxy(long nativeProxy);
+
+    private static native boolean nLoadSystemProperties(long nativeProxy);
+
+    private static native void nSetName(long nativeProxy, String name);
+
+    private static native void nSetSurface(long nativeProxy, Surface window);
+
+    private static native boolean nPause(long nativeProxy);
+
+    private static native void nSetStopped(long nativeProxy, boolean stopped);
+
+    private static native void nSetLightGeometry(long nativeProxy,
+            float lightX, float lightY, float lightZ, float lightRadius);
+
+    private static native void nSetLightAlpha(long nativeProxy, float ambientShadowAlpha,
+            float spotShadowAlpha);
+
+    private static native void nSetOpaque(long nativeProxy, boolean opaque);
+
+    private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
+
+    private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
+
+    private static native void nDestroy(long nativeProxy, long rootRenderNode);
+
+    private static native void nRegisterAnimatingRenderNode(long rootRenderNode,
+            long animatingNode);
+
+    private static native void nRegisterVectorDrawableAnimator(long rootRenderNode, long animator);
+
+    private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
+
+    private static native long nCreateTextureLayer(long nativeProxy);
+
+    private static native void nBuildLayer(long nativeProxy, long node);
+
+    private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
+
+    private static native void nPushLayerUpdate(long nativeProxy, long layer);
+
+    private static native void nCancelLayerUpdate(long nativeProxy, long layer);
+
+    private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
+
+    private static native void nDestroyHardwareResources(long nativeProxy);
+
+    private static native void nTrimMemory(int level);
+
+    private static native void nOverrideProperty(String name, String value);
+
+    private static native void nFence(long nativeProxy);
+
+    private static native void nStopDrawing(long nativeProxy);
+
+    private static native void nNotifyFramePending(long nativeProxy);
+
+    private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
+            @DumpFlags int dumpFlags);
+
+    private static native void nAddRenderNode(long nativeProxy, long rootRenderNode,
+            boolean placeFront);
+
+    private static native void nRemoveRenderNode(long nativeProxy, long rootRenderNode);
+
+    private static native void nDrawRenderNode(long nativeProxy, long rootRenderNode);
+
+    private static native void nSetContentDrawBounds(long nativeProxy, int left,
+            int top, int right, int bottom);
+
+    private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback);
+
+    private static native void nSetFrameCompleteCallback(long nativeProxy,
+            FrameCompleteCallback callback);
+
+    private static native long nAddFrameMetricsObserver(long nativeProxy,
+            FrameMetricsObserver observer);
+
+    private static native void nRemoveFrameMetricsObserver(long nativeProxy, long nativeObserver);
+
+    private static native int nCopySurfaceInto(Surface surface,
+            int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
+
+    private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
+
+    private static native void nSetHighContrastText(boolean enabled);
+
+    // For temporary experimentation b/66945974
+    private static native void nHackySetRTAnimationsEnabled(boolean enabled);
+
+    private static native void nSetDebuggingEnabled(boolean enabled);
+
+    private static native void nSetIsolatedProcess(boolean enabled);
+
+    private static native void nSetContextPriority(int priority);
+
+    private static native void nAllocateBuffers(long nativeProxy);
+
+    private static native void nSetForceDark(long nativeProxy, boolean enabled);
+}
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 9546a4a..c580c46 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -16,8 +16,6 @@
 
 package android.graphics;
 
-import android.annotation.UnsupportedAppUsage;
-
 public class ImageFormat {
     /*
      * these constants are chosen to be binary compatible with their previous
@@ -92,20 +90,21 @@
      * </ul>
      * </p>
      *
-     * <pre> y_size = stride * height </pre>
+     * <pre> size = stride * height </pre>
      *
      * <p>For example, the {@link android.media.Image} object can provide data
-     * in this format from a {@link android.hardware.camera2.CameraDevice}
-     * through a {@link android.media.ImageReader} object if this format is
-     * supported by {@link android.hardware.camera2.CameraDevice}.</p>
+     * in this format from a {@link android.hardware.camera2.CameraDevice} (if
+     * supported) through a {@link android.media.ImageReader} object. The
+     * {@link android.media.Image#getPlanes() Image#getPlanes()} will return a
+     * single plane containing the pixel data. The pixel stride is always 1 in
+     * {@link android.media.Image.Plane#getPixelStride()}, and the
+     * {@link android.media.Image.Plane#getRowStride()} describes the vertical
+     * neighboring pixel distance (in bytes) between adjacent rows.</p>
      *
      * @see android.media.Image
      * @see android.media.ImageReader
      * @see android.hardware.camera2.CameraDevice
-     *
-     * @hide
      */
-    @UnsupportedAppUsage
     public static final int Y8 = 0x20203859;
 
     /**
@@ -787,6 +786,7 @@
             case DEPTH_POINT_CLOUD:
             case PRIVATE:
             case RAW_DEPTH:
+            case Y8:
                 return true;
         }
 
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java
index fd5d624..67ad404 100644
--- a/graphics/java/android/graphics/RecordingCanvas.java
+++ b/graphics/java/android/graphics/RecordingCanvas.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.util.Pools.SynchronizedPool;
+import android.view.DisplayListCanvas;
 import android.view.TextureLayer;
 
 import dalvik.annotation.optimization.CriticalNative;
@@ -34,7 +35,7 @@
  * {@link RenderNode#endRecording()} is called. It must not be retained beyond that as it is
  * internally reused.
  */
-public final class RecordingCanvas extends BaseRecordingCanvas {
+public final class RecordingCanvas extends DisplayListCanvas {
     // The recording canvas pool should be large enough to handle a deeply nested
     // view hierarchy because display lists are generated recursively.
     private static final int POOL_LIMIT = 25;
@@ -89,7 +90,8 @@
     // Constructors
     ///////////////////////////////////////////////////////////////////////////
 
-    private RecordingCanvas(@NonNull RenderNode node, int width, int height) {
+    /** @hide */
+    protected RecordingCanvas(@NonNull RenderNode node, int width, int height) {
         super(nCreateDisplayListCanvas(node.mNativeRenderNode, width, height));
         mDensity = 0; // disable bitmap density scaling
     }
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 12128b3..45d7a21 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -161,7 +161,7 @@
  * top-level content is desired, and finally calling {@link Surface#unlockCanvasAndPost(Canvas)}.
  * </p>
  */
-public class RenderNode {
+public final class RenderNode {
 
     // Use a Holder to allow static initialization in the boot image.
     private static class NoImagePreloadHolder {
@@ -178,6 +178,16 @@
     private final AnimationHost mAnimationHost;
     private RecordingCanvas mCurrentRecordingCanvas;
 
+    /**
+     * Creates a new RenderNode that can be used to record batches of
+     * drawing operations, and store / apply render properties when drawn.
+     *
+     * @param name The name of the RenderNode, used for debugging purpose. May be null.
+     */
+    public RenderNode(String name) {
+        this(name, null);
+    }
+
     private RenderNode(String name, AnimationHost animationHost) {
         mNativeRenderNode = nCreate(name);
         NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, mNativeRenderNode);
@@ -193,17 +203,6 @@
         mAnimationHost = null;
     }
 
-    /**
-     * Creates a new RenderNode that can be used to record batches of
-     * drawing operations, and store / apply render properties when drawn.
-     *
-     * @param name The name of the RenderNode, used for debugging purpose. May be null.
-     * @return A new RenderNode.
-     */
-    public static @NonNull RenderNode create(@Nullable String name) {
-        return new RenderNode(name, null);
-    }
-
     /** @hide */
     public static RenderNode create(String name, @Nullable AnimationHost animationHost) {
         return new RenderNode(name, animationHost);
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index a09b063..bf969ef 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -566,7 +566,7 @@
                 final CustomFallbackBuilder builder = new CustomFallbackBuilder(family)
                         .setStyle(new FontStyle(weight, slant));
                 if (mFallbackFamilyName != null) {
-                    builder.setFallback(mFallbackFamilyName);
+                    builder.setSystemFallback(mFallbackFamilyName);
                 }
                 final Typeface typeface = builder.build();
                 if (key != null) {
@@ -584,6 +584,14 @@
     /**
      * A builder class for creating new Typeface instance.
      *
+     * There are two font fallback mechanisms, custom font fallback and system font fallback.
+     * The custom font fallback is a simple ordered list. The text renderer tries to see if it can
+     * render a character with the first font and if that font does not support the character, try
+     * next one and so on. It will keep trying until end of the custom fallback chain. The maximum
+     * length of the custom fallback chain is 64.
+     * The system font fallback is a system pre-defined fallback chain. The system fallback is
+     * processed only when no matching font is found in the custom font fallback.
+     *
      * <p>
      * Examples,
      * 1) Create Typeface from single ttf file.
@@ -617,15 +625,29 @@
      * Font font = new Font.Builder("your_font_file.ttf").build();
      * FontFamily family = new FontFamily.Builder(font).build();
      * Typeface typeface = new Typeface.CustomFallbackBuilder(family)
-     *     .setFallback("serif")  // Set serif font family as the fallback.
+     *     .setSystemFallback("serif")  // Set serif font family as the fallback.
+     *     .build();
+     * </code>
+     * </pre>
+     * 4) Create Typeface from single ttf file and set another ttf file for the fallback.
+     * <pre>
+     * <code>
+     * Font font = new Font.Builder("English.ttf").build();
+     * FontFamily family = new FontFamily.Builder(font).build();
+     *
+     * Font fallbackFont = new Font.Builder("Arabic.ttf").build();
+     * FontFamily fallbackFamily = new FontFamily.Builder(fallbackFont).build();
+     * Typeface typeface = new Typeface.CustomFallbackBuilder(family)
+     *     .addCustomFallback(fallbackFamily)  // Specify fallback family.
+     *     .setSystemFallback("serif")  // Set serif font family as the fallback.
      *     .build();
      * </code>
      * </pre>
      * </p>
      */
     public static class CustomFallbackBuilder {
-        // TODO: Remove package modifier once android.graphics.FontFamily is deprecated.
-        private final android.graphics.fonts.FontFamily mFamily;
+        private static final int MAX_CUSTOM_FALLBACK = 64;
+        private final ArrayList<FontFamily> mFamilies = new ArrayList<>();
         private String mFallbackName = null;
         private @Nullable FontStyle mStyle;
 
@@ -634,19 +656,25 @@
          *
          * @param family a family object
          */
-        // TODO: Remove package modifier once android.graphics.FontFamily is deprecated.
-        public CustomFallbackBuilder(@NonNull android.graphics.fonts.FontFamily family) {
+        public CustomFallbackBuilder(@NonNull FontFamily family) {
             Preconditions.checkNotNull(family);
-            mFamily = family;
+            mFamilies.add(family);
         }
 
         /**
          * Sets a system fallback by name.
          *
+         * You can specify generic font familiy names or OEM specific family names. If the system
+         * don't have a specified fallback, the default fallback is used instead.
+         * For more information about generic font families, see <a
+         * href="https://www.w3.org/TR/css-fonts-4/#generic-font-families">CSS specification</a>
+         *
+         * For more information about fallback, see class description.
+         *
          * @param familyName a family name to be used for fallback if the provided fonts can not be
          *                   used
          */
-        public CustomFallbackBuilder setFallback(@NonNull String familyName) {
+        public CustomFallbackBuilder setSystemFallback(@NonNull String familyName) {
             Preconditions.checkNotNull(familyName);
             mFallbackName = familyName;
             return this;
@@ -667,19 +695,40 @@
         }
 
         /**
+         * Append a font family to the end of the custom font fallback.
+         *
+         * You can set up to 64 custom fallback families including the first font family you passed
+         * to the constructor.
+         * For more information about fallback, see class description.
+         *
+         * @param family a fallback family
+         * @throws IllegalArgumentException if you give more than 64 custom fallback families
+         */
+        public CustomFallbackBuilder addCustomFallback(@NonNull FontFamily family) {
+            Preconditions.checkNotNull(family);
+            Preconditions.checkArgument(mFamilies.size() < MAX_CUSTOM_FALLBACK,
+                    "Custom fallback limit exceeded(" + MAX_CUSTOM_FALLBACK + ")");
+            mFamilies.add(family);
+            return this;
+        }
+
+        /**
          * Create the Typeface based on the configured values.
          *
          * @return the Typeface object
          */
         public Typeface build() {
+            final int userFallbackSize = mFamilies.size();
             final FontFamily[] fallback = SystemFonts.getSystemFallback(mFallbackName);
-            final FontFamily[] fullFamilies = new FontFamily[fallback.length + 1];
-            final long[] ptrArray = new long[fallback.length + 1];
-            ptrArray[0] = mFamily.getNativePtr();
-            fullFamilies[0] = mFamily;
+            final FontFamily[] fullFamilies = new FontFamily[fallback.length + userFallbackSize];
+            final long[] ptrArray = new long[fallback.length + userFallbackSize];
+            for (int i = 0; i < userFallbackSize; ++i) {
+                ptrArray[i] = mFamilies.get(i).getNativePtr();
+                fullFamilies[i] = mFamilies.get(i);
+            }
             for (int i = 0; i < fallback.length; ++i) {
-                ptrArray[i + 1] = fallback[i].getNativePtr();
-                fullFamilies[i + 1] = fallback[i];
+                ptrArray[i + userFallbackSize] = fallback[i].getNativePtr();
+                fullFamilies[i + userFallbackSize] = fallback[i];
             }
             final int weight = mStyle == null ? 400 : mStyle.getWeight();
             final int italic =
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index 18b41fa..3c44916 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -149,9 +149,13 @@
     }
 
     /**
-     * Returns the alpha value of this drawable's color.
+     * Returns the alpha value of this drawable's color. Note this may not be the same alpha value
+     * provided in {@link Drawable#setAlpha(int)}. Instead this will return the alpha of the color
+     * combined with the alpha provided by setAlpha
      *
      * @return A value between 0 and 255.
+     *
+     * @see ColorDrawable#setAlpha(int)
      */
     @Override
     public int getAlpha() {
@@ -159,7 +163,9 @@
     }
 
     /**
-     * Sets the color's alpha value.
+     * Applies the given alpha to the underlying color. Note if the color already has
+     * an alpha applied to it, this will apply this alpha to the existing value instead of
+     * overwriting it.
      *
      * @param alpha The alpha value to set, between 0 and 255.
      */
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index e1f7263..caf610b 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -934,11 +934,13 @@
      * do account for the value of {@link #setAlpha}, but the general behavior is dependent
      * upon the implementation of the subclass.
      *
+     * @deprecated This method is no longer used in graphics optimizations
+     *
      * @return int The opacity class of the Drawable.
      *
      * @see android.graphics.PixelFormat
      */
-    public abstract @PixelFormat.Opacity int getOpacity();
+    @Deprecated public abstract @PixelFormat.Opacity int getOpacity();
 
     /**
      * Return the appropriate opacity value for two source opacities.  If
diff --git a/graphics/java/android/graphics/fonts/FontFamily.java b/graphics/java/android/graphics/fonts/FontFamily.java
index 14d31d9..c0f1b16 100644
--- a/graphics/java/android/graphics/fonts/FontFamily.java
+++ b/graphics/java/android/graphics/fonts/FontFamily.java
@@ -108,16 +108,17 @@
          * @return a font family
          */
         public @NonNull FontFamily build() {
-            return build("", FontConfig.Family.VARIANT_DEFAULT);
+            return build("", FontConfig.Family.VARIANT_DEFAULT, true /* isCustomFallback */);
         }
 
         /** @hide */
-        public @NonNull FontFamily build(@NonNull String langTags, int variant) {
+        public @NonNull FontFamily build(@NonNull String langTags, int variant,
+                boolean isCustomFallback) {
             final long builderPtr = nInitBuilder();
             for (int i = 0; i < mFonts.size(); ++i) {
                 nAddFont(builderPtr, mFonts.get(i).getNativePtr());
             }
-            final long ptr = nBuild(builderPtr, langTags, variant);
+            final long ptr = nBuild(builderPtr, langTags, variant, isCustomFallback);
             final FontFamily family = new FontFamily(mFonts, ptr);
             sFamilyRegistory.registerNativeAllocation(family, ptr);
             return family;
@@ -130,7 +131,8 @@
         private static native long nInitBuilder();
         @CriticalNative
         private static native void nAddFont(long builderPtr, long fontPtr);
-        private static native long nBuild(long builderPtr, String langTags, int variant);
+        private static native long nBuild(long builderPtr, String langTags, int variant,
+                boolean isCustomFallback);
         @CriticalNative
         private static native long nGetReleaseNativeFamily();
     }
diff --git a/graphics/java/android/graphics/fonts/SystemFonts.java b/graphics/java/android/graphics/fonts/SystemFonts.java
index 750adb2..4a9cf14 100644
--- a/graphics/java/android/graphics/fonts/SystemFonts.java
+++ b/graphics/java/android/graphics/fonts/SystemFonts.java
@@ -208,7 +208,7 @@
                 b.addFont(font);
             }
         }
-        return b == null ? null : b.build(languageTags, variant);
+        return b == null ? null : b.build(languageTags, variant, false /* isCustomFallback */);
     }
 
     private static void appendNamedFamily(@NonNull FontConfig.Family xmlFamily,
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 0a4ac8c..6d58d95 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -23,6 +23,7 @@
 import android.app.KeyguardManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Binder;
 import android.os.IBinder;
@@ -30,6 +31,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.security.KeyStoreException;
 import android.security.keymaster.ExportResult;
 import android.security.keymaster.KeyCharacteristics;
 import android.security.keymaster.KeymasterArguments;
@@ -37,17 +39,30 @@
 import android.security.keymaster.KeymasterCertificateChain;
 import android.security.keymaster.KeymasterDefs;
 import android.security.keymaster.OperationResult;
+import android.security.keystore.IKeystoreService;
 import android.security.keystore.KeyExpiredException;
 import android.security.keystore.KeyNotYetValidException;
 import android.security.keystore.KeyPermanentlyInvalidatedException;
+import android.security.keystore.KeyProperties;
+import android.security.keystore.KeyProtection;
+import android.security.keystore.KeystoreResponse;
 import android.security.keystore.StrongBoxUnavailableException;
 import android.security.keystore.UserNotAuthenticatedException;
 import android.util.Log;
-
+import com.android.org.bouncycastle.asn1.ASN1InputStream;
+import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
 import java.math.BigInteger;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.security.InvalidKeyException;
+import java.util.Arrays;
+import java.util.Date;
 import java.util.List;
 import java.util.Locale;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import sun.security.util.ObjectIdentifier;
+import sun.security.x509.AlgorithmId;
 
 /**
  * @hide This should not be made public in its present form because it
@@ -69,6 +84,7 @@
     public static final int VALUE_CORRUPTED = 8;
     public static final int UNDEFINED_ACTION = 9;
     public static final int WRONG_PASSWORD = 10;
+    public static final int KEY_ALREADY_EXISTS = 16;
     public static final int CANNOT_ATTEST_IDS = -66;
     public static final int HARDWARE_TYPE_UNAVAILABLE = -68;
 
@@ -239,7 +255,12 @@
             if (value == null) {
                 value = new byte[0];
             }
-            return mBinder.insert(key, value, uid, flags);
+            int error = mBinder.insert(key, value, uid, flags);
+            if (error == KEY_ALREADY_EXISTS) {
+                mBinder.del(key, uid);
+                error = mBinder.insert(key, value, uid, flags);
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
@@ -289,6 +310,31 @@
         }
     }
 
+    /**
+     * List uids of all keys that are auth bound to the current user. 
+     * Only system is allowed to call this method.
+     */
+    @UnsupportedAppUsage
+    public int[] listUidsOfAuthBoundKeys() {
+        final int MAX_RESULT_SIZE = 100;
+        int[] uidsOut = new int[MAX_RESULT_SIZE];
+        try {
+            int rc = mBinder.listUidsOfAuthBoundKeys(uidsOut);
+            if (rc != NO_ERROR) {
+                Log.w(TAG, String.format("listUidsOfAuthBoundKeys failed with error code %d", rc));
+                return null;
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, "Cannot connect to keystore", e);
+            return null;
+        } catch (android.os.ServiceSpecificException e) {
+            Log.w(TAG, "KeyStore exception", e);
+            return null;
+        }
+        // Remove any 0 entries
+        return Arrays.stream(uidsOut).filter(x -> x > 0).toArray();
+   }
+
     public String[] list(String prefix) {
         return list(prefix, UID_SELF);
     }
@@ -366,53 +412,6 @@
         return isEmpty(UserHandle.myUserId());
     }
 
-    public boolean generate(String key, int uid, int keyType, int keySize, int flags,
-            byte[][] args) {
-        try {
-            return mBinder.generate(key, uid, keyType, keySize, flags,
-                    new KeystoreArguments(args)) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
-    public boolean importKey(String keyName, byte[] key, int uid, int flags) {
-        try {
-            return mBinder.import_key(keyName, key, uid, flags) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        }
-    }
-
-    public byte[] sign(String key, byte[] data) {
-        try {
-            return mBinder.sign(key, data);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return null;
-        } catch (android.os.ServiceSpecificException e) {
-            Log.w(TAG, "KeyStore exception", e);
-            return null;
-        }
-
-    }
-
-    public boolean verify(String key, byte[] data, byte[] signature) {
-        try {
-            signature = signature != null ? signature : new byte[0];
-            return mBinder.verify(key, data, signature) == NO_ERROR;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
-        } catch (android.os.ServiceSpecificException e) {
-            Log.w(TAG, "KeyStore exception", e);
-            return false;
-        }
-
-    }
-
     public String grant(String key, int uid) {
         try {
             String grantAlias =  mBinder.grant(key, uid);
@@ -484,22 +483,107 @@
 
     public boolean addRngEntropy(byte[] data, int flags) {
         try {
-            return mBinder.addRngEntropy(data, flags) == NO_ERROR;
+            KeystoreResultPromise promise = new KeystoreResultPromise();
+            int errorCode = mBinder.addRngEntropy(promise, data, flags);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get().getErrorCode() == NO_ERROR;
+            } else {
+                return false;
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return false;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "AddRngEntropy completed with exception", e);
+            return false;
         }
     }
 
+    private class KeyCharacteristicsCallbackResult {
+        private KeystoreResponse keystoreResponse;
+        private KeyCharacteristics keyCharacteristics;
+
+        public KeyCharacteristicsCallbackResult(KeystoreResponse keystoreResponse,
+                                                KeyCharacteristics keyCharacteristics) {
+            this.keystoreResponse = keystoreResponse;
+            this.keyCharacteristics = keyCharacteristics;
+        }
+
+        public KeystoreResponse getKeystoreResponse() {
+            return keystoreResponse;
+        }
+
+        public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
+            this.keystoreResponse = keystoreResponse;
+        }
+
+        public KeyCharacteristics getKeyCharacteristics() {
+            return keyCharacteristics;
+        }
+
+        public void setKeyCharacteristics(KeyCharacteristics keyCharacteristics) {
+            this.keyCharacteristics = keyCharacteristics;
+        }
+    }
+
+    private class KeyCharacteristicsPromise
+    extends android.security.keystore.IKeystoreKeyCharacteristicsCallback.Stub {
+        final private CompletableFuture<KeyCharacteristicsCallbackResult> future =
+                new CompletableFuture<KeyCharacteristicsCallbackResult>();
+        @Override
+        public void onFinished(KeystoreResponse keystoreResponse,
+                               KeyCharacteristics keyCharacteristics)
+                                       throws android.os.RemoteException {
+            future.complete(
+                    new KeyCharacteristicsCallbackResult(keystoreResponse, keyCharacteristics));
+        }
+        public final CompletableFuture<KeyCharacteristicsCallbackResult> getFuture() {
+            return future;
+        }
+    };
+
+    private int generateKeyInternal(String alias, KeymasterArguments args, byte[] entropy, int uid,
+            int flags, KeyCharacteristics outCharacteristics)
+                    throws RemoteException, ExecutionException, InterruptedException {
+        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+        int error = mBinder.generateKey(promise, alias, args, entropy, uid, flags);
+        if (error != NO_ERROR) {
+            Log.e(TAG, "generateKeyInternal failed on request " + error);
+            return error;
+        }
+
+        KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+        error = result.getKeystoreResponse().getErrorCode();
+        if (error != NO_ERROR) {
+            Log.e(TAG, "generateKeyInternal failed on response " + error);
+            return error;
+        }
+        KeyCharacteristics characteristics = result.getKeyCharacteristics();
+        if (characteristics == null) {
+            Log.e(TAG, "generateKeyInternal got empty key cheractariestics " + error);
+            return SYSTEM_ERROR;
+        }
+        outCharacteristics.shallowCopyFrom(characteristics);
+        return NO_ERROR;
+    }
+
     public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
             int flags, KeyCharacteristics outCharacteristics) {
         try {
             entropy = entropy != null ? entropy : new byte[0];
             args = args != null ? args : new KeymasterArguments();
-            return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+            int error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
+            if (error == KEY_ALREADY_EXISTS) {
+                mBinder.del(alias, uid);
+                error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "generateKey completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -513,10 +597,24 @@
         try {
             clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
             appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
-            return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics);
+            KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+            int error = mBinder.getKeyCharacteristics(promise, alias, clientId, appId, uid);
+            if (error != NO_ERROR) return error;
+
+            KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+            error = result.getKeystoreResponse().getErrorCode();
+            if (error != NO_ERROR) return error;
+
+            KeyCharacteristics characteristics = result.getKeyCharacteristics();
+            if (characteristics == null) return SYSTEM_ERROR;
+            outCharacteristics.shallowCopyFrom(characteristics);
+            return NO_ERROR;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "GetKeyCharacteristics completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -525,14 +623,40 @@
         return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
     }
 
+    private int importKeyInternal(String alias, KeymasterArguments args, int format, byte[] keyData,
+            int uid, int flags, KeyCharacteristics outCharacteristics)
+                    throws RemoteException, ExecutionException, InterruptedException {
+        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+        int error = mBinder.importKey(promise, alias, args, format, keyData, uid, flags);
+        if (error != NO_ERROR) return error;
+
+        KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+        error = result.getKeystoreResponse().getErrorCode();
+        if (error != NO_ERROR) return error;
+
+        KeyCharacteristics characteristics = result.getKeyCharacteristics();
+        if (characteristics == null) return SYSTEM_ERROR;
+        outCharacteristics.shallowCopyFrom(characteristics);
+        return NO_ERROR;
+    }
+
     public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
             int uid, int flags, KeyCharacteristics outCharacteristics) {
         try {
-            return mBinder.importKey(alias, args, format, keyData, uid, flags,
+            int error = importKeyInternal(alias, args, format, keyData, uid, flags,
                     outCharacteristics);
+            if (error == KEY_ALREADY_EXISTS) {
+                mBinder.del(alias, uid);
+                error = importKeyInternal(alias, args, format, keyData, uid, flags,
+                        outCharacteristics);
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "ImportKey completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -541,28 +665,136 @@
         return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
     }
 
+    private String getAlgorithmFromPKCS8(byte[] keyData) {
+        try {
+            final ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
+            final PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
+            final String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
+            return new AlgorithmId(new ObjectIdentifier(algOid)).getName();
+        } catch (IOException e) {
+            Log.e(TAG, "getAlgorithmFromPKCS8 Failed to parse key data");
+            Log.e(TAG, Log.getStackTraceString(e));
+            return null;
+        }
+    }
+
+    private KeymasterArguments makeLegacyArguments(String algorithm) {
+        KeymasterArguments args = new KeymasterArguments();
+        args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM,
+                KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(algorithm));
+        args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_SIGN);
+        args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_VERIFY);
+        args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_ENCRYPT);
+        args.addEnum(KeymasterDefs.KM_TAG_PURPOSE, KeymasterDefs.KM_PURPOSE_DECRYPT);
+        args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_NONE);
+        if (algorithm.equalsIgnoreCase(KeyProperties.KEY_ALGORITHM_RSA)) {
+            args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_OAEP);
+            args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
+            args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
+            args.addEnum(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_PSS);
+        }
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE);
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_MD5);
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA1);
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_224);
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_256);
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_384);
+        args.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_512);
+        args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
+        args.addDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, new Date(Long.MAX_VALUE));
+        args.addDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, new Date(Long.MAX_VALUE));
+        args.addDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, new Date(0));
+        return args;
+    }
+
+    public boolean importKey(String alias, byte[] keyData, int uid, int flags) {
+        String algorithm = getAlgorithmFromPKCS8(keyData);
+        if (algorithm == null) return false;
+        KeymasterArguments args = makeLegacyArguments(algorithm);
+        KeyCharacteristics out = new KeyCharacteristics();
+        int result =  importKey(alias, args, KeymasterDefs.KM_KEY_FORMAT_PKCS8, keyData, uid,
+                                flags, out);
+        if (result != NO_ERROR) {
+            Log.e(TAG, Log.getStackTraceString(
+                    new KeyStoreException(result, "legacy key import failed")));
+            return false;
+        }
+        return true;
+    }
+
+    private int importWrappedKeyInternal(String wrappedKeyAlias, byte[] wrappedKey,
+            String wrappingKeyAlias,
+            byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid,
+            KeyCharacteristics outCharacteristics)
+                    throws RemoteException, ExecutionException, InterruptedException {
+        KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+        int error = mBinder.importWrappedKey(promise, wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+                maskingKey, args, rootSid, fingerprintSid);
+        if (error != NO_ERROR) return error;
+
+        KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+        error = result.getKeystoreResponse().getErrorCode();
+        if (error != NO_ERROR) return error;
+
+        KeyCharacteristics characteristics = result.getKeyCharacteristics();
+        if (characteristics == null) return SYSTEM_ERROR;
+        outCharacteristics.shallowCopyFrom(characteristics);
+        return NO_ERROR;
+    }
+
     public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
             String wrappingKeyAlias,
             byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
             KeyCharacteristics outCharacteristics) {
+        // TODO b/119217337 uid parameter gets silently ignored.
         try {
-            return mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+            int error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
                     maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
+            if (error == KEY_ALREADY_EXISTS) {
+                mBinder.del(wrappedKeyAlias, UID_SELF);
+                error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+                        maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "ImportWrappedKey completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
+    private class ExportKeyPromise
+    extends android.security.keystore.IKeystoreExportKeyCallback.Stub {
+        final private CompletableFuture<ExportResult> future = new CompletableFuture<ExportResult>();
+        @Override
+        public void onFinished(ExportResult exportKeyResult) throws android.os.RemoteException {
+            future.complete(exportKeyResult);
+        }
+        public final CompletableFuture<ExportResult> getFuture() {
+            return future;
+        }
+    };
+
     public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
             KeymasterBlob appId, int uid) {
         try {
             clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
             appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
-            return mBinder.exportKey(alias, format, clientId, appId, uid);
+            ExportKeyPromise promise = new ExportKeyPromise();
+            int error = mBinder.exportKey(promise, alias, format, clientId, appId, uid);
+            if (error == NO_ERROR) {
+                return promise.getFuture().get();
+            } else {
+                return new ExportResult(error);
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "ExportKey completed with exception", e);
+            return null;
         }
     }
     public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
@@ -570,15 +802,37 @@
         return exportKey(alias, format, clientId, appId, UID_SELF);
     }
 
+    private class OperationPromise
+    extends android.security.keystore.IKeystoreOperationResultCallback.Stub {
+        final private CompletableFuture<OperationResult> future = new CompletableFuture<OperationResult>();
+        @Override
+        public void onFinished(OperationResult operationResult) throws android.os.RemoteException {
+            future.complete(operationResult);
+        }
+        public final CompletableFuture<OperationResult> getFuture() {
+            return future;
+        }
+    };
+
     public OperationResult begin(String alias, int purpose, boolean pruneable,
             KeymasterArguments args, byte[] entropy, int uid) {
         try {
             args = args != null ? args : new KeymasterArguments();
             entropy = entropy != null ? entropy : new byte[0];
-            return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
+            OperationPromise promise = new OperationPromise();
+            int errorCode =  mBinder.begin(promise, getToken(), alias, purpose, pruneable, args,
+                                           entropy, uid);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get();
+            } else {
+                return new OperationResult(errorCode);
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "Begin completed with exception", e);
+            return null;
         }
     }
 
@@ -593,10 +847,19 @@
         try {
             arguments = arguments != null ? arguments : new KeymasterArguments();
             input = input != null ? input : new byte[0];
-            return mBinder.update(token, arguments, input);
+            OperationPromise promise = new OperationPromise();
+            int errorCode =  mBinder.update(promise, token, arguments, input);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get();
+            } else {
+                return new OperationResult(errorCode);
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "Update completed with exception", e);
+            return null;
         }
     }
 
@@ -606,10 +869,19 @@
             arguments = arguments != null ? arguments : new KeymasterArguments();
             entropy = entropy != null ? entropy : new byte[0];
             signature = signature != null ? signature : new byte[0];
-            return mBinder.finish(token, arguments, signature, entropy);
+            OperationPromise promise = new OperationPromise();
+            int errorCode = mBinder.finish(promise, token, arguments, signature, entropy);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get();
+            } else {
+                return new OperationResult(errorCode);
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "Finish completed with exception", e);
+            return null;
         }
     }
 
@@ -617,27 +889,33 @@
         return finish(token, arguments, signature, null);
     }
 
+    private class KeystoreResultPromise
+    extends android.security.keystore.IKeystoreResponseCallback.Stub {
+        final private CompletableFuture<KeystoreResponse> future = new CompletableFuture<KeystoreResponse>();
+        @Override
+        public void onFinished(KeystoreResponse keystoreResponse) throws android.os.RemoteException {
+            future.complete(keystoreResponse);
+        }
+        public final CompletableFuture<KeystoreResponse> getFuture() {
+            return future;
+        }
+    };
+
     public int abort(IBinder token) {
         try {
-            return mBinder.abort(token);
+            KeystoreResultPromise promise = new KeystoreResultPromise();
+            int errorCode = mBinder.abort(promise, token);
+            if (errorCode == NO_ERROR) {
+                return promise.getFuture().get().getErrorCode();
+            } else {
+                return errorCode;
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
-        }
-    }
-
-    /**
-     * Check if the operation referenced by {@code token} is currently authorized.
-     *
-     * @param token An operation token returned by a call to
-     * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
-     */
-    public boolean isOperationAuthorized(IBinder token) {
-        try {
-            return mBinder.isOperationAuthorized(token);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Cannot connect to keystore", e);
-            return false;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "Abort completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -719,6 +997,47 @@
         return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
     }
 
+    private class KeyAttestationCallbackResult {
+        private KeystoreResponse keystoreResponse;
+        private KeymasterCertificateChain certificateChain;
+
+        public KeyAttestationCallbackResult(KeystoreResponse keystoreResponse,
+                KeymasterCertificateChain certificateChain) {
+            this.keystoreResponse = keystoreResponse;
+            this.certificateChain = certificateChain;
+        }
+
+        public KeystoreResponse getKeystoreResponse() {
+            return keystoreResponse;
+        }
+
+        public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
+            this.keystoreResponse = keystoreResponse;
+        }
+
+        public KeymasterCertificateChain getCertificateChain() {
+            return certificateChain;
+        }
+
+        public void setCertificateChain(KeymasterCertificateChain certificateChain) {
+            this.certificateChain = certificateChain;
+        }
+    }
+
+    private class CertificateChainPromise
+    extends android.security.keystore.IKeystoreCertificateChainCallback.Stub {
+        final private CompletableFuture<KeyAttestationCallbackResult> future = new CompletableFuture<KeyAttestationCallbackResult>();
+        @Override
+        public void onFinished(KeystoreResponse keystoreResponse,
+                KeymasterCertificateChain certificateChain) throws android.os.RemoteException {
+            future.complete(new KeyAttestationCallbackResult(keystoreResponse, certificateChain));
+        }
+        public final CompletableFuture<KeyAttestationCallbackResult> getFuture() {
+            return future;
+        }
+    };
+
+
     public int attestKey(
             String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
         try {
@@ -728,10 +1047,21 @@
             if (outChain == null) {
                 outChain = new KeymasterCertificateChain();
             }
-            return mBinder.attestKey(alias, params, outChain);
+            CertificateChainPromise promise = new CertificateChainPromise();
+            int error = mBinder.attestKey(promise, alias, params);
+            if (error != NO_ERROR) return error;
+            KeyAttestationCallbackResult result = promise.getFuture().get();
+            error = result.getKeystoreResponse().getErrorCode();
+            if (error == NO_ERROR) {
+                outChain.shallowCopyFrom(result.getCertificateChain());
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "AttestKey completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -743,10 +1073,21 @@
             if (outChain == null) {
                 outChain = new KeymasterCertificateChain();
             }
-            return mBinder.attestDeviceIds(params, outChain);
+            CertificateChainPromise promise = new CertificateChainPromise();
+            int error = mBinder.attestDeviceIds(promise, params);
+            if (error != NO_ERROR) return error;
+            KeyAttestationCallbackResult result = promise.getFuture().get();
+            error = result.getKeystoreResponse().getErrorCode();
+            if (error == NO_ERROR) {
+                outChain.shallowCopyFrom(result.getCertificateChain());
+            }
+            return error;
         } catch (RemoteException e) {
             Log.w(TAG, "Cannot connect to keystore", e);
             return SYSTEM_ERROR;
+        } catch (ExecutionException | InterruptedException e) {
+            Log.e(TAG, "AttestDevicdeIds completed with exception", e);
+            return SYSTEM_ERROR;
         }
     }
 
@@ -913,7 +1254,7 @@
                     return new UserNotAuthenticatedException();
                 }
 
-                long fingerprintOnlySid = getFingerprintOnlySid();
+                final long fingerprintOnlySid = getFingerprintOnlySid();
                 if ((fingerprintOnlySid != 0)
                         && (keySids.contains(KeymasterArguments.toUint64(fingerprintOnlySid)))) {
                     // One of the key's SIDs is the current fingerprint SID -- user can be
@@ -921,6 +1262,14 @@
                     return new UserNotAuthenticatedException();
                 }
 
+                final long faceOnlySid = getFaceOnlySid();
+                if ((faceOnlySid != 0)
+                        && (keySids.contains(KeymasterArguments.toUint64(faceOnlySid)))) {
+                    // One of the key's SIDs is the current face SID -- user can be
+                    // authenticated against that SID.
+                    return new UserNotAuthenticatedException();
+                }
+
                 // None of the key's SIDs can ever be authenticated
                 return new KeyPermanentlyInvalidatedException();
             }
@@ -931,6 +1280,21 @@
         }
     }
 
+    private long getFaceOnlySid() {
+        final PackageManager packageManager = mContext.getPackageManager();
+        if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) {
+            return 0;
+        }
+        FaceManager faceManager = mContext.getSystemService(FaceManager.class);
+        if (faceManager == null) {
+            return 0;
+        }
+
+        // TODO: Restore USE_BIOMETRIC or USE_BIOMETRIC_INTERNAL permission check in
+        // FaceManager.getAuthenticatorId once the ID is no longer needed here.
+        return faceManager.getAuthenticatorId();
+    }
+
     private long getFingerprintOnlySid() {
         final PackageManager packageManager = mContext.getPackageManager();
         if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
index 7bbc099..a2d2355 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -182,8 +182,8 @@
                     KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
 
         boolean invalidatedByBiometricEnrollment = false;
-        if (keymasterSwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_FINGERPRINT
-            || keymasterHwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_FINGERPRINT) {
+        if (keymasterSwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_BIOMETRIC
+            || keymasterHwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_BIOMETRIC) {
             // Fingerprint-only key; will be invalidated if the root SID isn't in the SID list.
             invalidatedByBiometricEnrollment = keymasterSecureUserIds != null
                     && !keymasterSecureUserIds.isEmpty()
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index f829bb7..52896b5 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -16,7 +16,7 @@
 
 package android.security.keystore;
 
-import android.app.ActivityManager;
+import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.security.GateKeeper;
 import android.security.KeyStore;
@@ -24,6 +24,8 @@
 import android.security.keymaster.KeymasterDefs;
 
 import java.security.ProviderException;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @hide
@@ -121,35 +123,44 @@
 
         if (spec.getUserAuthenticationValidityDurationSeconds() == -1) {
             // Every use of this key needs to be authorized by the user. This currently means
-            // fingerprint-only auth.
+            // fingerprint or face auth.
             FingerprintManager fingerprintManager =
                     KeyStore.getApplicationContext().getSystemService(FingerprintManager.class);
+            FaceManager faceManager =
+                    KeyStore.getApplicationContext().getSystemService(FaceManager.class);
             // TODO: Restore USE_FINGERPRINT permission check in
             // FingerprintManager.getAuthenticatorId once the ID is no longer needed here.
-            long fingerprintOnlySid =
+            final long fingerprintOnlySid =
                     (fingerprintManager != null) ? fingerprintManager.getAuthenticatorId() : 0;
-            if (fingerprintOnlySid == 0) {
+            final long faceOnlySid =
+                    (faceManager != null) ? faceManager.getAuthenticatorId() : 0;
+
+            if (fingerprintOnlySid == 0 && faceOnlySid == 0) {
                 throw new IllegalStateException(
-                        "At least one fingerprint must be enrolled to create keys requiring user"
+                        "At least one biometric must be enrolled to create keys requiring user"
                         + " authentication for every use");
             }
 
-            long sid;
+            List<Long> sids = new ArrayList<>();
             if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) {
-                sid = spec.getBoundToSpecificSecureUserId();
+                sids.add(spec.getBoundToSpecificSecureUserId());
             } else if (spec.isInvalidatedByBiometricEnrollment()) {
-                // The fingerprint-only SID will change on fingerprint enrollment or removal of all,
-                // enrolled fingerprints, invalidating the key.
-                sid = fingerprintOnlySid;
+                // The biometric-only SIDs will change on biometric enrollment or removal of all
+                // enrolled templates, invalidating the key.
+                sids.add(fingerprintOnlySid);
+                sids.add(faceOnlySid);
             } else {
                 // The root SID will *not* change on fingerprint enrollment, or removal of all
                 // enrolled fingerprints, allowing the key to remain valid.
-                sid = getRootSid();
+                sids.add(getRootSid());
             }
 
-            args.addUnsignedLong(
-                    KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(sid));
-            args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
+            for (int i = 0; i < sids.size(); i++) {
+                args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
+                        KeymasterArguments.toUint64(sids.get(i)));
+            }
+            args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_BIOMETRIC);
+
             if (spec.isUserAuthenticationValidWhileOnBody()) {
                 throw new ProviderException("Key validity extension while device is on-body is not "
                         + "supported for keys requiring fingerprint authentication");
@@ -166,7 +177,7 @@
             args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID,
                     KeymasterArguments.toUint64(sid));
             args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE,
-                    KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT);
+                    KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_BIOMETRIC);
             args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT,
                     spec.getUserAuthenticationValidityDurationSeconds());
             if (spec.isUserAuthenticationValidWhileOnBody()) {
diff --git a/keystore/java/android/security/keystore/KeystoreResponse.java b/keystore/java/android/security/keystore/KeystoreResponse.java
new file mode 100644
index 0000000..3a229cb
--- /dev/null
+++ b/keystore/java/android/security/keystore/KeystoreResponse.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 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.security.keystore;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelFormatException;
+
+/**
+ * The Java side of the KeystoreResponse.
+ * <p>
+ * Serialization code for this and subclasses must be kept in sync with system/security/keystore.
+ * @hide
+ */
+public class KeystoreResponse implements Parcelable {
+    public final int error_code_;
+    public final String error_msg_;
+
+    public static final Parcelable.Creator<KeystoreResponse> CREATOR = new
+            Parcelable.Creator<KeystoreResponse>() {
+                @Override
+                public KeystoreResponse createFromParcel(Parcel in) {
+                    final int error_code = in.readInt();
+                    final String error_msg = in.readString();
+                    return new KeystoreResponse(error_code, error_msg);
+                }
+
+                @Override
+                public KeystoreResponse[] newArray(int size) {
+                    return new KeystoreResponse[size];
+                }
+            };
+
+    protected KeystoreResponse(int error_code, String error_msg) {
+        this.error_code_ = error_code;
+        this.error_msg_ = error_msg;
+    }
+
+    /**
+     * @return the error_code_
+     */
+    public final int getErrorCode() {
+        return error_code_;
+    }
+
+    /**
+     * @return the error_msg_
+     */
+    public final String getErrorMessage() {
+        return error_msg_;
+    }
+
+    
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(error_code_);
+        out.writeString(error_msg_);
+    }
+}
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 92efb6b..98af3eb 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -59,8 +59,6 @@
         "ZipFileRO.cpp",
         "ZipUtils.cpp",
     ],
-    // Allow implicit fallthroughs in Locale.cpp and ResourceTypes.cpp until they are fixed.
-    cflags: ["-Wno-implicit-fallthrough"],
     export_include_dirs: ["include"],
     export_shared_lib_headers: ["libz"],
     target: {
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 843c146..1cb0d25 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -72,7 +72,7 @@
 
 const char* AssetManager::RESOURCES_FILENAME = "resources.arsc";
 const char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
-const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
+const char* AssetManager::VENDOR_OVERLAY_DIR = "/vendor/overlay";
 const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay";
 const char* AssetManager::PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay";
 const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 288ba32..9e69488 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -162,6 +162,13 @@
     LOG(INFO) << base::StringPrintf("PG (%02x): ",
                                     package_group.dynamic_ref_table.mAssignedPackageId)
               << list;
+
+    for (size_t i = 0; i < 256; i++) {
+      if (package_group.dynamic_ref_table.mLookupTable[i] != 0) {
+        LOG(INFO) << base::StringPrintf("    e[0x%02x] -> 0x%02x", (uint8_t) i,
+                                        package_group.dynamic_ref_table.mLookupTable[i]);
+      }
+    }
   }
 }
 
diff --git a/libs/androidfw/Locale.cpp b/libs/androidfw/Locale.cpp
index 2870066..3eedda8 100644
--- a/libs/androidfw/Locale.cpp
+++ b/libs/androidfw/Locale.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "android-base/macros.h"
 #include "androidfw/Locale.h"
 #include "androidfw/Util.h"
 
@@ -162,6 +163,7 @@
           set_script(subtags[1].c_str());
           break;
         }
+        FALLTHROUGH_INTENDED;
       case 5:
       case 6:
       case 7:
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index dc4a0a7..76db18d 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -29,6 +29,7 @@
 #include <memory>
 #include <type_traits>
 
+#include <android-base/macros.h>
 #include <androidfw/ByteBucketArray.h>
 #include <androidfw/ResourceTypes.h>
 #include <androidfw/TypeWrappers.h>
@@ -3073,6 +3074,7 @@
                }
                break;
            }
+           FALLTHROUGH_INTENDED;
        case 5:
        case 6:
        case 7:
@@ -6998,18 +7000,28 @@
 }
 
 status_t DynamicRefTable::lookupResourceValue(Res_value* value) const {
-    uint8_t resolvedType;
+    uint8_t resolvedType = Res_value::TYPE_REFERENCE;
+    switch (value->dataType) {
+        case Res_value::TYPE_ATTRIBUTE:
+            resolvedType = Res_value::TYPE_ATTRIBUTE;
+            FALLTHROUGH_INTENDED;
+        case Res_value::TYPE_REFERENCE:
+            // Only resolve non-dynamic references and attributes if the package is loaded as a
+            // library or if a shared library is attempting to retrieve its own resource
+            if (!(mAppAsLib || (Res_GETPACKAGE(value->data) + 1) == 0)) {
+                return NO_ERROR;
+            }
 
-    if (value->dataType == Res_value::TYPE_ATTRIBUTE
-        || value->dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE) {
-        resolvedType = Res_value::TYPE_ATTRIBUTE;
-
-    } else if (value->dataType == Res_value::TYPE_REFERENCE
-               || value->dataType == Res_value::TYPE_DYNAMIC_REFERENCE) {
-        resolvedType = Res_value::TYPE_REFERENCE;
-
-    } else {
-        return NO_ERROR;
+        // If the package is loaded as shared library, the resource reference
+        // also need to be fixed.
+        break;
+        case Res_value::TYPE_DYNAMIC_ATTRIBUTE:
+            resolvedType = Res_value::TYPE_ATTRIBUTE;
+            FALLTHROUGH_INTENDED;
+        case Res_value::TYPE_DYNAMIC_REFERENCE:
+            break;
+        default:
+            return NO_ERROR;
     }
 
     status_t err = lookupResourceId(&value->data);
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index cdb87bc..e22e2d2 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -59,13 +59,13 @@
 public:
     static const char* RESOURCES_FILENAME;
     static const char* IDMAP_BIN;
-    static const char* OVERLAY_DIR;
+    static const char* VENDOR_OVERLAY_DIR;
     static const char* PRODUCT_OVERLAY_DIR;
     static const char* PRODUCT_SERVICES_OVERLAY_DIR;
     /*
      * If OVERLAY_THEME_DIR_PROPERTY is set, search for runtime resource overlay
-     * APKs in OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to
-     * OVERLAY_DIR.
+     * APKs in VENDOR_OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in
+     * addition to VENDOR_OVERLAY_DIR.
      */
     static const char* OVERLAY_THEME_DIR_PROPERTY;
     static const char* TARGET_PACKAGE_NAME;
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index a028515..59abad4 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1709,13 +1709,13 @@
 
     struct resource_name
     {
-        const char16_t* package;
+        const char16_t* package = NULL;
         size_t packageLen;
-        const char16_t* type;
-        const char* type8;
+        const char16_t* type = NULL;
+        const char* type8 = NULL;
         size_t typeLen;
-        const char16_t* name;
-        const char* name8;
+        const char16_t* name = NULL;
+        const char* name8 = NULL;
         size_t nameLen;
     };
 
diff --git a/libs/androidfw/tests/DynamicRefTable_test.cpp b/libs/androidfw/tests/DynamicRefTable_test.cpp
index df44e34..5acc46a 100644
--- a/libs/androidfw/tests/DynamicRefTable_test.cpp
+++ b/libs/androidfw/tests/DynamicRefTable_test.cpp
@@ -40,6 +40,26 @@
   EXPECT_EQ(value2.data, 0x02010000);
 };
 
+TEST(DynamicRefTableTest, LookupSharedLibSelfAttributes) {
+  // Shared library
+  DynamicRefTable shared_table(0x03, /* appAsLib */ false);
+  shared_table.addMapping(0x00, 0x03);
+  Res_value value;
+  value.dataType = Res_value::TYPE_ATTRIBUTE;
+  value.data = 0x00010000;
+  ASSERT_EQ(shared_table.lookupResourceValue(&value), NO_ERROR);
+  EXPECT_EQ(value.data, 0x03010000);
+
+  // App loaded as a shared library
+  DynamicRefTable shared_app_table(0x04, /* appAsLib */ true);
+  shared_app_table.addMapping(0x7f, 0x04);
+  Res_value value2;
+  value2.dataType = Res_value::TYPE_ATTRIBUTE;
+  value2.data = 0x7f010000;
+  ASSERT_EQ(shared_app_table.lookupResourceValue(&value2), NO_ERROR);
+  EXPECT_EQ(value2.data, 0x04010000);
+};
+
 TEST(DynamicRefTableTest, LookupDynamicReferences) {
   // Shared library
   DynamicRefTable shared_table(0x2, /* appAsLib */ false);
@@ -51,24 +71,46 @@
   ASSERT_EQ(shared_table.lookupResourceValue(&value), NO_ERROR);
   EXPECT_EQ(value.data, 0x05010000);
 
-  // App loaded as a shared library
-  DynamicRefTable shared_app_table(0x2, /* appAsLib */ true);
-  shared_app_table.addMapping(0x03, 0x05);
-  shared_app_table.addMapping(0x7f, 0x2);
-  Res_value value2;
-  value2.dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
-  value2.data = 0x03010000;
-  ASSERT_EQ(shared_app_table.lookupResourceValue(&value2), NO_ERROR);
-  EXPECT_EQ(value2.data, 0x05010000);
-
   // Regular application
   DynamicRefTable app_table(0x7f, /* appAsLib */ false);
   app_table.addMapping(0x03, 0x05);
   Res_value value3;
-  value3.dataType = Res_value::TYPE_REFERENCE;
+  value3.dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
   value3.data = 0x03010000;
   ASSERT_EQ(app_table.lookupResourceValue(&value3), NO_ERROR);
   EXPECT_EQ(value3.data, 0x05010000);
 };
 
+TEST(DynamicRefTableTest, LookupDynamicAttributes) {
+// App loaded as a shared library
+  DynamicRefTable shared_app_table(0x2, /* appAsLib */ true);
+  shared_app_table.addMapping(0x03, 0x05);
+  shared_app_table.addMapping(0x7f, 0x2);
+  Res_value value2;
+  value2.dataType = Res_value::TYPE_DYNAMIC_ATTRIBUTE;
+  value2.data = 0x03010000;
+  ASSERT_EQ(shared_app_table.lookupResourceValue(&value2), NO_ERROR);
+  EXPECT_EQ(value2.data, 0x05010000);
+}
+
+TEST(DynamicRefTableTest, DoNotLookupNonDynamicReferences) {
+  // Regular application
+  DynamicRefTable app_table(0x7f, /* appAsLib */ false);
+  Res_value value;
+  value.dataType = Res_value::TYPE_REFERENCE;
+  value.data = 0x03010000;
+  ASSERT_EQ(app_table.lookupResourceValue(&value), NO_ERROR);
+  EXPECT_EQ(value.data, 0x03010000);
+};
+
+TEST(DynamicRefTableTest, DoNotLookupNonDynamicAttributes) {
+  // App with custom package id
+  DynamicRefTable custom_app_table(0x8f, /* appAsLib */ false);
+  Res_value value2;
+  value2.dataType = Res_value::TYPE_ATTRIBUTE;
+  value2.data = 0x03010000;
+  ASSERT_EQ(custom_app_table.lookupResourceValue(&value2), NO_ERROR);
+  EXPECT_EQ(value2.data, 0x03010000);
+};
+
 } // namespace android
\ No newline at end of file
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp
index 9eb4a13..26d2896 100644
--- a/libs/androidfw/tests/Idmap_test.cpp
+++ b/libs/androidfw/tests/Idmap_test.cpp
@@ -94,15 +94,15 @@
             target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_));
 
   ResTable::resource_name res_name;
-  ASSERT_TRUE(target_table_.getResourceName(R::array::integerArray1, false, &res_name));
+  ASSERT_TRUE(target_table_.getResourceName(R::array::integerArray1, true, &res_name));
 
   ASSERT_TRUE(res_name.package != NULL);
   ASSERT_TRUE(res_name.type != NULL);
-  ASSERT_TRUE(res_name.name != NULL);
+  ASSERT_TRUE(res_name.name8 != NULL);
 
   EXPECT_EQ(String16("com.android.basic"), String16(res_name.package, res_name.packageLen));
   EXPECT_EQ(String16("array"), String16(res_name.type, res_name.typeLen));
-  EXPECT_EQ(String16("integerArray1"), String16(res_name.name, res_name.nameLen));
+  EXPECT_EQ(String8("integerArray1"), String8(res_name.name8, res_name.nameLen));
 }
 
 constexpr const uint32_t kNonOverlaidResourceId = 0x7fff0000u;
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index f0053a4..17d2db71 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -176,7 +176,7 @@
         "pipeline/skia/SkiaRecordingCanvas.cpp",
         "pipeline/skia/SkiaVulkanPipeline.cpp",
         "pipeline/skia/VectorDrawableAtlas.cpp",
-        "pipeline/skia/VkFunctorDrawable.cpp",
+        "pipeline/skia/VkInteropFunctorDrawable.cpp",
         "renderstate/RenderState.cpp",
         "renderthread/CacheManager.cpp",
         "renderthread/CanvasContext.cpp",
diff --git a/libs/hwui/FrameInfoVisualizer.cpp b/libs/hwui/FrameInfoVisualizer.cpp
index 236a6b6..b04c774 100644
--- a/libs/hwui/FrameInfoVisualizer.cpp
+++ b/libs/hwui/FrameInfoVisualizer.cpp
@@ -66,6 +66,7 @@
 
 FrameInfoVisualizer::FrameInfoVisualizer(FrameInfoSource& source) : mFrameSource(source) {
     setDensity(1);
+    consumeProperties();
 }
 
 FrameInfoVisualizer::~FrameInfoVisualizer() {
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index 2ca40b9..769fce4 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -84,7 +84,7 @@
                                     const minikin::FontFakery& fakery) const {
     SkPaint skPaint;
     MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint, fakery);
-    SkPaint::FontMetrics metrics;
+    SkFontMetrics metrics;
     skPaint.getFontMetrics(&metrics);
     extent->ascent = metrics.fAscent;
     extent->descent = metrics.fDescent;
@@ -139,7 +139,7 @@
 
 uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
     uint32_t flags = paint->getFlags();
-    SkPaint::Hinting hinting = paint->getHinting();
+    unsigned hinting = static_cast<unsigned>(paint->getHinting());
     // select only flags that might affect text layout
     flags &= (SkPaint::kAntiAlias_Flag | SkPaint::kFakeBoldText_Flag | SkPaint::kLinearText_Flag |
               SkPaint::kSubpixelText_Flag | SkPaint::kEmbeddedBitmapText_Flag |
@@ -150,7 +150,7 @@
 
 void MinikinFontSkia::unpackPaintFlags(SkPaint* paint, uint32_t paintFlags) {
     paint->setFlags(paintFlags & SkPaint::kAllFlags);
-    paint->setHinting(static_cast<SkPaint::Hinting>(paintFlags >> 16));
+    paint->setHinting(static_cast<SkFontHinting>(paintFlags >> 16));
 }
 
 void MinikinFontSkia::populateSkPaint(SkPaint* paint, const MinikinFont* font,
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index d401b38..6ae5999 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -164,7 +164,11 @@
 
     if (surface) {
         mRenderThread.requireGlContext();
-        mEglSurface = mEglManager.createSurface(surface, colorMode);
+        auto newSurface = mEglManager.createSurface(surface, colorMode);
+        if (!newSurface) {
+            return false;
+        }
+        mEglSurface = newSurface.unwrap();
     }
 
     if (colorMode == ColorMode::SRGB) {
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 596b8af..45022e7 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -24,7 +24,7 @@
 #include "RenderNode.h"
 #include "pipeline/skia/AnimatedDrawables.h"
 #include "pipeline/skia/GLFunctorDrawable.h"
-#include "pipeline/skia/VkFunctorDrawable.h"
+#include "pipeline/skia/VkInteropFunctorDrawable.h"
 
 namespace android {
 namespace uirenderer {
@@ -124,8 +124,8 @@
                                              uirenderer::GlFunctorLifecycleListener* listener) {
     FunctorDrawable* functorDrawable;
     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
-        functorDrawable = mDisplayList->allocateDrawable<VkFunctorDrawable>(functor, listener,
-                asSkCanvas());
+        functorDrawable = mDisplayList->allocateDrawable<VkInteropFunctorDrawable>(functor,
+                listener, asSkCanvas());
     } else {
         functorDrawable = mDisplayList->allocateDrawable<GLFunctorDrawable>(functor, listener,
                 asSkCanvas());
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 2ca110f..a494e49 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -22,7 +22,7 @@
 #include "SkiaProfileRenderer.h"
 #include "renderstate/RenderState.h"
 #include "renderthread/Frame.h"
-#include "VkFunctorDrawable.h"
+#include "VkInteropFunctorDrawable.h"
 
 #include <SkSurface.h>
 #include <SkTypes.h>
@@ -51,7 +51,7 @@
     LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr,
                         "drawRenderNode called on a context with no surface!");
 
-    SkSurface* backBuffer = mVkManager.getBackbufferSurface(mVkSurface);
+    SkSurface* backBuffer = mVkManager.getBackbufferSurface(&mVkSurface);
     if (backBuffer == nullptr) {
         SkDebugf("failed to get backbuffer");
         return Frame(-1, -1, 0);
@@ -144,7 +144,7 @@
 }
 
 void SkiaVulkanPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) {
-    VkFunctorDrawable::vkInvokeFunctor(functor);
+    VkInteropFunctorDrawable::vkInvokeFunctor(functor);
 }
 
 sk_sp<Bitmap> SkiaVulkanPipeline::allocateHardwareBitmap(renderthread::RenderThread& renderThread,
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
similarity index 92%
rename from libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
rename to libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
index 6486ddb..a594206 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "VkFunctorDrawable.h"
+#include "VkInteropFunctorDrawable.h"
 #include <private/hwui/DrawGlInfo.h>
 
 #include "renderthread/EglManager.h"
@@ -64,7 +64,7 @@
     }
 };
 
-void VkFunctorDrawable::vkInvokeFunctor(Functor* functor) {
+void VkInteropFunctorDrawable::vkInvokeFunctor(Functor* functor) {
     ScopedDrawRequest _drawRequest{};
     sGLDrawThread->queue().runSync([&]() {
         EGLDisplay display = sEglManager.eglDisplay();
@@ -78,11 +78,11 @@
 
 #define FENCE_TIMEOUT 2000000000
 
-void VkFunctorDrawable::onDraw(SkCanvas* canvas) {
+void VkInteropFunctorDrawable::onDraw(SkCanvas* canvas) {
     ATRACE_CALL();
 
     if (canvas->getGrContext() == nullptr) {
-        SkDEBUGF(("Attempting to draw VkFunctor into an unsupported surface"));
+        SkDEBUGF(("Attempting to draw VkInteropFunctor into an unsupported surface"));
         return;
     }
 
@@ -99,10 +99,11 @@
                  ColorTypeToPixelFormat(surfaceInfo.colorType()),
                  GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER |
                          GraphicBuffer::USAGE_SW_READ_NEVER | GraphicBuffer::USAGE_HW_RENDER,
-                 std::string("VkFunctorDrawable::onDraw pid [") + std::to_string(getpid()) + "]");
+                 std::string("VkInteropFunctorDrawable::onDraw pid [") + std::to_string(getpid()) +
+                         "]");
         status_t error = mFrameBuffer->initCheck();
         if (error < 0) {
-            ALOGW("VkFunctorDrawable::onDraw() failed in GraphicBuffer.create()");
+            ALOGW("VkInteropFunctorDrawable::onDraw() failed in GraphicBuffer.create()");
             return;
         }
 
@@ -202,7 +203,7 @@
     canvas->restore();
 }
 
-VkFunctorDrawable::~VkFunctorDrawable() {
+VkInteropFunctorDrawable::~VkInteropFunctorDrawable() {
     if (mListener.get() != nullptr) {
         ScopedDrawRequest _drawRequest{};
         sGLDrawThread->queue().runSync([&]() {
@@ -211,7 +212,7 @@
     }
 }
 
-void VkFunctorDrawable::syncFunctor() const {
+void VkInteropFunctorDrawable::syncFunctor() const {
     ScopedDrawRequest _drawRequest{};
     sGLDrawThread->queue().runSync([&]() {
          (*mFunctor)(DrawGlInfo::kModeSync, nullptr);
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.h b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h
similarity index 86%
rename from libs/hwui/pipeline/skia/VkFunctorDrawable.h
rename to libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h
index e37f6fb..3269cfb 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.h
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.h
@@ -30,11 +30,12 @@
  * This drawable wraps a Vulkan functor enabling it to be recorded into a list
  * of Skia drawing commands.
  */
-class VkFunctorDrawable : public FunctorDrawable {
+class VkInteropFunctorDrawable : public FunctorDrawable {
 public:
-    VkFunctorDrawable(Functor* functor, GlFunctorLifecycleListener* listener, SkCanvas* canvas)
+    VkInteropFunctorDrawable(Functor* functor, GlFunctorLifecycleListener* listener,
+            SkCanvas* canvas)
             : FunctorDrawable(functor, listener, canvas) {}
-    virtual ~VkFunctorDrawable();
+    virtual ~VkInteropFunctorDrawable();
 
     void syncFunctor() const override;
 
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 92a749f..f1a522e 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -180,14 +180,20 @@
     }
 }
 
-void CanvasContext::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
-    mLightGeometry.radius = lightRadius;
+void CanvasContext::allocateBuffers() {
+    if (mNativeSurface) {
+        mNativeSurface->allocateBuffers();
+    }
+}
+
+void CanvasContext::setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
     mLightInfo.ambientShadowAlpha = ambientShadowAlpha;
     mLightInfo.spotShadowAlpha = spotShadowAlpha;
 }
 
-void CanvasContext::setLightCenter(const Vector3& lightCenter) {
+void CanvasContext::setLightGeometry(const Vector3& lightCenter, float lightRadius) {
     mLightGeometry.center = lightCenter;
+    mLightGeometry.radius = lightRadius;
 }
 
 void CanvasContext::setOpaque(bool opaque) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2307ee4..70be4a6 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -113,9 +113,10 @@
     bool pauseSurface();
     void setStopped(bool stopped);
     bool hasSurface() { return mNativeSurface.get(); }
+    void allocateBuffers();
 
-    void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
-    void setLightCenter(const Vector3& lightCenter);
+    void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+    void setLightGeometry(const Vector3& lightCenter, float lightRadius);
     void setOpaque(bool opaque);
     void setWideGamut(bool wideGamut);
     bool makeCurrent();
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index d4ffddd..65ced6a 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -261,7 +261,7 @@
     }
 }
 
-EGLSurface EglManager::createSurface(EGLNativeWindowType window, ColorMode colorMode) {
+Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window, ColorMode colorMode) {
     LOG_ALWAYS_FATAL_IF(!hasEglContext(), "Not initialized");
 
     bool wideColorGamut = colorMode == ColorMode::WideColorGamut && EglExtensions.glColorSpace &&
@@ -311,9 +311,9 @@
 
     EGLSurface surface = eglCreateWindowSurface(
             mEglDisplay, wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
-    LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
-                        "Failed to create EGLSurface for window %p, eglErr = %s", (void*)window,
-                        eglErrorString());
+    if (surface == EGL_NO_SURFACE) {
+        return Error<EGLint> { eglGetError() };
+    }
 
     if (mSwapBehavior != SwapBehavior::Preserved) {
         LOG_ALWAYS_FATAL_IF(eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR,
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 55c81d4..2a44f7e 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -25,6 +25,7 @@
 #include <ui/GraphicBuffer.h>
 #include <utils/StrongPointer.h>
 #include "IRenderPipeline.h"
+#include "utils/Result.h"
 
 namespace android {
 namespace uirenderer {
@@ -47,7 +48,7 @@
 
     bool hasEglContext();
 
-    EGLSurface createSurface(EGLNativeWindowType window, ColorMode colorMode);
+    Result<EGLSurface, EGLint> createSurface(EGLNativeWindowType window, ColorMode colorMode);
     void destroySurface(EGLSurface surface);
 
     void destroy();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 54219b5..085812a 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -80,22 +80,16 @@
     mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
 }
 
-void RenderProxy::initialize(const sp<Surface>& surface) {
+void RenderProxy::setSurface(const sp<Surface>& surface) {
     mRenderThread.queue().post(
             [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
 }
 
-void RenderProxy::allocateBuffers(const sp<Surface>& surface) {
-    mRenderThread.queue().post(
-            [ surf = surface ]() mutable { surf->allocateBuffers(); });
+void RenderProxy::allocateBuffers() {
+    mRenderThread.queue().post([=]() { mContext->allocateBuffers(); });
 }
 
-void RenderProxy::updateSurface(const sp<Surface>& surface) {
-    mRenderThread.queue().post(
-            [ this, surf = surface ]() mutable { mContext->setSurface(std::move(surf)); });
-}
-
-bool RenderProxy::pauseSurface(const sp<Surface>& surface) {
+bool RenderProxy::pause() {
     return mRenderThread.queue().runSync([this]() -> bool { return mContext->pauseSurface(); });
 }
 
@@ -103,13 +97,13 @@
     mRenderThread.queue().runSync([this, stopped]() { mContext->setStopped(stopped); });
 }
 
-void RenderProxy::setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
+void RenderProxy::setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
     mRenderThread.queue().post(
-            [=]() { mContext->setup(lightRadius, ambientShadowAlpha, spotShadowAlpha); });
+            [=]() { mContext->setLightAlpha(ambientShadowAlpha, spotShadowAlpha); });
 }
 
-void RenderProxy::setLightCenter(const Vector3& lightCenter) {
-    mRenderThread.queue().post([=]() { mContext->setLightCenter(lightCenter); });
+void RenderProxy::setLightGeometry(const Vector3& lightCenter, float lightRadius) {
+    mRenderThread.queue().post([=]() { mContext->setLightGeometry(lightCenter, lightRadius); });
 }
 
 void RenderProxy::setOpaque(bool opaque) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index d29fcc4..6668c58 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -69,13 +69,12 @@
     ANDROID_API bool loadSystemProperties();
     ANDROID_API void setName(const char* name);
 
-    ANDROID_API void initialize(const sp<Surface>& surface);
-    ANDROID_API void allocateBuffers(const sp<Surface>& surface);
-    ANDROID_API void updateSurface(const sp<Surface>& surface);
-    ANDROID_API bool pauseSurface(const sp<Surface>& surface);
+    ANDROID_API void setSurface(const sp<Surface>& surface);
+    ANDROID_API void allocateBuffers();
+    ANDROID_API bool pause();
     ANDROID_API void setStopped(bool stopped);
-    ANDROID_API void setup(float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
-    ANDROID_API void setLightCenter(const Vector3& lightCenter);
+    ANDROID_API void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
+    ANDROID_API void setLightGeometry(const Vector3& lightCenter, float lightRadius);
     ANDROID_API void setOpaque(bool opaque);
     ANDROID_API void setWideGamut(bool wideGamut);
     ANDROID_API int64_t* frameInfo();
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 62f704b..2384f95 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -74,7 +74,7 @@
     PREVENT_COPY_AND_ASSIGN(RenderThread);
 
 public:
-    // Sets a callback that fires before any RenderThread setup has occured.
+    // Sets a callback that fires before any RenderThread setup has occurred.
     ANDROID_API static void setOnStartHook(void (*onStartHook)());
 
     WorkQueue& queue() { return ThreadBase::queue(); }
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index f96b1f8..d84ec85 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -16,6 +16,8 @@
 
 #include "VulkanManager.h"
 
+#include <gui/Surface.h>
+
 #include "Properties.h"
 #include "RenderThread.h"
 #include "renderstate/RenderState.h"
@@ -452,7 +454,20 @@
     return backbuffer;
 }
 
-SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface* surface) {
+SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) {
+    // Recreate VulkanSurface, if ANativeWindow has been resized.
+    VulkanSurface* surface = *surfaceOut;
+    int windowWidth = 0, windowHeight = 0;
+    ANativeWindow* window = surface->mNativeWindow;
+    window->query(window, NATIVE_WINDOW_WIDTH, &windowWidth);
+    window->query(window, NATIVE_WINDOW_HEIGHT, &windowHeight);
+    if (windowWidth != surface->mWindowWidth || windowHeight != surface->mWindowHeight) {
+        ColorMode colorMode = surface->mColorMode;
+        destroySurface(surface);
+        *surfaceOut = createSurface(window, colorMode);
+        surface = *surfaceOut;
+    }
+
     VulkanSurface::BackbufferInfo* backbuffer = getAvailableBackbuffer(surface);
     SkASSERT(backbuffer);
 
@@ -717,6 +732,8 @@
         extent.height = caps.minImageExtent.height;
     }
     SkASSERT(extent.height <= caps.maxImageExtent.height);
+    surface->mWindowWidth = extent.width;
+    surface->mWindowHeight = extent.height;
 
     uint32_t imageCount = caps.minImageCount + 2;
     if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) {
@@ -814,7 +831,7 @@
         return nullptr;
     }
 
-    VulkanSurface* surface = new VulkanSurface(colorMode);
+    VulkanSurface* surface = new VulkanSurface(colorMode, window);
 
     VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
     memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 6702649..8594a1b 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -38,7 +38,8 @@
 
 class VulkanSurface {
 public:
-    VulkanSurface(ColorMode colorMode) : mColorMode(colorMode) {}
+    VulkanSurface(ColorMode colorMode, ANativeWindow* window)
+            : mColorMode(colorMode), mNativeWindow(window) {}
 
     sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; }
 
@@ -75,6 +76,9 @@
     ImageInfo* mImageInfos;
     uint16_t mCurrentTime = 0;
     ColorMode mColorMode;
+    ANativeWindow* mNativeWindow;
+    int mWindowWidth = 0;
+    int mWindowHeight = 0;
 };
 
 // This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
@@ -109,7 +113,7 @@
     // Returns an SkSurface which wraps the next image returned from vkAcquireNextImageKHR. It also
     // will transition the VkImage from a present layout to color attachment so that it can be used
     // by the client for drawing.
-    SkSurface* getBackbufferSurface(VulkanSurface* surface);
+    SkSurface* getBackbufferSurface(VulkanSurface** surface);
 
     // Presents the current VkImage.
     void swapBuffers(VulkanSurface* surface);
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index fb1fde2..3d50d2d 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -232,9 +232,9 @@
         return;
     }
     dprintf(fd, "\nPackage: %s", proto->package_name().c_str());
-    dprintf(fd, "\nVersion: %" PRId64, proto->version_code());
-    dprintf(fd, "\nStats since: %" PRId64 "ns", proto->stats_start());
-    dprintf(fd, "\nStats end: %" PRId64 "ns", proto->stats_end());
+    dprintf(fd, "\nVersion: %lld", proto->version_code());
+    dprintf(fd, "\nStats since: %lldns", proto->stats_start());
+    dprintf(fd, "\nStats end: %lldns", proto->stats_end());
     auto summary = proto->summary();
     dprintf(fd, "\nTotal frames rendered: %d", summary.total_frames());
     dprintf(fd, "\nJanky frames: %d (%.2f%%)", summary.janky_frames(),
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 5f5a92e..5fa008b 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -132,10 +132,10 @@
     ContextFactory factory;
     std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, rootNode.get(), &factory));
     proxy->loadSystemProperties();
-    proxy->initialize(surface);
+    proxy->setSurface(surface);
     float lightX = width / 2.0;
-    proxy->setup(dp(800.0f), 255 * 0.075, 255 * 0.15);
-    proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)});
+    proxy->setLightAlpha(255 * 0.075, 255 * 0.15);
+    proxy->setLightGeometry((Vector3){lightX, dp(-200.0f), dp(800.0f)}, dp(800.0f));
 
     // Do a few cold runs then reset the stats so that the caches are all hot
     int warmupFrameCount = 5;
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index 0795208..a6073eb 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -321,7 +321,7 @@
     // Check that the VD is in the dislay list, and the layer update queue contains the correct
     // damage rect.
     EXPECT_TRUE(rootNode->getDisplayList()->hasVectorDrawables());
-    EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
+    ASSERT_FALSE(info.layerUpdateQueue->entries().empty());
     EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode.get());
     EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
     canvasContext->destroy();
diff --git a/libs/hwui/utils/Result.h b/libs/hwui/utils/Result.h
new file mode 100644
index 0000000..7f33f2e
--- /dev/null
+++ b/libs/hwui/utils/Result.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <variant>
+#include <log/log.h>
+
+namespace android::uirenderer {
+
+template <typename E>
+struct Error {
+    E error;
+};
+
+template <typename R, typename E>
+class Result {
+public:
+    Result(const R& r) : result(std::forward<R>(r)) {}
+    Result(R&& r) : result(std::forward<R>(r)) {}
+    Result(Error<E>&& error) : result(std::forward<Error<E>>(error)) {}
+
+    operator bool() const {
+        return result.index() == 0;
+    }
+
+    R unwrap() const {
+        LOG_ALWAYS_FATAL_IF(result.index() == 1, "unwrap called on error value!");
+        return std::get<R>(result);
+    }
+
+    E error() const {
+        LOG_ALWAYS_FATAL_IF(result.index() == 0, "No error to get from Result");
+        return std::get<Error<E>>(result).error;
+    }
+
+private:
+    std::variant<R, Error<E>> result;
+};
+
+}; // namespace android::uirenderer
diff --git a/libs/protoutil/include/android/util/ProtoOutputStream.h b/libs/protoutil/include/android/util/ProtoOutputStream.h
index 0377426..ad76559 100644
--- a/libs/protoutil/include/android/util/ProtoOutputStream.h
+++ b/libs/protoutil/include/android/util/ProtoOutputStream.h
@@ -97,7 +97,6 @@
     bool write(uint64_t fieldId, double val);
     bool write(uint64_t fieldId, float val);
     bool write(uint64_t fieldId, int val);
-    bool write(uint64_t fieldId, long val);
     bool write(uint64_t fieldId, long long val);
     bool write(uint64_t fieldId, bool val);
     bool write(uint64_t fieldId, std::string val);
diff --git a/libs/protoutil/src/ProtoOutputStream.cpp b/libs/protoutil/src/ProtoOutputStream.cpp
index 0c62d52..ff3fad6 100644
--- a/libs/protoutil/src/ProtoOutputStream.cpp
+++ b/libs/protoutil/src/ProtoOutputStream.cpp
@@ -116,34 +116,6 @@
 }
 
 bool
-ProtoOutputStream::write(uint64_t fieldId, long val)
-{
-    if (mCompact) return false;
-    const uint32_t id = (uint32_t)fieldId;
-    switch (fieldId & FIELD_TYPE_MASK) {
-        case FIELD_TYPE_DOUBLE:   writeDoubleImpl(id, (double)val);           break;
-        case FIELD_TYPE_FLOAT:    writeFloatImpl(id, (float)val);             break;
-        case FIELD_TYPE_INT64:    writeInt64Impl(id, (long long)val);         break;
-        case FIELD_TYPE_UINT64:   writeUint64Impl(id, (uint64_t)val);         break;
-        case FIELD_TYPE_INT32:    writeInt32Impl(id, (int)val);               break;
-        case FIELD_TYPE_FIXED64:  writeFixed64Impl(id, (uint64_t)val);        break;
-        case FIELD_TYPE_FIXED32:  writeFixed32Impl(id, (uint32_t)val);        break;
-        case FIELD_TYPE_UINT32:   writeUint32Impl(id, (uint32_t)val);         break;
-        case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int)val);            break;
-        case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val);      break;
-        case FIELD_TYPE_SINT32:   writeZigzagInt32Impl(id, (int)val);         break;
-        case FIELD_TYPE_SINT64:   writeZigzagInt64Impl(id, (long long)val);   break;
-        case FIELD_TYPE_ENUM:     writeEnumImpl(id, (int)val);                break;
-        case FIELD_TYPE_BOOL:     writeBoolImpl(id, val != 0);                break;
-        default:
-            ALOGW("Field type %d is not supported when writing long val.",
-                    (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
-            return false;
-    }
-    return true;
-}
-
-bool
 ProtoOutputStream::write(uint64_t fieldId, long long val)
 {
     return internalWrite(fieldId, val, "long long");
diff --git a/libs/services/src/os/StatsLogEventWrapper.cpp b/libs/services/src/os/StatsLogEventWrapper.cpp
index a1a6d9f..04c4629 100644
--- a/libs/services/src/os/StatsLogEventWrapper.cpp
+++ b/libs/services/src/os/StatsLogEventWrapper.cpp
@@ -85,9 +85,6 @@
       case StatsLogValue::FLOAT:
         mElements.push_back(StatsLogValue(in->readFloat()));
         break;
-      case StatsLogValue::DOUBLE:
-        mElements.push_back(StatsLogValue(in->readDouble()));
-        break;
       case StatsLogValue::STORAGE:
         mElements.push_back(StatsLogValue());
         mElements.back().setType(StatsLogValue::STORAGE);
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 2152e1e..f179bc3 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -16,8 +16,8 @@
 
 package android.location;
 
-import android.annotation.TestApi;
 import android.annotation.IntDef;
+import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -685,6 +685,12 @@
      *
      * <p>This includes ensuring that all half-cycle ambiguities are resolved before this value is
      * reported as {@link #ADR_STATE_VALID}.
+     *
+     * <p>The alignment of the phase measurement will not be adjusted by the receiver so the
+     * in-phase and quadrature phase components will have a quarter cycle offset as they do when
+     * transmitted from the satellites. If the measurement is from a combination of the in-phase
+     * and quadrature phase components, then the alignment of the phase measurement will be aligned
+     * to the in-phase component.
      */
     public double getAccumulatedDeltaRangeMeters() {
         return mAccumulatedDeltaRangeMeters;
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 1276881..b5d835a 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -120,4 +120,18 @@
 
     // used by gts tests to verify throttling whitelist
     String[] getBackgroundThrottlingWhitelist();
+
+    /**
+     * Allow the {@link android.location.LocationManager#getNetworkProviderPackage location
+     * provider} to start the UI to modify the location permission for a package.
+     *
+     * <p>Can only be called by the location provider.
+     *
+     * @param packageName The package the permission belongs to
+     * @param permission The (individual) permission to switch
+     *
+     * @return A pending intent that starts the permission management UI or {@code null} if the
+     *         intent cannot be created
+     */
+    PendingIntent createManageLocationPermissionIntent(in String packageName, in String permission);
 }
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index b1968ba..02680ab 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -22,6 +22,7 @@
 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
@@ -43,7 +44,9 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Log;
+
 import com.android.internal.location.ProviderProperties;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -2393,4 +2396,29 @@
             return null;
         }
     }
+
+    /**
+     * Allow the {@link android.location.LocationManager#getNetworkProviderPackage location
+     * provider} to start the UI to modify the location permission for a package.
+     *
+     * <p>Can only be called by the location provider.
+     *
+     * @param packageName The package the permission belongs to
+     * @param permission The (individual) location permission to switch
+     *
+     * @return A one-shot pending intent that starts the permission management UI or {@code null} if
+     *         the intent cannot be created
+     *
+     * @hide
+     */
+    @SystemApi
+    public @Nullable PendingIntent createManageLocationPermissionIntent(@NonNull String packageName,
+            @NonNull String permission) {
+        try {
+            return mService.createManageLocationPermissionIntent(packageName, permission);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+            return null;
+        }
+    }
 }
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index 8a02a82..057a4ae 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -20,9 +20,12 @@
 import android.os.connectivity.GpsBatteryStats;
 import android.os.SystemProperties;
 
+import android.server.location.ServerLocationProtoEnums;
+
 import android.text.format.DateUtils;
 import android.util.Base64;
 import android.util.Log;
+import android.util.StatsLog;
 import android.util.TimeUtils;
 
 import java.util.Arrays;
@@ -39,11 +42,17 @@
 
   private static final String TAG = GnssMetrics.class.getSimpleName();
 
+  /* Constant which indicates GPS signal quality is as yet unknown */
+  public static final int GPS_SIGNAL_QUALITY_UNKNOWN =
+          ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_UNKNOWN; // -1
+
   /* Constant which indicates GPS signal quality is poor */
-  public static final int GPS_SIGNAL_QUALITY_POOR = 0;
+  public static final int GPS_SIGNAL_QUALITY_POOR =
+      ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_POOR; // 0
 
   /* Constant which indicates GPS signal quality is good */
-  public static final int GPS_SIGNAL_QUALITY_GOOD = 1;
+  public static final int GPS_SIGNAL_QUALITY_GOOD =
+      ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_GOOD; // 1
 
   /* Number of GPS signal quality levels */
   public static final int NUM_GPS_SIGNAL_QUALITY_LEVELS = GPS_SIGNAL_QUALITY_GOOD + 1;
@@ -329,11 +338,15 @@
     /* Last reported Top Four Average CN0 */
     private double mLastAverageCn0;
 
+    /* Last reported signal quality bin (based on Top Four Average CN0) */
+    private int mLastSignalLevel;
+
     public GnssPowerMetrics(IBatteryStats stats) {
       mBatteryStats = stats;
       // Used to initialize the variable to a very small value (unachievable in practice) so that
       // the first CNO report will trigger an update to BatteryStats
       mLastAverageCn0 = -100.0;
+      mLastSignalLevel = GPS_SIGNAL_QUALITY_UNKNOWN;
     }
 
     /**
@@ -384,8 +397,13 @@
       if (Math.abs(avgCn0 - mLastAverageCn0) < REPORTING_THRESHOLD_DB_HZ) {
         return;
       }
+      int signalLevel = getSignalLevel(avgCn0);
+      if (signalLevel != mLastSignalLevel) {
+        StatsLog.write(StatsLog.GPS_SIGNAL_QUALITY_CHANGED, signalLevel);
+        mLastSignalLevel = signalLevel;
+      }
       try {
-        mBatteryStats.noteGpsSignalQuality(getSignalLevel(avgCn0));
+        mBatteryStats.noteGpsSignalQuality(signalLevel);
         mLastAverageCn0 = avgCn0;
       } catch (Exception e) {
         Log.w(TAG, "Exception", e);
diff --git a/media/java/android/media/AudioPresentation.java b/media/java/android/media/AudioPresentation.java
index 1cc650b..823af65 100644
--- a/media/java/android/media/AudioPresentation.java
+++ b/media/java/android/media/AudioPresentation.java
@@ -18,7 +18,6 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.TestApi;
 import android.icu.util.ULocale;
 
 import java.lang.annotation.Retention;
@@ -172,6 +171,10 @@
         return localeLabels;
     }
 
+    private Map<ULocale, String> getULabels() {
+        return mLabels;
+    }
+
     /**
      * @return the locale corresponding to audio presentation's ISO 639-1/639-2 language code.
      */
@@ -231,17 +234,24 @@
         AudioPresentation obj = (AudioPresentation) o;
         return mPresentationId == obj.getPresentationId()
                 && mProgramId == obj.getProgramId()
-                && mLanguage == obj.getULocale()
+                && mLanguage.equals(obj.getULocale())
                 && mMasteringIndication == obj.getMasteringIndication()
                 && mAudioDescriptionAvailable == obj.hasAudioDescription()
                 && mSpokenSubtitlesAvailable == obj.hasSpokenSubtitles()
                 && mDialogueEnhancementAvailable == obj.hasDialogueEnhancement()
-                && mLabels.equals(obj.getLabels());
+                && mLabels.equals(obj.getULabels());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(mPresentationId);
+        return Objects.hash(mPresentationId,
+                mProgramId,
+                mLanguage.hashCode(),
+                mMasteringIndication,
+                mAudioDescriptionAvailable,
+                mSpokenSubtitlesAvailable,
+                mDialogueEnhancementAvailable,
+                mLabels.hashCode());
     }
 
     /**
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 3ec595d..d37f8ab 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -16,23 +16,13 @@
 
 package android.media;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.WeakReference;
-import java.lang.Math;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.NioUtils;
-import java.util.LinkedList;
-import java.util.concurrent.Executor;
-
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
-import android.os.Build;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -43,6 +33,15 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.NioUtils;
+import java.util.LinkedList;
+import java.util.concurrent.Executor;
+
 /**
  * The AudioTrack class manages and plays a single audio resource for Java applications.
  * It allows streaming of PCM audio buffers to the audio sink for playback. This is
@@ -372,6 +371,10 @@
      */
     private int mAudioFormat;   // initialized by all constructors via audioParamCheck()
     /**
+     * The AudioAttributes used in configuration.
+     */
+    private AudioAttributes mConfiguredAudioAttributes;
+    /**
      * Audio session ID
      */
     private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
@@ -571,6 +574,8 @@
         super(attributes, AudioPlaybackConfiguration.PLAYER_TYPE_JAM_AUDIOTRACK);
         // mState already == STATE_UNINITIALIZED
 
+        mConfiguredAudioAttributes = attributes; // object copy not needed, immutable.
+
         if (format == null) {
             throw new IllegalArgumentException("Illegal null AudioFormat");
         }
@@ -1302,6 +1307,23 @@
     }
 
     /**
+     * Returns the {@link AudioAttributes} used in configuration.
+     * If a {@code streamType} is used instead of an {@code AudioAttributes}
+     * to configure the AudioTrack
+     * (the use of {@code streamType} for configuration is deprecated),
+     * then the {@code AudioAttributes}
+     * equivalent to the {@code streamType} is returned.
+     * @return The {@code AudioAttributes} used to configure the AudioTrack.
+     * @throws IllegalStateException If the track is not initialized.
+     */
+    public @NonNull AudioAttributes getAudioAttributes() {
+        if (mState == STATE_UNINITIALIZED || mConfiguredAudioAttributes == null) {
+            throw new IllegalStateException("track not initialized");
+        }
+        return mConfiguredAudioAttributes;
+    }
+
+    /**
      * Returns the configured audio data encoding. See {@link AudioFormat#ENCODING_PCM_8BIT},
      * {@link AudioFormat#ENCODING_PCM_16BIT}, and {@link AudioFormat#ENCODING_PCM_FLOAT}.
      */
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index 12352e7..ce631a433 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -104,7 +104,7 @@
         @Override
         protected IMediaCasService create() {
             try {
-                return IMediaCasService.getService();
+                return IMediaCasService.getService(true /*wait*/);
             } catch (RemoteException e) {}
             return null;
         }
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index ee12b91..cdbc7b44 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -418,9 +418,6 @@
 
         /**
          * Returns the status code for the key
-         * @return one of {@link #STATUS_USABLE}, {@link #STATUS_EXPIRED},
-         * {@link #STATUS_OUTPUT_NOT_ALLOWED}, {@link #STATUS_PENDING}
-         * or {@link #STATUS_INTERNAL_ERROR}.
          */
         @KeyStatusCode
         public int getStatusCode() { return mStatusCode; }
@@ -654,13 +651,7 @@
      * can be queried using {@link #getSecurityLevel}. A session
      * ID is returned.
      *
-     * @param level the new security level, one of
-     * {@link #SECURITY_LEVEL_SW_SECURE_CRYPTO},
-     * {@link #SECURITY_LEVEL_SW_SECURE_DECODE},
-     * {@link #SECURITY_LEVEL_HW_SECURE_CRYPTO},
-     * {@link #SECURITY_LEVEL_HW_SECURE_DECODE} or
-     * {@link #SECURITY_LEVEL_HW_SECURE_ALL}.
-     *
+     * @param level the new security level
      * @throws NotProvisionedException if provisioning is needed
      * @throws ResourceBusyException if required resources are in use
      * @throws IllegalArgumentException if the requested security level is
@@ -790,9 +781,6 @@
 
         /**
          * Get the type of the request
-         * @return one of {@link #REQUEST_TYPE_INITIAL},
-         * {@link #REQUEST_TYPE_RENEWAL}, {@link #REQUEST_TYPE_RELEASE},
-         * {@link #REQUEST_TYPE_NONE} or {@link #REQUEST_TYPE_UPDATE}
          */
         @RequestType
         public int getRequestType() { return mRequestType; }
@@ -979,6 +967,86 @@
             throws DeniedByServerException;
 
     /**
+     * The keys in an offline license allow protected content to be played even
+     * if the device is not connected to a network. Offline licenses are stored
+     * on the device after a key request/response exchange when the key request
+     * KeyType is OFFLINE. Normally each app is responsible for keeping track of
+     * the keySetIds it has created. If an app loses the keySetId for any stored
+     * licenses that it created, however, it must be able to recover the stored
+     * keySetIds so those licenses can be removed when they expire or when the
+     * app is uninstalled.
+     * <p>
+     * This method returns a list of the keySetIds for all offline licenses.
+     * The offline license keySetId may be used to query the status of an
+     * offline license with {@link #getOfflineLicenseState} or remove it with
+     * {@link #removeOfflineLicense}.
+     *
+     * @return a list of offline license keySetIds
+     */
+    @NonNull
+    public native List<byte[]> getOfflineLicenseKeySetIds();
+
+    /**
+     * Normally offline licenses are released using a key request/response
+     * exchange using {@link #getKeyRequest} where the key type is
+     * KEY_TYPE_RELEASE, followed by {@link #provideKeyResponse}. This allows
+     * the server to cryptographically confirm that the license has been removed
+     * and then adjust the count of offline licenses allocated to the device.
+     * <p>
+     * In some exceptional situations it may be necessary to directly remove
+     * offline licenses without notifying the server, which may be performed
+     * using this method.
+     *
+     * @param keySetId the id of the offline license to remove
+     * @throws IllegalArgumentException if the keySetId does not refer to an
+     * offline license.
+     */
+    public native void removeOfflineLicense(@NonNull byte[] keySetId);
+
+    /**
+     * Offline license state is unknown, an error occurred while trying
+     * to access it.
+     */
+    public static final int OFFLINE_LICENSE_STATE_UNKNOWN = 0;
+
+    /**
+     * Offline license state is usable, the keys may be used for decryption.
+     */
+    public static final int OFFLINE_LICENSE_USABLE = 1;
+
+    /**
+     * Offline license state is inactive, the keys have been marked for
+     * release using {@link #getKeyRequest} with KEY_TYPE_RELEASE but the
+     * key response has not been received.
+     */
+    public static final int OFFLINE_LICENSE_INACTIVE = 2;
+
+    /** @hide */
+    @IntDef({
+        OFFLINE_LICENSE_STATE_UNKNOWN,
+        OFFLINE_LICENSE_USABLE,
+        OFFLINE_LICENSE_INACTIVE,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface OfflineLicenseState {}
+
+    /**
+     * Request the state of an offline license. An offline license may be usable
+     * or inactive. The keys in a usable offline license are available for
+     * decryption. When the offline license state is inactive, the keys have
+     * been marked for release using {@link #getKeyRequest} with
+     * KEY_TYPE_RELEASE but the key response has not been received. The keys in
+     * an inactive offline license are not usable for decryption.
+     *
+     * @param keySetId selects the offline license
+     * @return the offline license state
+     * @throws IllegalArgumentException if the keySetId does not refer to an
+     * offline license.
+     */
+    @OfflineLicenseState
+    public native int getOfflineLicenseState(@NonNull byte[] keySetId);
+
+    /**
      * Secure stops are a way to enforce limits on the number of concurrent
      * streams per subscriber across devices. They provide secure monitoring of
      * the lifetime of content decryption keys in MediaDrm sessions.
@@ -1110,9 +1178,7 @@
      * enforcing compliance with HDCP requirements. Trusted enforcement of
      * HDCP policies must be handled by the DRM system.
      * <p>
-     * @return one of {@link #HDCP_LEVEL_UNKNOWN}, {@link #HDCP_NONE},
-     * {@link #HDCP_V1}, {@link #HDCP_V2}, {@link #HDCP_V2_1}, {@link #HDCP_V2_2}
-     * or {@link #HDCP_NO_DIGITAL_OUTPUT}.
+     * @return the connected HDCP level
      */
     @HdcpLevel
     public native int getConnectedHdcpLevel();
@@ -1123,9 +1189,7 @@
      * that may be connected. If multiple HDCP-capable interfaces are present,
      * it indicates the highest of the maximum HDCP levels of all interfaces.
      * <p>
-     * @return one of {@link #HDCP_LEVEL_UNKNOWN}, {@link #HDCP_NONE},
-     * {@link #HDCP_V1}, {@link #HDCP_V2}, {@link #HDCP_V2_1}, {@link #HDCP_V2_2}
-     * or {@link #HDCP_NO_DIGITAL_OUTPUT}.
+     * @return the maximum supported HDCP level
      */
     @HdcpLevel
     public native int getMaxHdcpLevel();
@@ -1215,10 +1279,7 @@
      * time a session is opened using {@link #openSession}.
      * @param sessionId the session to query.
      * <p>
-     * @return one of {@link #SECURITY_LEVEL_UNKNOWN},
-     * {@link #SECURITY_LEVEL_SW_SECURE_CRYPTO}, {@link #SECURITY_LEVEL_SW_SECURE_DECODE},
-     * {@link #SECURITY_LEVEL_HW_SECURE_CRYPTO}, {@link #SECURITY_LEVEL_HW_SECURE_DECODE} or
-     * {@link #SECURITY_LEVEL_HW_SECURE_ALL}.
+     * @return the security level of the session
      */
     @SecurityLevel
     public native int getSecurityLevel(@NonNull byte[] sessionId);
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 4919eeb..c203fa9 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -272,10 +272,12 @@
     public static final class CasInfo {
         private final int mSystemId;
         private final MediaCas.Session mSession;
+        private final byte[] mPrivateData;
 
-        CasInfo(int systemId, @Nullable MediaCas.Session session) {
+        CasInfo(int systemId, @Nullable MediaCas.Session session, @Nullable byte[] privateData) {
             mSystemId = systemId;
             mSession = session;
+            mPrivateData = privateData;
         }
 
         /**
@@ -288,10 +290,30 @@
         }
 
         /**
+         * Retrieves the private data in the CA_Descriptor associated with a track.
+         * Some CAS systems may need this to initialize the CAS plugin object. This
+         * private data can only be retrieved before a valid {@link MediaCas} object
+         * is set on the extractor.
+         * <p>
+         * @see MediaExtractor#setMediaCas
+         * <p>
+         * @return a byte array containing the private data. A null return value
+         *         indicates that the private data is unavailable. An empty array,
+         *         on the other hand, indicates that the private data is empty
+         *         (zero in length).
+         */
+        @Nullable
+        public byte[] getPrivateData() {
+            return mPrivateData;
+        }
+
+        /**
          * Retrieves the {@link MediaCas.Session} associated with a track. The
          * session is needed to initialize a descrambler in order to decode the
-         * scrambled track.
+         * scrambled track. The session object can only be retrieved after a valid
+         * {@link MediaCas} object is set on the extractor.
          * <p>
+         * @see MediaExtractor#setMediaCas
          * @see MediaDescrambler#setMediaCasSession
          * <p>
          * @return a {@link MediaCas.Session} object associated with a track.
@@ -321,6 +343,13 @@
         if (formatMap.containsKey(MediaFormat.KEY_CA_SYSTEM_ID)) {
             int systemId = ((Integer)formatMap.get(MediaFormat.KEY_CA_SYSTEM_ID)).intValue();
             MediaCas.Session session = null;
+            byte[] privateData = null;
+            if (formatMap.containsKey(MediaFormat.KEY_CA_PRIVATE_DATA)) {
+                ByteBuffer buf = (ByteBuffer) formatMap.get(MediaFormat.KEY_CA_PRIVATE_DATA);
+                buf.rewind();
+                privateData = new byte[buf.remaining()];
+                buf.get(privateData);
+            }
             if (mMediaCas != null && formatMap.containsKey(MediaFormat.KEY_CA_SESSION_ID)) {
                 ByteBuffer buf = (ByteBuffer) formatMap.get(MediaFormat.KEY_CA_SESSION_ID);
                 buf.rewind();
@@ -328,7 +357,7 @@
                 buf.get(sessionId);
                 session = mMediaCas.createFromSessionId(toByteArray(sessionId));
             }
-            return new CasInfo(systemId, session);
+            return new CasInfo(systemId, session, privateData);
         }
         return null;
     }
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index d10cbbc..5dee16e 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -919,7 +919,7 @@
      * a media track.
      * <p>
      * This key is set by {@link MediaExtractor} if the track is scrambled with a conditional
-     * access system.
+     * access system, regardless of the presence of a valid {@link MediaCas} object.
      * <p>
      * The associated value is an integer.
      * @hide
@@ -930,13 +930,25 @@
      * A key describing the {@link MediaCas.Session} object associated with a media track.
      * <p>
      * This key is set by {@link MediaExtractor} if the track is scrambled with a conditional
-     * access system.
+     * access system, after it receives a valid {@link MediaCas} object.
      * <p>
      * The associated value is a ByteBuffer.
      * @hide
      */
     public static final String KEY_CA_SESSION_ID = "ca-session-id";
 
+
+    /**
+     * A key describing the private data in the CA_descriptor associated with a media track.
+     * <p>
+     * This key is set by {@link MediaExtractor} if the track is scrambled with a conditional
+     * access system, before it receives a valid {@link MediaCas} object.
+     * <p>
+     * The associated value is a ByteBuffer.
+     * @hide
+     */
+    public static final String KEY_CA_PRIVATE_DATA = "ca-private-data";
+
     /* package private */ MediaFormat(Map<String, Object> map) {
         mMap = map;
     }
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index b51caa5..a80511a 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -21,25 +21,59 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.content.ContentResolver;
 import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
+import android.media.MediaPlayer2Proto.PlayerMessage;
+import android.media.MediaPlayer2Proto.Value;
 import android.net.Uri;
 import android.os.Handler;
-import android.os.Parcel;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
 import android.os.PersistableBundle;
+import android.os.PowerManager;
+import android.util.Log;
+import android.util.Pair;
 import android.view.Surface;
 import android.view.SurfaceHolder;
 
+import com.android.framework.protobuf.InvalidProtocolBufferException;
+import com.android.internal.annotations.GuardedBy;
+
 import dalvik.system.CloseGuard;
 
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
+import java.net.HttpCookie;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.ByteOrder;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Executor;
-
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * @hide
@@ -228,73 +262,108 @@
  * successful transition. Any other value will be an error. Call {@link #getState()} to
  * determine the current state. </p>
  */
-public abstract class MediaPlayer2 implements AutoCloseable
+public class MediaPlayer2 implements AutoCloseable
                                             , AudioRouting {
+    static {
+        System.loadLibrary("media2_jni");
+        native_init();
+    }
+
+    private static native void native_init();
+
+    private static final int NEXT_SOURCE_STATE_ERROR = -1;
+    private static final int NEXT_SOURCE_STATE_INIT = 0;
+    private static final int NEXT_SOURCE_STATE_PREPARING = 1;
+    private static final int NEXT_SOURCE_STATE_PREPARED = 2;
+
+    private static final String TAG = "MediaPlayer2";
+
+    private Context mContext;
+
+    private long mNativeContext;  // accessed by native methods
+    private long mNativeSurfaceTexture;  // accessed by native methods
+    private int mListenerContext;  // accessed by native methods
+    private SurfaceHolder mSurfaceHolder;
+    private PowerManager.WakeLock mWakeLock = null;
+    private boolean mScreenOnWhilePlaying;
+    private boolean mStayAwake;
+
+    private final Object mSrcLock = new Object();
+    //--- guarded by |mSrcLock| start
+    private SourceInfo mCurrentSourceInfo;
+    private final Queue<SourceInfo> mNextSourceInfos = new ConcurrentLinkedQueue<>();
+    //--- guarded by |mSrcLock| end
+    private final AtomicLong mSrcIdGenerator = new AtomicLong(0);
+
+    private volatile float mVolume = 1.0f;
+    private VideoSize mVideoSize = new VideoSize(0, 0);
+
+    // TODO: create per-source drm fields in SourceInfo
+    // Modular DRM
+    private final Object mDrmLock = new Object();
+    //--- guarded by |mDrmLock| start
+    private UUID mDrmUUID;
+    private DrmInfo mDrmInfo;
+    private MediaDrm mDrmObj;
+    private byte[] mDrmSessionId;
+    private boolean mDrmInfoResolved;
+    private boolean mActiveDrmScheme;
+    private boolean mDrmConfigAllowed;
+    private boolean mDrmProvisioningInProgress;
+    private boolean mPrepareDrmInProgress;
+    private ProvisioningThread mDrmProvisioningThread;
+    //--- guarded by |mDrmLock| end
+
+    // Creating a dummy audio track, used for keeping session id alive
+    private final Object mSessionIdLock = new Object();
+    @GuardedBy("mSessionIdLock")
+    private AudioTrack mDummyAudioTrack;
+
+    private HandlerThread mHandlerThread;
+    private final TaskHandler mTaskHandler;
+    private final Object mTaskLock = new Object();
+    @GuardedBy("mTaskLock")
+    private final List<Task> mPendingTasks = new LinkedList<>();
+    @GuardedBy("mTaskLock")
+    private Task mCurrentTask;
+
+    @GuardedBy("mTaskLock")
+    boolean mIsPreviousCommandSeekTo = false;
+    // |mPreviousSeekPos| and |mPreviousSeekMode| are valid only when |mIsPreviousCommandSeekTo|
+    // is true, and they are accessed on |mHandlerThread| only.
+    long mPreviousSeekPos = -1;
+    int mPreviousSeekMode = SEEK_PREVIOUS_SYNC;
+
+    @GuardedBy("this")
+    private boolean mReleased;
+
     private final CloseGuard mGuard = CloseGuard.get();
 
     /**
-     * Create a MediaPlayer2 object.
-     *
-     * @return A MediaPlayer2 object created
+     * Default constructor.
+     * <p>When done with the MediaPlayer2, you should call {@link #close()},
+     * to free the resources. If not released, too many MediaPlayer2 instances may
+     * result in an exception.</p>
      */
-    public static final MediaPlayer2 create(Context context) {
-        return new MediaPlayer2Impl(context);
-    }
-
-    private static final String[] decodeMediaPlayer2Uri(String location) {
-        Uri uri = Uri.parse(location);
-        if (!"mediaplayer2".equals(uri.getScheme())) {
-            return new String[] {location};
-        }
-
-        List<String> uris = uri.getQueryParameters("uri");
-        if (uris.isEmpty()) {
-            return new String[] {location};
-        }
-
-        List<String> keys = uri.getQueryParameters("key");
-        List<String> values = uri.getQueryParameters("value");
-        if (keys.size() != values.size()) {
-            return new String[] {uris.get(0)};
-        }
-
-        List<String> ls = new ArrayList();
-        ls.add(uris.get(0));
-        for (int i = 0; i < keys.size() ; i++) {
-            ls.add(keys.get(i));
-            ls.add(values.get(i));
-        }
-
-        return ls.toArray(new String[ls.size()]);
-    }
-
-    private static final String encodeMediaPlayer2Uri(String uri, String[] keys, String[] values) {
-        Uri.Builder builder = new Uri.Builder();
-        builder.scheme("mediaplayer2").path("/").appendQueryParameter("uri", uri);
-        if (keys == null || values == null || keys.length != values.length) {
-            return builder.build().toString();
-        }
-        for (int i = 0; i < keys.length ; i++) {
-            builder
-                .appendQueryParameter("key", keys[i])
-                .appendQueryParameter("value", values[i]);
-        }
-        return builder.build().toString();
-    }
-
-    /**
-     * @hide
-     */
-    // add hidden empty constructor so it doesn't show in SDK
-    public MediaPlayer2() {
+    public MediaPlayer2(Context context) {
         mGuard.open("close");
+
+        mContext = context;
+        mHandlerThread = new HandlerThread("MediaPlayer2TaskThread");
+        mHandlerThread.start();
+        Looper looper = mHandlerThread.getLooper();
+        mTaskHandler = new TaskHandler(this, looper);
+        AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        int sessionId = am.generateAudioSessionId();
+        keepAudioSessionIdAlive(sessionId);
+
+        /* Native setup requires a weak reference to our object.
+         * It's easier to create it here than in C++.
+         */
+        native_setup(sessionId, new WeakReference<MediaPlayer2>(this));
     }
 
-    /**
-     * Returns a {@link MediaPlayerBase} implementation which runs based on
-     * this MediaPlayer2 instance.
-     */
-    public abstract MediaPlayerBase getMediaPlayerBase();
+    private native void native_setup(int sessionId, Object mediaplayer2This);
 
     /**
      * Releases the resources held by this {@code MediaPlayer2} object.
@@ -325,8 +394,41 @@
         synchronized (mGuard) {
             mGuard.close();
         }
+        release();
     }
 
+    private synchronized void release() {
+        if (mReleased) {
+            return;
+        }
+        stayAwake(false);
+        updateSurfaceScreenOn();
+        synchronized (mEventCbLock) {
+            mEventCallbackRecords.clear();
+        }
+        if (mHandlerThread != null) {
+            mHandlerThread.quitSafely();
+            mHandlerThread = null;
+        }
+
+        // Modular DRM clean up
+        mOnDrmConfigHelper = null;
+        synchronized (mDrmEventCbLock) {
+            mDrmEventCallbackRecords.clear();
+        }
+        resetDrmState();
+
+        native_release();
+
+        synchronized (mSessionIdLock) {
+            mDummyAudioTrack.release();
+        }
+
+        mReleased = true;
+    }
+
+    private native void native_release();
+
     // Have to declare protected for finalize() since it is protected
     // in the base class Object.
     @Override
@@ -336,55 +438,124 @@
         }
 
         close();
+        native_finalize();
     }
 
+    private native void native_finalize();
+
+    /**
+     * Resets the MediaPlayer2 to its uninitialized state. After calling
+     * this method, you will have to initialize it again by setting the
+     * data source and calling prepare().
+     */
+    // This is a synchronous call.
+    public void reset() {
+        synchronized (mEventCbLock) {
+            mEventCallbackRecords.clear();
+        }
+        synchronized (mDrmEventCbLock) {
+            mDrmEventCallbackRecords.clear();
+        }
+        synchronized (mSrcLock) {
+            mCurrentSourceInfo = null;
+            mNextSourceInfos.clear();
+        }
+
+        synchronized (mTaskLock) {
+            mPendingTasks.clear();
+            mIsPreviousCommandSeekTo = false;
+        }
+
+        stayAwake(false);
+        native_reset();
+
+        AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        int sessionId = am.generateAudioSessionId();
+        keepAudioSessionIdAlive(sessionId);
+
+        // make sure none of the listeners get called anymore
+        if (mTaskHandler != null) {
+            mTaskHandler.removeCallbacksAndMessages(null);
+        }
+
+        resetDrmState();
+    }
+
+    private native void native_reset();
+
     /**
      * Starts or resumes playback. If playback had previously been paused,
      * playback will continue from where it was paused. If playback had
      * reached end of stream and been paused, or never started before,
-     * playback will start at the beginning. If the source had not been
-     * prepared, the player will prepare the source and play.
+     * playback will start at the beginning.
      *
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object play();
+    public Object play() {
+        return addTask(new Task(CALL_COMPLETED_PLAY, false) {
+            @Override
+            void process() {
+                stayAwake(true);
+                native_start();
+            }
+        });
+    }
+
+    private native void native_start() throws IllegalStateException;
 
     /**
      * Prepares the player for playback, asynchronously.
      *
-     * After setting the datasource and the display surface, you need to
-     * call prepare().
+     * After setting the datasource and the display surface, you need to call prepare().
      *
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object prepare();
+    public Object prepare() {
+        return addTask(new Task(CALL_COMPLETED_PREPARE, true) {
+            @Override
+            void process() {
+                native_prepare();
+            }
+        });
+    }
+
+    private native void native_prepare();
 
     /**
      * Pauses playback. Call play() to resume.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object pause();
+    public Object pause() {
+        return addTask(new Task(CALL_COMPLETED_PAUSE, false) {
+            @Override
+            void process() {
+                stayAwake(false);
+
+                native_pause();
+            }
+        });
+    }
+
+    private native void native_pause() throws IllegalStateException;
 
     /**
      * Tries to play next data source if applicable.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object skipToNext();
-
-    /**
-     * Moves the media to specified time position.
-     * Same as {@link #seekTo(long, int)} with {@code mode = SEEK_PREVIOUS_SYNC}.
-     *
-     * @param msec the offset in milliseconds from the start to seek to
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
-     */
-    // This is an asynchronous call.
-    public Object seekTo(long msec) {
-        return seekTo(msec, SEEK_PREVIOUS_SYNC /* mode */);
+    public Object skipToNext() {
+        return addTask(new Task(CALL_COMPLETED_SKIP_TO_NEXT, false) {
+            @Override
+            void process() {
+                if (getState() == PLAYER_STATE_PLAYING) {
+                    pause();
+                }
+                playNextDataSource();
+            }
+        });
     }
 
     /**
@@ -392,7 +563,7 @@
      *
      * @return the current position in milliseconds
      */
-    public abstract long getCurrentPosition();
+    public native long getCurrentPosition();
 
     /**
      * Gets the duration of the file.
@@ -400,23 +571,32 @@
      * @return the duration in milliseconds, if no duration is available
      *         (for example, if streaming live content), -1 is returned.
      */
-    public abstract long getDuration();
+    public native long getDuration();
 
     /**
      * Gets the current buffered media source position received through progressive downloading.
-     * The received buffering percentage indicates how much of the content has been buffered
-     * or played. For example a buffering update of 80 percent when half the content
-     * has already been played indicates that the next 30 percent of the
+     * For example a buffering update of 8000 milliseconds when 5000 milliseconds of the content
+     * has already been played indicates that the next 3000 milliseconds of the
      * content to play has been buffered.
      *
      * @return the current buffered media source position in milliseconds
      */
-    public abstract long getBufferedPosition();
+    public long getBufferedPosition() {
+        // Use cached buffered percent for now.
+        int bufferedPercentage;
+        synchronized (mSrcLock) {
+            if (mCurrentSourceInfo == null) {
+                bufferedPercentage = 0;
+            } else {
+                bufferedPercentage = mCurrentSourceInfo.mBufferedPercentage.get();
+            }
+        }
+        return getDuration() * bufferedPercentage / 100;
+    }
 
     /**
      * MediaPlayer2 has not been prepared or just has been reset.
      * In this state, MediaPlayer2 doesn't fetch data.
-     * @hide
      */
     public static final int PLAYER_STATE_IDLE = 1001;
 
@@ -424,26 +604,23 @@
      * MediaPlayer2 has been just prepared.
      * In this state, MediaPlayer2 just fetches data from media source,
      * but doesn't actively render data.
-     * @hide
      */
     public static final int PLAYER_STATE_PREPARED = 1002;
 
     /**
      * MediaPlayer2 is paused.
-     * In this state, MediaPlayer2 doesn't actively render data.
-     * @hide
+     * In this state, MediaPlayer2 has allocated resources to construct playback
+     * pipeline, but it doesn't actively render data.
      */
     public static final int PLAYER_STATE_PAUSED = 1003;
 
     /**
      * MediaPlayer2 is actively playing back data.
-     * @hide
      */
     public static final int PLAYER_STATE_PLAYING = 1004;
 
     /**
      * MediaPlayer2 has hit some fatal error and cannot continue playback.
-     * @hide
      */
     public static final int PLAYER_STATE_ERROR = 1005;
 
@@ -464,74 +641,479 @@
      *
      * @return the current player state.
      */
-    public abstract @MediaPlayer2State int getState();
+    public @MediaPlayer2State int getState() {
+        return native_getState();
+    }
+
+    private native int native_getState();
 
     /**
      * Sets the audio attributes for this MediaPlayer2.
      * See {@link AudioAttributes} for how to build and configure an instance of this class.
-     * You must call this method before {@link #prepare()} in order
+     * You must call this method before {@link #play()} and {@link #pause()} in order
      * for the audio attributes to become effective thereafter.
      * @param attributes a non-null set of audio attributes
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object setAudioAttributes(@NonNull AudioAttributes attributes);
+    public Object setAudioAttributes(@NonNull AudioAttributes attributes) {
+        return addTask(new Task(CALL_COMPLETED_SET_AUDIO_ATTRIBUTES, false) {
+            @Override
+            void process() {
+                if (attributes == null) {
+                    final String msg = "Cannot set AudioAttributes to null";
+                    throw new IllegalArgumentException(msg);
+                }
+                native_setAudioAttributes(attributes);
+            }
+        });
+    }
+
+    // return true if the parameter is set successfully, false otherwise
+    private native boolean native_setAudioAttributes(AudioAttributes audioAttributes);
 
     /**
      * Gets the audio attributes for this MediaPlayer2.
      * @return attributes a set of audio attributes
      */
-    public abstract @Nullable AudioAttributes getAudioAttributes();
+    public @NonNull AudioAttributes getAudioAttributes() {
+        return native_getAudioAttributes();
+    }
+
+    private native AudioAttributes native_getAudioAttributes();
 
     /**
      * Sets the data source as described by a DataSourceDesc.
      *
      * @param dsd the descriptor of data source you want to play
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object setDataSource(@NonNull DataSourceDesc dsd);
+    public Object setDataSource(@NonNull DataSourceDesc dsd) {
+        return addTask(new Task(CALL_COMPLETED_SET_DATA_SOURCE, false) {
+            @Override
+            void process() throws IOException {
+                checkArgument(dsd != null, "the DataSourceDesc cannot be null");
+                int state = getState();
+                if (state != PLAYER_STATE_ERROR && state != PLAYER_STATE_IDLE) {
+                    throw new IllegalStateException("called in wrong state " + state);
+                }
+
+                synchronized (mSrcLock) {
+                    mCurrentSourceInfo = new SourceInfo(dsd);
+                    handleDataSource(true /* isCurrent */, dsd, mCurrentSourceInfo.mId);
+                }
+            }
+        });
+    }
 
     /**
      * Sets a single data source as described by a DataSourceDesc which will be played
      * after current data source is finished.
      *
      * @param dsd the descriptor of data source you want to play after current one
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object setNextDataSource(@NonNull DataSourceDesc dsd);
+    public Object setNextDataSource(@NonNull DataSourceDesc dsd) {
+        return addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCE, false) {
+            @Override
+            void process() {
+                checkArgument(dsd != null, "the DataSourceDesc cannot be null");
+                synchronized (mSrcLock) {
+                    mNextSourceInfos.clear();
+                    mNextSourceInfos.add(new SourceInfo(dsd));
+                }
+                prepareNextDataSource();
+            }
+        });
+    }
 
     /**
      * Sets a list of data sources to be played sequentially after current data source is done.
      *
      * @param dsds the list of data sources you want to play after current one
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object setNextDataSources(@NonNull List<DataSourceDesc> dsds);
+    public Object setNextDataSources(@NonNull List<DataSourceDesc> dsds) {
+        return addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCES, false) {
+            @Override
+            void process() {
+                if (dsds == null || dsds.size() == 0) {
+                    throw new IllegalArgumentException("data source list cannot be null or empty.");
+                }
+                for (DataSourceDesc dsd : dsds) {
+                    if (dsd == null) {
+                        throw new IllegalArgumentException(
+                                "DataSourceDesc in the source list cannot be null.");
+                    }
+                }
+
+                synchronized (mSrcLock) {
+                    mNextSourceInfos.clear();
+                    for (DataSourceDesc dsd : dsds) {
+                        mNextSourceInfos.add(new SourceInfo(dsd));
+                    }
+                }
+                prepareNextDataSource();
+            }
+        });
+    }
 
     /**
      * Removes all data sources pending to be played.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object clearNextDataSources();
+    public Object clearNextDataSources() {
+        return addTask(new Task(CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES, false) {
+            @Override
+            void process() {
+                mNextSourceInfos.clear();
+            }
+        });
+    }
 
     /**
      * Gets the current data source as described by a DataSourceDesc.
      *
      * @return the current DataSourceDesc
      */
-    public abstract @NonNull DataSourceDesc getCurrentDataSource();
+    public DataSourceDesc getCurrentDataSource() {
+        synchronized (mSrcLock) {
+            return mCurrentSourceInfo == null ? null : mCurrentSourceInfo.mDSD;
+        }
+    }
+
+    private void handleDataSource(boolean isCurrent, @NonNull DataSourceDesc dsd, long srcId)
+            throws IOException {
+        checkArgument(dsd != null, "the DataSourceDesc cannot be null");
+
+        switch (dsd.getType()) {
+            case DataSourceDesc.TYPE_CALLBACK:
+                handleDataSource(isCurrent,
+                                 srcId,
+                                 dsd.getMedia2DataSource(),
+                                 dsd.getStartPosition(),
+                                 dsd.getEndPosition());
+                break;
+
+            case DataSourceDesc.TYPE_FD:
+                handleDataSource(isCurrent,
+                                 srcId,
+                                 dsd.getFileDescriptor(),
+                                 dsd.getFileDescriptorOffset(),
+                                 dsd.getFileDescriptorLength(),
+                                 dsd.getStartPosition(),
+                                 dsd.getEndPosition());
+                break;
+
+            case DataSourceDesc.TYPE_URI:
+                handleDataSource(isCurrent,
+                                 srcId,
+                                 dsd.getUriContext(),
+                                 dsd.getUri(),
+                                 dsd.getUriHeaders(),
+                                 dsd.getUriCookies(),
+                                 dsd.getStartPosition(),
+                                 dsd.getEndPosition());
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    /**
+     * To provide cookies for the subsequent HTTP requests, you can install your own default cookie
+     * handler and use other variants of setDataSource APIs instead. Alternatively, you can use
+     * this API to pass the cookies as a list of HttpCookie. If the app has not installed
+     * a CookieHandler already, this API creates a CookieManager and populates its CookieStore with
+     * the provided cookies. If the app has installed its own handler already, this API requires the
+     * handler to be of CookieManager type such that the API can update the manager’s CookieStore.
+     *
+     * <p><strong>Note</strong> that the cross domain redirection is allowed by default,
+     * but that can be changed with key/value pairs through the headers parameter with
+     * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value to
+     * disallow or allow cross domain redirection.
+     *
+     * @throws IllegalArgumentException if cookies are provided and the installed handler is not
+     *                                  a CookieManager
+     * @throws IllegalStateException    if it is called in an invalid state
+     * @throws NullPointerException     if context or uri is null
+     * @throws IOException              if uri has a file scheme and an I/O error occurs
+     */
+    private void handleDataSource(
+            boolean isCurrent, long srcId,
+            @NonNull Context context, @NonNull Uri uri,
+            @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies,
+            long startPos, long endPos)
+            throws IOException {
+        // The context and URI usually belong to the calling user. Get a resolver for that user.
+        final ContentResolver resolver = context.getContentResolver();
+        final String scheme = uri.getScheme();
+        if (ContentResolver.SCHEME_FILE.equals(scheme)) {
+            handleDataSource(isCurrent, srcId, uri.getPath(), null, null, startPos, endPos);
+            return;
+        }
+
+        final int ringToneType = RingtoneManager.getDefaultType(uri);
+        try {
+            AssetFileDescriptor afd;
+            // Try requested Uri locally first
+            if (ContentResolver.SCHEME_CONTENT.equals(scheme) && ringToneType != -1) {
+                afd = RingtoneManager.openDefaultRingtoneUri(context, uri);
+                if (attemptDataSource(isCurrent, srcId, afd, startPos, endPos)) {
+                    return;
+                }
+                final Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(
+                        context, ringToneType);
+                afd = resolver.openAssetFileDescriptor(actualUri, "r");
+            } else {
+                afd = resolver.openAssetFileDescriptor(uri, "r");
+            }
+            if (attemptDataSource(isCurrent, srcId, afd, startPos, endPos)) {
+                return;
+            }
+        } catch (NullPointerException | SecurityException | IOException ex) {
+            Log.w(TAG, "Couldn't open " + uri + ": " + ex);
+            // Fallback to media server
+        }
+        handleDataSource(isCurrent, srcId, uri.toString(), headers, cookies, startPos, endPos);
+    }
+
+    private boolean attemptDataSource(boolean isCurrent, long srcId, AssetFileDescriptor afd,
+            long startPos, long endPos) throws IOException {
+        try {
+            if (afd.getDeclaredLength() < 0) {
+                handleDataSource(isCurrent,
+                        srcId,
+                        afd.getFileDescriptor(),
+                        0,
+                        DataSourceDesc.LONG_MAX,
+                        startPos,
+                        endPos);
+            } else {
+                handleDataSource(isCurrent,
+                        srcId,
+                        afd.getFileDescriptor(),
+                        afd.getStartOffset(),
+                        afd.getDeclaredLength(),
+                        startPos,
+                        endPos);
+            }
+            return true;
+        } catch (NullPointerException | SecurityException | IOException ex) {
+            Log.w(TAG, "Couldn't open srcId:" + srcId + ": " + ex);
+            return false;
+        } finally {
+            if (afd != null) {
+                afd.close();
+            }
+        }
+    }
+
+    private void handleDataSource(
+            boolean isCurrent, long srcId,
+            String path, Map<String, String> headers, List<HttpCookie> cookies,
+            long startPos, long endPos)
+            throws IOException {
+        String[] keys = null;
+        String[] values = null;
+
+        if (headers != null) {
+            keys = new String[headers.size()];
+            values = new String[headers.size()];
+
+            int i = 0;
+            for (Map.Entry<String, String> entry: headers.entrySet()) {
+                keys[i] = entry.getKey();
+                values[i] = entry.getValue();
+                ++i;
+            }
+        }
+        handleDataSource(isCurrent, srcId, path, keys, values, cookies, startPos, endPos);
+    }
+
+    private void handleDataSource(boolean isCurrent, long srcId,
+            String path, String[] keys, String[] values, List<HttpCookie> cookies,
+            long startPos, long endPos)
+            throws IOException {
+        final Uri uri = Uri.parse(path);
+        final String scheme = uri.getScheme();
+        if ("file".equals(scheme)) {
+            path = uri.getPath();
+        } else if (scheme != null) {
+            // handle non-file sources
+            Media2Utils.storeCookies(cookies);
+            nativeHandleDataSourceUrl(
+                    isCurrent,
+                    srcId,
+                    Media2HTTPService.createHTTPService(path),
+                    path,
+                    keys,
+                    values,
+                    startPos,
+                    endPos);
+            return;
+        }
+
+        final File file = new File(path);
+        if (file.exists()) {
+            FileInputStream is = new FileInputStream(file);
+            FileDescriptor fd = is.getFD();
+            handleDataSource(isCurrent, srcId, fd, 0, DataSourceDesc.LONG_MAX, startPos, endPos);
+            is.close();
+        } else {
+            throw new IOException("handleDataSource failed.");
+        }
+    }
+
+    private native void nativeHandleDataSourceUrl(
+            boolean isCurrent, long srcId,
+            Media2HTTPService httpService, String path, String[] keys, String[] values,
+            long startPos, long endPos)
+            throws IOException;
+
+    /**
+     * Sets the data source (FileDescriptor) to use. The FileDescriptor must be
+     * seekable (N.B. a LocalSocket is not seekable). It is the caller's responsibility
+     * to close the file descriptor. It is safe to do so as soon as this call returns.
+     *
+     * @throws IllegalStateException if it is called in an invalid state
+     * @throws IllegalArgumentException if fd is not a valid FileDescriptor
+     * @throws IOException if fd can not be read
+     */
+    private void handleDataSource(
+            boolean isCurrent, long srcId,
+            FileDescriptor fd, long offset, long length,
+            long startPos, long endPos) throws IOException {
+        nativeHandleDataSourceFD(isCurrent, srcId, fd, offset, length, startPos, endPos);
+    }
+
+    private native void nativeHandleDataSourceFD(boolean isCurrent, long srcId,
+            FileDescriptor fd, long offset, long length,
+            long startPos, long endPos) throws IOException;
+
+    /**
+     * @throws IllegalStateException if it is called in an invalid state
+     * @throws IllegalArgumentException if dataSource is not a valid Media2DataSource
+     */
+    private void handleDataSource(boolean isCurrent, long srcId, Media2DataSource dataSource,
+            long startPos, long endPos) {
+        nativeHandleDataSourceCallback(isCurrent, srcId, dataSource, startPos, endPos);
+    }
+
+    private native void nativeHandleDataSourceCallback(
+            boolean isCurrent, long srcId, Media2DataSource dataSource,
+            long startPos, long endPos);
+
+    // return true if there is a next data source, false otherwise.
+    // This function should be always called on |mHandlerThread|.
+    private boolean prepareNextDataSource() {
+        HandlerThread handlerThread = mHandlerThread;
+        if (handlerThread != null && Looper.myLooper() != handlerThread.getLooper()) {
+            Log.e(TAG, "prepareNextDataSource: called on wrong looper");
+        }
+
+        boolean hasNextDSD;
+        int state = getState();
+        synchronized (mSrcLock) {
+            hasNextDSD = !mNextSourceInfos.isEmpty();
+            if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) {
+                // Current source has not been prepared yet.
+                return hasNextDSD;
+            }
+
+            SourceInfo nextSource = mNextSourceInfos.peek();
+            if (!hasNextDSD || nextSource.mStateAsNextSource != NEXT_SOURCE_STATE_INIT) {
+                // There is no next source or it's in preparing or prepared state.
+                return hasNextDSD;
+            }
+
+            try {
+                nextSource.mStateAsNextSource = NEXT_SOURCE_STATE_PREPARING;
+                handleDataSource(false /* isCurrent */, nextSource.mDSD, nextSource.mId);
+            } catch (Exception e) {
+                Message msg = mTaskHandler.obtainMessage(
+                        MEDIA_ERROR, MEDIA_ERROR_IO, MEDIA_ERROR_UNKNOWN, null);
+                mTaskHandler.handleMessage(msg, nextSource.mId);
+
+                mNextSourceInfos.poll();
+                return prepareNextDataSource();
+            }
+        }
+        return hasNextDSD;
+    }
+
+    // This function should be always called on |mHandlerThread|.
+    private void playNextDataSource() {
+        HandlerThread handlerThread = mHandlerThread;
+        if (handlerThread != null && Looper.myLooper() != handlerThread.getLooper()) {
+            Log.e(TAG, "playNextDataSource: called on wrong looper");
+        }
+
+        boolean hasNextDSD = false;
+        synchronized (mSrcLock) {
+            if (!mNextSourceInfos.isEmpty()) {
+                hasNextDSD = true;
+                SourceInfo nextSourceInfo = mNextSourceInfos.peek();
+                if (nextSourceInfo.mStateAsNextSource == NEXT_SOURCE_STATE_PREPARED) {
+                    // Switch to next source only when it has been prepared.
+                    mCurrentSourceInfo = mNextSourceInfos.poll();
+
+                    long srcId = mCurrentSourceInfo.mId;
+                    try {
+                        nativePlayNextDataSource(srcId);
+                    } catch (Exception e) {
+                        Message msg2 = mTaskHandler.obtainMessage(
+                                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
+                        mTaskHandler.handleMessage(msg2, srcId);
+                        // Keep |mNextSourcePlayPending|
+                        hasNextDSD = prepareNextDataSource();
+                    }
+                    if (hasNextDSD) {
+                        stayAwake(true);
+
+                        // Now a new current src is playing.
+                        // Wait for MEDIA_INFO_DATA_SOURCE_START to prepare next source.
+                    }
+                } else if (nextSourceInfo.mStateAsNextSource == NEXT_SOURCE_STATE_INIT) {
+                    hasNextDSD = prepareNextDataSource();
+                }
+            }
+        }
+
+        if (!hasNextDSD) {
+            sendEvent(new EventNotifier() {
+                @Override
+                public void notify(EventCallback callback) {
+                    callback.onInfo(
+                            MediaPlayer2.this, null, MEDIA_INFO_DATA_SOURCE_LIST_END, 0);
+                }
+            });
+        }
+    }
+
+    private native void nativePlayNextDataSource(long srcId);
 
     /**
      * Configures the player to loop on the current data source.
      * @param loop true if the current data source is meant to loop.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object loopCurrent(boolean loop);
+    public Object loopCurrent(boolean loop) {
+        return addTask(new Task(CALL_COMPLETED_LOOP_CURRENT, false) {
+            @Override
+            void process() {
+                setLooping(loop);
+            }
+        });
+    }
+
+    private native void setLooping(boolean looping);
 
     /**
      * Sets the volume of the audio of the media to play, expressed as a linear multiplier
@@ -541,17 +1123,29 @@
      * A value of 0.0f indicates muting, a value of 1.0f is the nominal unattenuated and unamplified
      * gain. See {@link #getMaxPlayerVolume()} for the volume range supported by this player.
      * @param volume a value between 0.0f and {@link #getMaxPlayerVolume()}.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object setPlayerVolume(float volume);
+    public Object setPlayerVolume(float volume) {
+        return addTask(new Task(CALL_COMPLETED_SET_PLAYER_VOLUME, false) {
+            @Override
+            void process() {
+                mVolume = volume;
+                native_setVolume(volume);
+            }
+        });
+    }
+
+    private native void native_setVolume(float volume);
 
     /**
-     * Returns the current volume of this player to this player.
+     * Returns the current volume of this player.
      * Note that it does not take into account the associated stream volume.
      * @return the player volume.
      */
-    public abstract float getPlayerVolume();
+    public float getPlayerVolume() {
+        return mVolume;
+    }
 
     /**
      * @return the maximum volume that can be used in {@link #setPlayerVolume(float)}.
@@ -561,52 +1155,62 @@
     }
 
     /**
-     * Create a request parcel which can be routed to the native media
-     * player using {@link #invoke(Parcel, Parcel)}. The Parcel
-     * returned has the proper InterfaceToken set. The caller should
-     * not overwrite that token, i.e it can only append data to the
-     * Parcel.
-     *
-     * @return A parcel suitable to hold a request for the native
-     * player.
-     * {@hide}
-     */
-    public Parcel newRequest() {
-        return null;
-    }
-
-    /**
      * Insert a task in the command queue to help the client to identify whether a batch
      * of commands has been finished. When this command is processed, a notification
-     * {@code EventCallback.onCommandLabelReached} will be fired with the
+     * {@link EventCallback#onCommandLabelReached onCommandLabelReached} will be fired with the
      * given {@code label}.
      *
      * @see EventCallback#onCommandLabelReached
      *
      * @param label An application specific Object used to help to identify the completeness
      * of a batch of commands.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object notifyWhenCommandLabelReached(@NonNull Object label);
+    public Object notifyWhenCommandLabelReached(@NonNull Object label) {
+        return addTask(new Task(CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED, false) {
+            @Override
+            void process() {
+                sendEvent(new EventNotifier() {
+                    @Override
+                    public void notify(EventCallback callback) {
+                        callback.onCommandLabelReached(
+                                MediaPlayer2.this, label);
+                    }
+                });
+            }
+        });
+    }
 
     /**
      * Sets the {@link SurfaceHolder} to use for displaying the video
      * portion of the media.
      *
      * Either a surface holder or surface must be set if a display or video sink
-     * is needed.  Not calling this method or {@link #setSurface(Surface)}
+     * is needed. Not calling this method or {@link #setSurface(Surface)}
      * when playing back a video will result in only the audio track being played.
      * A null surface holder or surface will result in only the audio track being
      * played.
      *
      * @param sh the SurfaceHolder to use for video display
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized or has been released.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
-     * @hide
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
-    public abstract Object setDisplay(SurfaceHolder sh);
+    public Object setDisplay(SurfaceHolder sh) {
+        return addTask(new Task(CALL_COMPLETED_SET_DISPLAY, false) {
+            @Override
+            void process() {
+                mSurfaceHolder = sh;
+                Surface surface;
+                if (sh != null) {
+                    surface = sh.getSurface();
+                } else {
+                    surface = null;
+                }
+                native_setVideoSurface(surface);
+                updateSurfaceScreenOn();
+            }
+        });
+    }
 
     /**
      * Sets the {@link Surface} to be used as the sink for the video portion of
@@ -624,56 +1228,125 @@
      *
      * @param surface The {@link Surface} to be used for the video portion of
      * the media.
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized or has been released.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object setSurface(Surface surface);
+    public Object setSurface(Surface surface) {
+        return addTask(new Task(CALL_COMPLETED_SET_SURFACE, false) {
+            @Override
+            void process() {
+                if (mScreenOnWhilePlaying && surface != null) {
+                    Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface");
+                }
+                mSurfaceHolder = null;
+                native_setVideoSurface(surface);
+                updateSurfaceScreenOn();
+            }
+        });
+    }
 
-    /* Do not change these video scaling mode values below without updating
-     * their counterparts in system/window.h! Please do not forget to update
-     * {@link #isVideoScalingModeSupported} when new video scaling modes
-     * are added.
-     */
-    /**
-     * Specifies a video scaling mode. The content is stretched to the
-     * surface rendering area. When the surface has the same aspect ratio
-     * as the content, the aspect ratio of the content is maintained;
-     * otherwise, the aspect ratio of the content is not maintained when video
-     * is being rendered.
-     * There is no content cropping with this video scaling mode.
-     */
-    public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1;
+    private native void native_setVideoSurface(Surface surface);
 
     /**
-     * Specifies a video scaling mode. The content is scaled, maintaining
-     * its aspect ratio. The whole surface area is always used. When the
-     * aspect ratio of the content is the same as the surface, no content
-     * is cropped; otherwise, content is cropped to fit the surface.
-     * @hide
+     * Set the low-level power management behavior for this MediaPlayer2. This
+     * can be used when the MediaPlayer2 is not playing through a SurfaceHolder
+     * set with {@link #setDisplay(SurfaceHolder)} and thus can use the
+     * high-level {@link #setScreenOnWhilePlaying(boolean)} feature.
+     *
+     * <p>This function has the MediaPlayer2 access the low-level power manager
+     * service to control the device's power usage while playing is occurring.
+     * The parameter is a combination of {@link android.os.PowerManager} wake flags.
+     * Use of this method requires {@link android.Manifest.permission#WAKE_LOCK}
+     * permission.
+     * By default, no attempt is made to keep the device awake during playback.
+     *
+     * @param context the Context to use
+     * @param mode    the power/wake mode to set
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
+     * @see android.os.PowerManager
      */
-    public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2;
+    // This is an asynchronous call.
+    public Object setWakeMode(Context context, int mode) {
+        return addTask(new Task(CALL_COMPLETED_SET_WAKE_MODE, false) {
+            @Override
+            void process() {
+                boolean washeld = false;
+
+                if (mWakeLock != null) {
+                    if (mWakeLock.isHeld()) {
+                        washeld = true;
+                        mWakeLock.release();
+                    }
+                    mWakeLock = null;
+                }
+
+                PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+                ActivityManager am =
+                        (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+                List<RunningAppProcessInfo> runningAppsProcInfo = am.getRunningAppProcesses();
+                int pid = android.os.Process.myPid();
+                String name = "pid " + String.valueOf(pid);
+                if (runningAppsProcInfo != null) {
+                    for (RunningAppProcessInfo procInfo : runningAppsProcInfo) {
+                        if (procInfo.pid == pid) {
+                            name = procInfo.processName;
+                            break;
+                        }
+                    }
+                }
+                mWakeLock = pm.newWakeLock(mode | PowerManager.ON_AFTER_RELEASE, name);
+                mWakeLock.setReferenceCounted(false);
+                if (washeld) {
+                    mWakeLock.acquire();
+                }
+            }
+        });
+    }
 
     /**
-     * Sets video scaling mode. To make the target video scaling mode
-     * effective during playback, this method must be called after
-     * data source is set. If not called, the default video
-     * scaling mode is {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT}.
+     * Control whether we should use the attached SurfaceHolder to keep the
+     * screen on while video playback is occurring.  This is the preferred
+     * method over {@link #setWakeMode} where possible, since it doesn't
+     * require that the application have permission for low-level wake lock
+     * access.
      *
-     * <p> The supported video scaling modes are:
-     * <ul>
-     * <li> {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT}
-     * </ul>
-     *
-     * @param mode target video scaling mode. Must be one of the supported
-     * video scaling modes; otherwise, IllegalArgumentException will be thrown.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
-     *
-     * @see MediaPlayer2#VIDEO_SCALING_MODE_SCALE_TO_FIT
-     * @hide
+     * @param screenOn Supply true to keep the screen on, false to allow it to turn off.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
-    public abstract Object setVideoScalingMode(int mode);
+    // This is an asynchronous call.
+    public Object setScreenOnWhilePlaying(boolean screenOn) {
+        return addTask(new Task(CALL_COMPLETED_SET_SCREEN_ON_WHILE_PLAYING, false) {
+            @Override
+            void process() {
+                if (mScreenOnWhilePlaying != screenOn) {
+                    if (screenOn && mSurfaceHolder == null) {
+                        Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective"
+                                + " without a SurfaceHolder");
+                    }
+                    mScreenOnWhilePlaying = screenOn;
+                    updateSurfaceScreenOn();
+                }
+            }
+        });
+    }
+
+    private void stayAwake(boolean awake) {
+        if (mWakeLock != null) {
+            if (awake && !mWakeLock.isHeld()) {
+                mWakeLock.acquire();
+            } else if (!awake && mWakeLock.isHeld()) {
+                mWakeLock.release();
+            }
+        }
+        mStayAwake = awake;
+        updateSurfaceScreenOn();
+    }
+
+    private void updateSurfaceScreenOn() {
+        if (mSurfaceHolder != null) {
+            mSurfaceHolder.setKeepScreenOn(mScreenOnWhilePlaying && mStayAwake);
+        }
+    }
 
     /**
      * Cancels a pending command.
@@ -682,17 +1355,26 @@
      * @return {@code false} if the task could not be cancelled; {@code true} otherwise.
      */
     // This is a synchronous call.
-    public abstract boolean cancelCommand(Object token);
+    public boolean cancelCommand(Object token) {
+        synchronized (mTaskLock) {
+            return mPendingTasks.remove(token);
+        }
+    }
 
     /**
      * Discards all pending commands.
      */
     // This is a synchronous call.
-    public abstract void clearPendingCommands();
+    public void clearPendingCommands() {
+        synchronized (mTaskLock) {
+            mPendingTasks.clear();
+        }
+    }
 
     //--------------------------------------------------------------------------
     // Explicit Routing
     //--------------------
+    private AudioDeviceInfo mPreferredDevice = null;
 
     /**
      * Specifies an audio device (via an {@link AudioDeviceInfo} object) to route
@@ -702,16 +1384,30 @@
      * @return true if succesful, false if the specified {@link AudioDeviceInfo} is non-null and
      * does not correspond to a valid audio device.
      */
-    // This is an asynchronous call.
+    // This is a synchronous call.
     @Override
-    public abstract boolean setPreferredDevice(AudioDeviceInfo deviceInfo);
+    public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) {
+        boolean status = native_setPreferredDevice(deviceInfo);
+        if (status) {
+            synchronized (this) {
+                mPreferredDevice = deviceInfo;
+            }
+        }
+        return status;
+    }
+
+    private native boolean native_setPreferredDevice(AudioDeviceInfo device);
 
     /**
      * Returns the selected output specified by {@link #setPreferredDevice}. Note that this
      * is not guaranteed to correspond to the actual device being used for playback.
      */
     @Override
-    public abstract AudioDeviceInfo getPreferredDevice();
+    public AudioDeviceInfo getPreferredDevice() {
+        synchronized (this) {
+            return mPreferredDevice;
+        }
+    }
 
     /**
      * Returns an {@link AudioDeviceInfo} identifying the current routing of this MediaPlayer2
@@ -720,7 +1416,7 @@
      * selected device when the player was last active.
      */
     @Override
-    public abstract AudioDeviceInfo getRoutedDevice();
+    public native AudioDeviceInfo getRoutedDevice();
 
     /**
      * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing
@@ -732,8 +1428,16 @@
      */
     // This is a synchronous call.
     @Override
-    public abstract void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener,
-            Handler handler);
+    public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener,
+            Handler handler) {
+        if (listener == null) {
+            throw new IllegalArgumentException("addOnRoutingChangedListener: listener is NULL");
+        }
+        RoutingDelegate routingDelegate = new RoutingDelegate(this, listener, handler);
+        native_addDeviceCallback(routingDelegate);
+    }
+
+    private native void native_addDeviceCallback(RoutingDelegate rd);
 
     /**
      * Removes an {@link AudioRouting.OnRoutingChangedListener} which has been previously added
@@ -743,62 +1447,29 @@
      */
     // This is a synchronous call.
     @Override
-    public abstract void removeOnRoutingChangedListener(
+    public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("removeOnRoutingChangedListener: listener is NULL");
+        }
+        native_removeDeviceCallback(listener);
+    }
+
+    private native void native_removeDeviceCallback(
             AudioRouting.OnRoutingChangedListener listener);
 
     /**
-     * Set the low-level power management behavior for this MediaPlayer2.
+     * Returns the size of the video.
      *
-     * <p>This function has the MediaPlayer2 access the low-level power manager
-     * service to control the device's power usage while playing is occurring.
-     * The parameter is a combination of {@link android.os.PowerManager} wake flags.
-     * Use of this method requires {@link android.Manifest.permission#WAKE_LOCK}
-     * permission.
-     * By default, no attempt is made to keep the device awake during playback.
-     *
-     * @param context the Context to use
-     * @param mode    the power/wake mode to set
-     * @see android.os.PowerManager
-     * @hide
-     */
-    public abstract void setWakeMode(Context context, int mode);
-
-    /**
-     * Control whether we should use the attached SurfaceHolder to keep the
-     * screen on while video playback is occurring.  This is the preferred
-     * method over {@link #setWakeMode} where possible, since it doesn't
-     * require that the application have permission for low-level wake lock
-     * access.
-     *
-     * @param screenOn Supply true to keep the screen on, false to allow it
-     * to turn off.
-     * @hide
-     */
-    public abstract void setScreenOnWhilePlaying(boolean screenOn);
-
-    /**
-     * Returns the width of the video.
-     *
-     * @return the width of the video, or 0 if there is no video,
-     * no display surface was set, or the width has not been determined
-     * yet. The {@code EventCallback} can be registered via
+     * @return the size of the video. The width and height of size could be 0 if there is no video,
+     * no display surface was set, or the size has not been determined yet.
+     * The {@code EventCallback} can be registered via
      * {@link #setEventCallback(Executor, EventCallback)} to provide a
-     * notification {@code EventCallback.onVideoSizeChanged} when the width
+     * notification {@code EventCallback.onVideoSizeChanged} when the size
      * is available.
      */
-    public abstract int getVideoWidth();
-
-    /**
-     * Returns the height of the video.
-     *
-     * @return the height of the video, or 0 if there is no video,
-     * no display surface was set, or the height has not been determined
-     * yet. The {@code EventCallback} can be registered via
-     * {@link #setEventCallback(Executor, EventCallback)} to provide a
-     * notification {@code EventCallback.onVideoSizeChanged} when the height is
-     * available.
-     */
-    public abstract int getVideoHeight();
+    public VideoSize getVideoSize() {
+        return mVideoSize;
+    }
 
     /**
      * Return Metrics data about the current player.
@@ -807,20 +1478,15 @@
      * available for the media being handled by this instance of MediaPlayer2
      * The attributes are descibed in {@link MetricsConstants}.
      *
-     *  Additional vendor-specific fields may also be present in
-     *  the return value.
+     * Additional vendor-specific fields may also be present in the return value.
      */
-    public abstract PersistableBundle getMetrics();
+    public PersistableBundle getMetrics() {
+        PersistableBundle bundle = native_getMetrics();
+        return bundle;
+    }
 
-    /**
-     * Checks whether the MediaPlayer2 is playing.
-     *
-     * @return true if currently playing, false otherwise
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized or has been released.
-     * @hide
-     */
-    public abstract boolean isPlaying();
+    private native PersistableBundle native_getMetrics();
+
 
     /**
      * Gets the current buffering management params used by the source component.
@@ -830,12 +1496,10 @@
      * @return the current buffering management params used by the source component.
      * @throws IllegalStateException if the internal player engine has not been
      * initialized, or {@code setDataSource} has not been called.
-     * @hide
      */
+    // TODO: make it public when ready
     @NonNull
-    public BufferingParams getBufferingParams() {
-        return new BufferingParams.Builder().build();
-    }
+    native BufferingParams getBufferingParams();
 
     /**
      * Sets buffering management params.
@@ -845,81 +1509,23 @@
      * The input is a hint to MediaPlayer2.
      *
      * @param params the buffering management params.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
-     *
-     * @hide
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
+    // TODO: make it public when ready
     // This is an asynchronous call.
-    public abstract Object setBufferingParams(@NonNull BufferingParams params);
-
-    /**
-     * Change playback speed of audio by resampling the audio.
-     * <p>
-     * Specifies resampling as audio mode for variable rate playback, i.e.,
-     * resample the waveform based on the requested playback rate to get
-     * a new waveform, and play back the new waveform at the original sampling
-     * frequency.
-     * When rate is larger than 1.0, pitch becomes higher.
-     * When rate is smaller than 1.0, pitch becomes lower.
-     *
-     * @hide
-     */
-    public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 2;
-
-    /**
-     * Change playback speed of audio without changing its pitch.
-     * <p>
-     * Specifies time stretching as audio mode for variable rate playback.
-     * Time stretching changes the duration of the audio samples without
-     * affecting its pitch.
-     * <p>
-     * This mode is only supported for a limited range of playback speed factors,
-     * e.g. between 1/2x and 2x.
-     *
-     * @hide
-     */
-    public static final int PLAYBACK_RATE_AUDIO_MODE_STRETCH = 1;
-
-    /**
-     * Change playback speed of audio without changing its pitch, and
-     * possibly mute audio if time stretching is not supported for the playback
-     * speed.
-     * <p>
-     * Try to keep audio pitch when changing the playback rate, but allow the
-     * system to determine how to change audio playback if the rate is out
-     * of range.
-     *
-     * @hide
-     */
-    public static final int PLAYBACK_RATE_AUDIO_MODE_DEFAULT = 0;
-
-    /** @hide */
-    @IntDef(flag = false, prefix = "PLAYBACK_RATE_AUDIO_MODE", value = {
-            PLAYBACK_RATE_AUDIO_MODE_DEFAULT,
-            PLAYBACK_RATE_AUDIO_MODE_STRETCH,
-            PLAYBACK_RATE_AUDIO_MODE_RESAMPLE,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface PlaybackRateAudioMode {}
-
-    /**
-     * Sets playback rate and audio mode.
-     *
-     * @param rate the ratio between desired playback rate and normal one.
-     * @param audioMode audio playback mode. Must be one of the supported
-     * audio modes.
-     *
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized.
-     * @throws IllegalArgumentException if audioMode is not supported.
-     *
-     * @hide
-     */
-    @NonNull
-    public PlaybackParams easyPlaybackParams(float rate, @PlaybackRateAudioMode int audioMode) {
-        return new PlaybackParams();
+    Object setBufferingParams(@NonNull BufferingParams params) {
+        return addTask(new Task(CALL_COMPLETED_SET_BUFFERING_PARAMS, false) {
+            @Override
+            void process() {
+                checkArgument(params != null, "the BufferingParams cannot be null");
+                native_setBufferingParams(params);
+            }
+        });
     }
 
+    private native void native_setBufferingParams(@NonNull BufferingParams params);
+
+
     /**
      * Sets playback rate using {@link PlaybackParams}. The object sets its internal
      * PlaybackParams to the input. This allows the object to resume at previous speed
@@ -927,35 +1533,69 @@
      * the object state.
      *
      * @param params the playback params.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object setPlaybackParams(@NonNull PlaybackParams params);
+    public Object setPlaybackParams(@NonNull PlaybackParams params) {
+        return addTask(new Task(CALL_COMPLETED_SET_PLAYBACK_PARAMS, false) {
+            @Override
+            void process() {
+                checkArgument(params != null, "the PlaybackParams cannot be null");
+                native_setPlaybackParams(params);
+            }
+        });
+    }
+
+    private native void native_setPlaybackParams(@NonNull PlaybackParams params);
 
     /**
      * Gets the playback params, containing the current playback rate.
      *
      * @return the playback params.
+     * @throws IllegalStateException if the internal player engine has not been initialized.
      */
     @NonNull
-    public abstract PlaybackParams getPlaybackParams();
+    public native PlaybackParams getPlaybackParams();
 
     /**
      * Sets A/V sync mode.
      *
      * @param params the A/V sync params to apply
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object setSyncParams(@NonNull SyncParams params);
+    public Object setSyncParams(@NonNull SyncParams params) {
+        return addTask(new Task(CALL_COMPLETED_SET_SYNC_PARAMS, false) {
+            @Override
+            void process() {
+                checkArgument(params != null, "the SyncParams cannot be null");
+                native_setSyncParams(params);
+            }
+        });
+    }
+
+    private native void native_setSyncParams(@NonNull SyncParams params);
 
     /**
      * Gets the A/V sync mode.
      *
      * @return the A/V sync params
+     * @throws IllegalStateException if the internal player engine has not been initialized.
      */
     @NonNull
-    public abstract SyncParams getSyncParams();
+    public native SyncParams getSyncParams();
+
+    /**
+     * Moves the media to specified time position.
+     * Same as {@link #seekTo(long, int)} with {@code mode = SEEK_PREVIOUS_SYNC}.
+     *
+     * @param msec the offset in milliseconds from the start to seek to
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
+     */
+    // This is an asynchronous call.
+    public Object seekTo(long msec) {
+        return seekTo(msec, SEEK_PREVIOUS_SYNC /* mode */);
+    }
 
     /**
      * Seek modes used in method seekTo(long, int) to move media position
@@ -1010,7 +1650,8 @@
     /**
      * Moves the media to specified time position by considering the given mode.
      * <p>
-     * When seekTo is finished, the user will be notified via OnSeekComplete supplied by the user.
+     * When seekTo is finished, the user will be notified via
+     * {@link EventCallback#onCallCompleted} with {@link #CALL_COMPLETED_SEEK_TO}.
      * There is at most one active seekTo processed at any time. If there is a to-be-completed
      * seekTo, new seekTo requests will be queued in such a way that only the last request
      * is kept. When current seekTo is completed, the queued request will be processed if
@@ -1023,10 +1664,50 @@
      * If msec is negative, time position zero will be used.
      * If msec is larger than duration, duration will be used.
      * @param mode the mode indicating where exactly to seek to.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object seekTo(long msec, @SeekMode int mode);
+    public Object seekTo(long msec, @SeekMode int mode) {
+        return addTask(new Task(CALL_COMPLETED_SEEK_TO, true) {
+            @Override
+            void process() {
+                if (mode < SEEK_PREVIOUS_SYNC || mode > SEEK_CLOSEST) {
+                    final String msg = "Illegal seek mode: " + mode;
+                    throw new IllegalArgumentException(msg);
+                }
+                // TODO: pass long to native, instead of truncating here.
+                long posMs = msec;
+                if (posMs > Integer.MAX_VALUE) {
+                    Log.w(TAG, "seekTo offset " + posMs + " is too large, cap to "
+                            + Integer.MAX_VALUE);
+                    posMs = Integer.MAX_VALUE;
+                } else if (posMs < Integer.MIN_VALUE) {
+                    Log.w(TAG, "seekTo offset " + posMs + " is too small, cap to "
+                            + Integer.MIN_VALUE);
+                    posMs = Integer.MIN_VALUE;
+                }
+
+                synchronized (mTaskLock) {
+                    if (mIsPreviousCommandSeekTo
+                            && mPreviousSeekPos == posMs
+                            && mPreviousSeekMode == mode) {
+                        throw new CommandSkippedException(
+                                "same as previous seekTo");
+                    }
+                }
+
+                native_seekTo(posMs, mode);
+
+                synchronized (mTaskLock) {
+                    mIsPreviousCommandSeekTo = true;
+                    mPreviousSeekPos = posMs;
+                    mPreviousSeekMode = mode;
+                }
+            }
+        });
+    }
+
+    private native void native_seekTo(long msec, int mode);
 
     /**
      * Get current playback position as a {@link MediaTimestamp}.
@@ -1047,25 +1728,25 @@
      * @see MediaTimestamp
      */
     @Nullable
-    public abstract MediaTimestamp getTimestamp();
-
-    /**
-     * Resets the MediaPlayer2 to its uninitialized state. After calling
-     * this method, you will have to initialize it again by setting the
-     * data source and calling prepare().
-     */
-    // This is a synchronous call.
-    public abstract void reset();
+    public MediaTimestamp getTimestamp() {
+        try {
+            // TODO: get the timestamp from native side
+            return new MediaTimestamp(
+                    getCurrentPosition() * 1000L,
+                    System.nanoTime(),
+                    getState() == PLAYER_STATE_PLAYING ? getPlaybackParams().getSpeed() : 0.f);
+        } catch (IllegalStateException e) {
+            return null;
+        }
+    }
 
     /**
      * Checks whether the MediaPlayer2 is looping or non-looping.
      *
      * @return true if the MediaPlayer2 is currently looping, false otherwise
-     * @hide
      */
-    public boolean isLooping() {
-        return false;
-    }
+    // This is a synchronous call.
+    public native boolean isLooping();
 
     /**
      * Sets the audio session ID.
@@ -1080,19 +1761,32 @@
      * When created, a MediaPlayer2 instance automatically generates its own audio session ID.
      * However, it is possible to force this player to be part of an already existing audio session
      * by calling this method.
-     * This method must be called before one of the overloaded <code> setDataSource </code> methods.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * This method must be called when player is in {@link #PLAYER_STATE_IDLE} or
+     * {@link #PLAYER_STATE_PREPARED} state in order to have sessionId take effect.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object setAudioSessionId(int sessionId);
+    public Object setAudioSessionId(int sessionId) {
+        keepAudioSessionIdAlive(sessionId);
+        return addTask(new Task(CALL_COMPLETED_SET_AUDIO_SESSION_ID, false) {
+            @Override
+            void process() {
+                native_setAudioSessionId(sessionId);
+            }
+        });
+    }
+
+    private native void native_setAudioSessionId(int sessionId);
 
     /**
      * Returns the audio session ID.
      *
      * @return the audio session ID. {@see #setAudioSessionId(int)}
-     * Note that the audio session ID is 0 only if a problem occured when the MediaPlayer2 was contructed.
+     * Note that the audio session ID is 0 only if a problem occured when the MediaPlayer2 was
+     * contructed.
      */
-    public abstract int getAudioSessionId();
+    // This is a synchronous call.
+    public native int getAudioSessionId();
 
     /**
      * Attaches an auxiliary effect to the player. A typical auxiliary effect is a reverberation
@@ -1107,11 +1801,19 @@
      * <p>This method must be called after one of the overloaded <code> setDataSource </code>
      * methods.
      * @param effectId system wide unique id of the effect to attach
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object attachAuxEffect(int effectId);
+    public Object attachAuxEffect(int effectId) {
+        return addTask(new Task(CALL_COMPLETED_ATTACH_AUX_EFFECT, false) {
+            @Override
+            void process() {
+                native_attachAuxEffect(effectId);
+            }
+        });
+    }
 
+    private native void native_attachAuxEffect(int effectId);
 
     /**
      * Sets the send level of the player to the attached auxiliary effect.
@@ -1124,23 +1826,75 @@
      * x == 0 -> level = 0
      * 0 < x <= R -> level = 10^(72*(x-R)/20/R)
      * @param level send level scalar
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object setAuxEffectSendLevel(float level);
+    public Object setAuxEffectSendLevel(float level) {
+        return addTask(new Task(CALL_COMPLETED_SET_AUX_EFFECT_SEND_LEVEL, false) {
+            @Override
+            void process() {
+                native_setAuxEffectSendLevel(level);
+            }
+        });
+    }
+
+    private native void native_setAuxEffectSendLevel(float level);
+
+    private static native void native_stream_event_onTearDown(
+            long nativeCallbackPtr, long userDataPtr);
+    private static native void native_stream_event_onStreamPresentationEnd(
+            long nativeCallbackPtr, long userDataPtr);
+    private static native void native_stream_event_onStreamDataRequest(
+            long jAudioTrackPtr, long nativeCallbackPtr, long userDataPtr);
+
+    /* Do not change these values (starting with INVOKE_ID) without updating
+     * their counterparts in include/media/mediaplayer2.h!
+     */
+    private static final int INVOKE_ID_GET_TRACK_INFO = 1;
+    private static final int INVOKE_ID_ADD_EXTERNAL_SOURCE = 2;
+    private static final int INVOKE_ID_ADD_EXTERNAL_SOURCE_FD = 3;
+    private static final int INVOKE_ID_SELECT_TRACK = 4;
+    private static final int INVOKE_ID_DESELECT_TRACK = 5;
+    private static final int INVOKE_ID_GET_SELECTED_TRACK = 7;
+
+    /**
+     * Invoke a generic method on the native player using opaque protocol
+     * buffer message for the request and reply. Both payloads' format is a
+     * convention between the java caller and the native player.
+     *
+     * @param msg PlayerMessage for the extension.
+     *
+     * @return PlayerMessage with the data returned by the
+     * native player.
+     */
+    private PlayerMessage invoke(PlayerMessage msg) {
+        byte[] ret = native_invoke(msg.toByteArray());
+        if (ret == null) {
+            return null;
+        }
+        try {
+            return PlayerMessage.parseFrom(ret);
+        } catch (InvalidProtocolBufferException e) {
+            return null;
+        }
+    }
+
+    private native byte[] native_invoke(byte[] request);
 
     /**
      * Class for MediaPlayer2 to return each audio/video/subtitle track's metadata.
      *
      * @see MediaPlayer2#getTrackInfo
      */
-    public abstract static class TrackInfo {
+    public static class TrackInfo {
         /**
          * Gets the track type.
          * @return TrackType which indicates if the track is video, audio, timed text.
          */
         @UnsupportedAppUsage
-        public abstract int getTrackType();
+        public int getTrackType() {
+            return mTrackType;
+        }
 
         /**
          * Gets the language code of the track.
@@ -1149,13 +1903,22 @@
          * ISO-639-2 language code, "und", is returned.
          */
         @UnsupportedAppUsage
-        public abstract String getLanguage();
+        public String getLanguage() {
+            String language = mFormat.getString(MediaFormat.KEY_LANGUAGE);
+            return language == null ? "und" : language;
+        }
 
         /**
          * Gets the {@link MediaFormat} of the track.  If the format is
          * unknown or could not be determined, null is returned.
          */
-        public abstract MediaFormat getFormat();
+        public MediaFormat getFormat() {
+            if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT
+                    || mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
+                return mFormat;
+            }
+            return null;
+        }
 
         public static final int MEDIA_TRACK_TYPE_UNKNOWN = 0;
         public static final int MEDIA_TRACK_TYPE_VIDEO = 1;
@@ -1167,8 +1930,56 @@
         public static final int MEDIA_TRACK_TYPE_SUBTITLE = 4;
         public static final int MEDIA_TRACK_TYPE_METADATA = 5;
 
+        final int mTrackType;
+        final MediaFormat mFormat;
+
+        TrackInfo(Iterator<Value> in) {
+            mTrackType = in.next().getInt32Value();
+            // TODO: build the full MediaFormat; currently we are using createSubtitleFormat
+            // even for audio/video tracks, meaning we only set the mime and language.
+            String mime = in.next().getStringValue();
+            String language = in.next().getStringValue();
+            mFormat = MediaFormat.createSubtitleFormat(mime, language);
+
+            if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
+                mFormat.setInteger(MediaFormat.KEY_IS_AUTOSELECT, in.next().getInt32Value());
+                mFormat.setInteger(MediaFormat.KEY_IS_DEFAULT, in.next().getInt32Value());
+                mFormat.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.next().getInt32Value());
+            }
+        }
+
+        /** @hide */
+        TrackInfo(int type, MediaFormat format) {
+            mTrackType = type;
+            mFormat = format;
+        }
+
         @Override
-        public abstract String toString();
+        public String toString() {
+            StringBuilder out = new StringBuilder(128);
+            out.append(getClass().getName());
+            out.append('{');
+            switch (mTrackType) {
+                case MEDIA_TRACK_TYPE_VIDEO:
+                    out.append("VIDEO");
+                    break;
+                case MEDIA_TRACK_TYPE_AUDIO:
+                    out.append("AUDIO");
+                    break;
+                case MEDIA_TRACK_TYPE_TIMEDTEXT:
+                    out.append("TIMEDTEXT");
+                    break;
+                case MEDIA_TRACK_TYPE_SUBTITLE:
+                    out.append("SUBTITLE");
+                    break;
+                default:
+                    out.append("UNKNOWN");
+                    break;
+            }
+            out.append(", " + mFormat.toString());
+            out.append("}");
+            return out.toString();
+        }
     };
 
     /**
@@ -1177,35 +1988,32 @@
      * @return List of track info. The total number of tracks is the array length.
      * Must be called again if an external timed text source has been added after
      * addTimedTextSource method is called.
+     * @throws IllegalStateException if it is called in an invalid state.
      */
-    public abstract List<TrackInfo> getTrackInfo();
+    public List<TrackInfo> getTrackInfo() {
+        TrackInfo[] trackInfo = getInbandTrackInfo();
+        return Arrays.asList(trackInfo);
+    }
 
-    /* Do not change these values without updating their counterparts
-     * in include/media/stagefright/MediaDefs.h and media/libstagefright/MediaDefs.cpp!
-     */
-    /**
-     * MIME type for SubRip (SRT) container. Used in addTimedTextSource APIs.
-     * @hide
-     */
-    public static final String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
-
-    /**
-     * MIME type for WebVTT subtitle data.
-     * @hide
-     */
-    public static final String MEDIA_MIMETYPE_TEXT_VTT = "text/vtt";
-
-    /**
-     * MIME type for CEA-608 closed caption data.
-     * @hide
-     */
-    public static final String MEDIA_MIMETYPE_TEXT_CEA_608 = "text/cea-608";
-
-    /**
-     * MIME type for CEA-708 closed caption data.
-     * @hide
-     */
-    public static final String MEDIA_MIMETYPE_TEXT_CEA_708 = "text/cea-708";
+    private TrackInfo[] getInbandTrackInfo() throws IllegalStateException {
+        PlayerMessage request = PlayerMessage.newBuilder()
+                .addValues(Value.newBuilder().setInt32Value(INVOKE_ID_GET_TRACK_INFO))
+                .build();
+        PlayerMessage response = invoke(request);
+        if (response == null) {
+            return null;
+        }
+        Iterator<Value> in = response.getValuesList().iterator();
+        int size = in.next().getInt32Value();
+        if (size == 0) {
+            return null;
+        }
+        TrackInfo[] trackInfo = new TrackInfo[size];
+        for (int i = 0; i < size; ++i) {
+            trackInfo[i] = new TrackInfo(in);
+        }
+        return trackInfo;
+    }
 
     /**
      * Returns the index of the audio, video, or subtitle track currently selected for playback,
@@ -1224,7 +2032,17 @@
      * @see #selectTrack(int)
      * @see #deselectTrack(int)
      */
-    public abstract int getSelectedTrack(int trackType);
+    public int getSelectedTrack(int trackType) {
+        PlayerMessage request = PlayerMessage.newBuilder()
+                .addValues(Value.newBuilder().setInt32Value(INVOKE_ID_GET_SELECTED_TRACK))
+                .addValues(Value.newBuilder().setInt32Value(trackType))
+                .build();
+        PlayerMessage response = invoke(request);
+        if (response == null) {
+            return -1;
+        }
+        return response.getValues(0).getInt32Value();
+    }
 
     /**
      * Selects a track.
@@ -1250,12 +2068,19 @@
      * @param index the index of the track to be selected. The valid range of the index
      * is 0..total number of track - 1. The total number of tracks as well as the type of
      * each individual track can be found by calling {@link #getTrackInfo()} method.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      *
      * @see MediaPlayer2#getTrackInfo
      */
     // This is an asynchronous call.
-    public abstract Object selectTrack(int index);
+    public Object selectTrack(int index) {
+        return addTask(new Task(CALL_COMPLETED_SELECT_TRACK, false) {
+            @Override
+            void process() {
+                selectOrDeselectTrack(index, true /* select */);
+            }
+        });
+    }
 
     /**
      * Deselect a track.
@@ -1267,18 +2092,455 @@
      * @param index the index of the track to be deselected. The valid range of the index
      * is 0..total number of tracks - 1. The total number of tracks as well as the type of
      * each individual track can be found by calling {@link #getTrackInfo()} method.
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      *
      * @see MediaPlayer2#getTrackInfo
      */
     // This is an asynchronous call.
-    public abstract Object deselectTrack(int index);
+    public Object deselectTrack(int index) {
+        return addTask(new Task(CALL_COMPLETED_DESELECT_TRACK, false) {
+            @Override
+            void process() {
+                selectOrDeselectTrack(index, false /* select */);
+            }
+        });
+    }
+
+    private void selectOrDeselectTrack(int index, boolean select)
+            throws IllegalStateException {
+        PlayerMessage request = PlayerMessage.newBuilder()
+                .addValues(Value.newBuilder().setInt32Value(
+                            select ? INVOKE_ID_SELECT_TRACK : INVOKE_ID_DESELECT_TRACK))
+                .addValues(Value.newBuilder().setInt32Value(index))
+                .build();
+        invoke(request);
+    }
+
+    /* Do not change these values without updating their counterparts
+     * in include/media/mediaplayer2.h!
+     */
+    private static final int MEDIA_NOP = 0; // interface test message
+    private static final int MEDIA_PREPARED = 1;
+    private static final int MEDIA_PLAYBACK_COMPLETE = 2;
+    private static final int MEDIA_BUFFERING_UPDATE = 3;
+    private static final int MEDIA_SEEK_COMPLETE = 4;
+    private static final int MEDIA_SET_VIDEO_SIZE = 5;
+    private static final int MEDIA_STARTED = 6;
+    private static final int MEDIA_PAUSED = 7;
+    private static final int MEDIA_STOPPED = 8;
+    private static final int MEDIA_SKIPPED = 9;
+    private static final int MEDIA_NOTIFY_TIME = 98;
+    private static final int MEDIA_TIMED_TEXT = 99;
+    private static final int MEDIA_ERROR = 100;
+    private static final int MEDIA_INFO = 200;
+    private static final int MEDIA_SUBTITLE_DATA = 201;
+    private static final int MEDIA_META_DATA = 202;
+    private static final int MEDIA_DRM_INFO = 210;
+
+    private class TaskHandler extends Handler {
+        private MediaPlayer2 mMediaPlayer;
+
+        TaskHandler(MediaPlayer2 mp, Looper looper) {
+            super(looper);
+            mMediaPlayer = mp;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            handleMessage(msg, 0);
+        }
+
+        public void handleMessage(Message msg, long srcId) {
+            if (mMediaPlayer.mNativeContext == 0) {
+                Log.w(TAG, "mediaplayer2 went away with unhandled events");
+                return;
+            }
+            final int what = msg.arg1;
+            final int extra = msg.arg2;
+
+            final SourceInfo sourceInfo = getSourceInfoById(srcId);
+            if (sourceInfo == null) {
+                return;
+            }
+            final DataSourceDesc dsd = sourceInfo.mDSD;
+
+            switch(msg.what) {
+                case MEDIA_PREPARED:
+                {
+                    if (dsd != null) {
+                        sendEvent(new EventNotifier() {
+                            @Override
+                            public void notify(EventCallback callback) {
+                                callback.onInfo(
+                                        mMediaPlayer, dsd, MEDIA_INFO_PREPARED, 0);
+                            }
+                        });
+                    }
+
+                    synchronized (mSrcLock) {
+                        SourceInfo nextSourceInfo = mNextSourceInfos.peek();
+                        Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
+                                + ", curSrc=" + mCurrentSourceInfo
+                                + ", nextSrc=" + nextSourceInfo);
+
+                        if (isCurrentSource(srcId)) {
+                            prepareNextDataSource();
+                        } else if (isNextSource(srcId)) {
+                            nextSourceInfo.mStateAsNextSource = NEXT_SOURCE_STATE_PREPARED;
+                            if (nextSourceInfo.mPlayPendingAsNextSource) {
+                                playNextDataSource();
+                            }
+                        }
+                    }
+
+                    synchronized (mTaskLock) {
+                        if (mCurrentTask != null
+                                && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE
+                                && mCurrentTask.mDSD == dsd
+                                && mCurrentTask.mNeedToWaitForEventToComplete) {
+                            mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
+                            mCurrentTask = null;
+                            processPendingTask_l();
+                        }
+                    }
+                    return;
+                }
+
+                case MEDIA_DRM_INFO:
+                {
+                    if (msg.obj == null) {
+                        Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
+                    } else if (msg.obj instanceof byte[]) {
+                        // The PlayerMessage was parsed already in postEventFromNative
+                        final DrmInfo drmInfo;
+
+                        synchronized (mDrmLock) {
+                            if (mDrmInfo != null) {
+                                drmInfo = mDrmInfo.makeCopy();
+                            } else {
+                                drmInfo = null;
+                            }
+                        }
+
+                        // notifying the client outside the lock
+                        if (drmInfo != null) {
+                            sendDrmEvent(new DrmEventNotifier() {
+                                @Override
+                                public void notify(DrmEventCallback callback) {
+                                    callback.onDrmInfo(
+                                            mMediaPlayer, dsd, drmInfo);
+                                }
+                            });
+                        }
+                    } else {
+                        Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + msg.obj);
+                    }
+                    return;
+                }
+
+                case MEDIA_PLAYBACK_COMPLETE:
+                {
+                    if (isCurrentSource(srcId)) {
+                        sendEvent(new EventNotifier() {
+                            @Override
+                            public void notify(EventCallback callback) {
+                                callback.onInfo(
+                                        mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0);
+                            }
+                        });
+                        stayAwake(false);
+
+                        synchronized (mSrcLock) {
+                            SourceInfo nextSourceInfo = mNextSourceInfos.peek();
+                            if (nextSourceInfo != null) {
+                                nextSourceInfo.mPlayPendingAsNextSource = true;
+                            }
+                            Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId
+                                    + ", curSrc=" + mCurrentSourceInfo
+                                    + ", nextSrc=" + nextSourceInfo);
+                        }
+
+                        playNextDataSource();
+                    }
+
+                    return;
+                }
+
+                case MEDIA_STOPPED:
+                case MEDIA_STARTED:
+                case MEDIA_PAUSED:
+                case MEDIA_SKIPPED:
+                case MEDIA_NOTIFY_TIME:
+                {
+                    // Do nothing. The client should have enough information with
+                    // {@link EventCallback#onMediaTimeDiscontinuity}.
+                    break;
+                }
+
+                case MEDIA_BUFFERING_UPDATE:
+                {
+                    final int percent = msg.arg1;
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onInfo(
+                                    mMediaPlayer, dsd, MEDIA_INFO_BUFFERING_UPDATE, percent);
+                        }
+                    });
+
+                    SourceInfo src = getSourceInfoById(srcId);
+                    if (src != null) {
+                        src.mBufferedPercentage.set(percent);
+                    }
+
+                    return;
+                }
+
+                case MEDIA_SEEK_COMPLETE:
+                {
+                    synchronized (mTaskLock) {
+                        if (!mPendingTasks.isEmpty()
+                                && mPendingTasks.get(0).mMediaCallType != CALL_COMPLETED_SEEK_TO
+                                && getState() == PLAYER_STATE_PLAYING) {
+                            mIsPreviousCommandSeekTo = false;
+                        }
+
+                        if (mCurrentTask != null
+                                && mCurrentTask.mMediaCallType == CALL_COMPLETED_SEEK_TO
+                                && mCurrentTask.mNeedToWaitForEventToComplete) {
+                            mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
+                            mCurrentTask = null;
+                            processPendingTask_l();
+                        }
+                    }
+                    return;
+                }
+
+                case MEDIA_SET_VIDEO_SIZE:
+                {
+                    final int width = msg.arg1;
+                    final int height = msg.arg2;
+
+                    mVideoSize = new VideoSize(width, height);
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onVideoSizeChanged(
+                                    mMediaPlayer, dsd, mVideoSize);
+                        }
+                    });
+                    return;
+                }
+
+                case MEDIA_ERROR:
+                {
+                    Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onError(
+                                    mMediaPlayer, dsd, what, extra);
+                        }
+                    });
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onInfo(
+                                    mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0);
+                        }
+                    });
+                    stayAwake(false);
+                    return;
+                }
+
+                case MEDIA_INFO:
+                {
+                    switch (msg.arg1) {
+                        case MEDIA_INFO_VIDEO_TRACK_LAGGING:
+                            Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")");
+                            break;
+                    }
+
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onInfo(
+                                    mMediaPlayer, dsd, what, extra);
+                        }
+                    });
+
+                    if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) {
+                        if (isCurrentSource(srcId)) {
+                            prepareNextDataSource();
+                        }
+                    }
+
+                    // No real default action so far.
+                    return;
+                }
+
+                case MEDIA_TIMED_TEXT:
+                {
+                    final TimedText text;
+                    if (msg.obj instanceof byte[]) {
+                        PlayerMessage playerMsg;
+                        try {
+                            playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
+                        } catch (InvalidProtocolBufferException e) {
+                            Log.w(TAG, "Failed to parse timed text.", e);
+                            return;
+                        }
+                        text = TimedTextUtil.parsePlayerMessage(playerMsg);
+                    } else {
+                        text = null;
+                    }
+
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onTimedText(
+                                    mMediaPlayer, dsd, text);
+                        }
+                    });
+                    return;
+                }
+
+                case MEDIA_SUBTITLE_DATA:
+                {
+                    if (msg.obj instanceof byte[]) {
+                        PlayerMessage playerMsg;
+                        try {
+                            playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
+                        } catch (InvalidProtocolBufferException e) {
+                            Log.w(TAG, "Failed to parse subtitle data.", e);
+                            return;
+                        }
+                        Iterator<Value> in = playerMsg.getValuesList().iterator();
+                        SubtitleData data = new SubtitleData(
+                                in.next().getInt32Value(),  // trackIndex
+                                in.next().getInt64Value(),  // startTimeUs
+                                in.next().getInt64Value(),  // durationUs
+                                in.next().getBytesValue().toByteArray());  // data
+                        sendEvent(new EventNotifier() {
+                            @Override
+                            public void notify(EventCallback callback) {
+                                callback.onSubtitleData(
+                                        mMediaPlayer, dsd, data);
+                            }
+                        });
+                    }
+                    return;
+                }
+
+                case MEDIA_META_DATA:
+                {
+                    final TimedMetaData data;
+                    if (msg.obj instanceof byte[]) {
+                        PlayerMessage playerMsg;
+                        try {
+                            playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
+                        } catch (InvalidProtocolBufferException e) {
+                            Log.w(TAG, "Failed to parse timed meta data.", e);
+                            return;
+                        }
+                        Iterator<Value> in = playerMsg.getValuesList().iterator();
+                        data = new TimedMetaData(
+                                in.next().getInt64Value(),  // timestampUs
+                                in.next().getBytesValue().toByteArray());  // metaData
+                    } else {
+                        data = null;
+                    }
+
+                    sendEvent(new EventNotifier() {
+                        @Override
+                        public void notify(EventCallback callback) {
+                            callback.onTimedMetaDataAvailable(
+                                    mMediaPlayer, dsd, data);
+                        }
+                    });
+                    return;
+                }
+
+                case MEDIA_NOP: // interface test message - ignore
+                {
+                    break;
+                }
+
+                default:
+                {
+                    Log.e(TAG, "Unknown message type " + msg.what);
+                    return;
+                }
+            }
+        }
+    }
+
+    /*
+     * Called from native code when an interesting event happens.  This method
+     * just uses the TaskHandler system to post the event back to the main app thread.
+     * We use a weak reference to the original MediaPlayer2 object so that the native
+     * code is safe from the object disappearing from underneath it.  (This is
+     * the cookie passed to native_setup().)
+     */
+    private static void postEventFromNative(Object mediaplayer2Ref, long srcId,
+                                            int what, int arg1, int arg2, byte[] obj) {
+        final MediaPlayer2 mp = (MediaPlayer2) ((WeakReference) mediaplayer2Ref).get();
+        if (mp == null) {
+            return;
+        }
+
+        switch (what) {
+            case MEDIA_DRM_INFO:
+                // We need to derive mDrmInfo before prepare() returns so processing it here
+                // before the notification is sent to TaskHandler below. TaskHandler runs in the
+                // notification looper so its handleMessage might process the event after prepare()
+                // has returned.
+                Log.v(TAG, "postEventFromNative MEDIA_DRM_INFO");
+                if (obj != null) {
+                    PlayerMessage playerMsg;
+                    try {
+                        playerMsg = PlayerMessage.parseFrom(obj);
+                    } catch (InvalidProtocolBufferException e) {
+                        Log.w(TAG, "MEDIA_DRM_INFO failed to parse msg.obj " + obj);
+                        break;
+                    }
+                    DrmInfo drmInfo = new DrmInfo(playerMsg);
+                    synchronized (mp.mDrmLock) {
+                        mp.mDrmInfo = drmInfo;
+                    }
+                } else {
+                    Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + obj);
+                }
+                break;
+
+            case MEDIA_PREPARED:
+                // By this time, we've learned about DrmInfo's presence or absence. This is meant
+                // mainly for prepare() use case. For prepare(), this still can run to a race
+                // condition b/c MediaPlayerNative releases the prepare() lock before calling notify
+                // so we also set mDrmInfoResolved in prepare().
+                synchronized (mp.mDrmLock) {
+                    mp.mDrmInfoResolved = true;
+                }
+                break;
+        }
+
+        if (mp.mTaskHandler != null) {
+            Message m = mp.mTaskHandler.obtainMessage(what, arg1, arg2, obj);
+
+            mp.mTaskHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mp.mTaskHandler.handleMessage(m, srcId);
+                }
+            });
+        }
+    }
 
     /**
      * Interface definition for callbacks to be invoked when the player has the corresponding
      * events.
      */
-    public abstract static class EventCallback {
+    public static class EventCallback {
         /**
          * Called to indicate the video size
          *
@@ -1287,11 +2549,10 @@
          *
          * @param mp the MediaPlayer2 associated with this callback
          * @param dsd the DataSourceDesc of this data source
-         * @param width the width of the video
-         * @param height the height of the video
+         * @param size the size of the video
          */
         public void onVideoSizeChanged(
-                MediaPlayer2 mp, DataSourceDesc dsd, int width, int height) { }
+                MediaPlayer2 mp, DataSourceDesc dsd, VideoSize size) { }
 
         /**
          * Called to indicate an avaliable timed text
@@ -1389,6 +2650,10 @@
                 MediaPlayer2 mp, DataSourceDesc dsd, @NonNull SubtitleData data) { }
     }
 
+    private final Object mEventCbLock = new Object();
+    private ArrayList<Pair<Executor, EventCallback>> mEventCallbackRecords =
+            new ArrayList<Pair<Executor, EventCallback>>();
+
     /**
      * Registers the callback to be invoked for various events covered by {@link EventCallback}.
      *
@@ -1396,8 +2661,19 @@
      * @param eventCallback the callback that will be run
      */
     // This is a synchronous call.
-    public abstract void registerEventCallback(@NonNull @CallbackExecutor Executor executor,
-            @NonNull EventCallback eventCallback);
+    public void registerEventCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull EventCallback eventCallback) {
+        if (eventCallback == null) {
+            throw new IllegalArgumentException("Illegal null EventCallback");
+        }
+        if (executor == null) {
+            throw new IllegalArgumentException(
+                    "Illegal null Executor for the EventCallback");
+        }
+        synchronized (mEventCbLock) {
+            mEventCallbackRecords.add(new Pair(executor, eventCallback));
+        }
+    }
 
     /**
      * Unregisters the {@link EventCallback}.
@@ -1405,10 +2681,58 @@
      * @param eventCallback the callback to be unregistered
      */
     // This is a synchronous call.
-    public abstract void unregisterEventCallback(EventCallback eventCallback);
+    public void unregisterEventCallback(EventCallback eventCallback) {
+        synchronized (mEventCbLock) {
+            for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                if (cb.second == eventCallback) {
+                    mEventCallbackRecords.remove(cb);
+                }
+            }
+        }
+    }
+
+    private static void checkArgument(boolean expression, String errorMessage) {
+        if (!expression) {
+            throw new IllegalArgumentException(errorMessage);
+        }
+    }
+
+    private void sendEvent(final EventNotifier notifier) {
+        synchronized (mEventCbLock) {
+            try {
+                for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
+                    cb.first.execute(() -> notifier.notify(cb.second));
+                }
+            } catch (RejectedExecutionException e) {
+                // The executor has been shut down.
+                Log.w(TAG, "The executor has been shut down. Ignoring event.");
+            }
+        }
+    }
+
+    private void sendDrmEvent(final DrmEventNotifier notifier) {
+        synchronized (mDrmEventCbLock) {
+            try {
+                for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
+                    cb.first.execute(() -> notifier.notify(cb.second));
+                }
+            } catch (RejectedExecutionException e) {
+                // The executor has been shut down.
+                Log.w(TAG, "The executor has been shut down. Ignoring drm event.");
+            }
+        }
+    }
+
+    private interface EventNotifier {
+        void notify(EventCallback callback);
+    }
+
+    private interface DrmEventNotifier {
+        void notify(DrmEventCallback callback);
+    }
 
     /* Do not change these values without updating their counterparts
-     * in include/media/mediaplayer2.h!
+     * in include/media/MediaPlayer2Types.h!
      */
     /** Unspecified media player error.
      * @see EventCallback#onError
@@ -1719,18 +3043,21 @@
      */
     public static final int CALL_COMPLETED_SET_BUFFERING_PARAMS = 31;
 
-    /** The player just completed a call {@link #setVideoScalingMode}.
-     * @see EventCallback#onCallCompleted
-     * @hide
-     */
-    public static final int CALL_COMPLETED_SET_VIDEO_SCALING_MODE = 32;
-
     /** The player just completed a call {@link #setDisplay}.
      * @see EventCallback#onCallCompleted
-     * @hide
      */
     public static final int CALL_COMPLETED_SET_DISPLAY = 33;
 
+    /** The player just completed a call {@link #setWakeMode}.
+     * @see EventCallback#onCallCompleted
+     */
+    public static final int CALL_COMPLETED_SET_WAKE_MODE = 34;
+
+    /** The player just completed a call {@link #setScreenOnWhilePlaying}.
+     * @see EventCallback#onCallCompleted
+     */
+    public static final int CALL_COMPLETED_SET_SCREEN_ON_WHILE_PLAYING = 35;
+
     /**
      * The start of the methods which have separate call complete callback.
      * @hide
@@ -1744,7 +3071,7 @@
     public static final int CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED =
             SEPARATE_CALL_COMPLETED_CALLBACK_START;
 
-    /** The player just completed a call {@link #prepareDrm}.
+    /** The player just completed a call {@link #prepareDrm(DataSourceDesc, UUID)}.
      * @see DrmEventCallback#onDrmPrepared
      * @hide
      */
@@ -1776,8 +3103,9 @@
             CALL_COMPLETED_SKIP_TO_NEXT,
             CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES,
             CALL_COMPLETED_SET_BUFFERING_PARAMS,
-            CALL_COMPLETED_SET_VIDEO_SCALING_MODE,
             CALL_COMPLETED_SET_DISPLAY,
+            CALL_COMPLETED_SET_WAKE_MODE,
+            CALL_COMPLETED_SET_SCREEN_ON_WHILE_PLAYING,
             CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED,
             CALL_COMPLETED_PREPARE_DRM,
     })
@@ -1821,7 +3149,7 @@
     public static final int CALL_STATUS_SKIPPED = 5;
 
     /** Status code represents that DRM operation is called before preparing a DRM scheme through
-     *  {@link #prepareDrm}.
+     *  {@link #prepareDrm(DataSourceDesc, UUID)}.
      * @see EventCallback#onCallCompleted
      */
     public static final int CALL_STATUS_NO_DRM_SCHEME = 6;
@@ -1850,11 +3178,11 @@
      * 'securityLevel', which has to be set after DRM scheme creation but
      * before the DRM session is opened.
      *
-     * The only allowed DRM calls in this listener are {@link #getDrmPropertyString}
-     * and {@link #setDrmPropertyString}.
+     * The only allowed DRM calls in this listener are
+     * {@link MediaPlayer2#getDrmPropertyString(DataSourceDesc, String)}
+     * and {@link MediaPlayer2#setDrmPropertyString(DataSourceDesc, String, String)}.
      */
-    public interface OnDrmConfigHelper
-    {
+    public interface OnDrmConfigHelper {
         /**
          * Called to give the app the opportunity to configure DRM before the session is created
          *
@@ -1868,18 +3196,24 @@
      * Register a callback to be invoked for configuration of the DRM object before
      * the session is created.
      * The callback will be invoked synchronously during the execution
-     * of {@link #prepareDrm(UUID uuid)}.
+     * of {@link #prepareDrm(DataSourceDesc, UUID)}.
      *
      * @param listener the callback that will be run
      */
     // This is a synchronous call.
-    public abstract void setOnDrmConfigHelper(OnDrmConfigHelper listener);
+    public void setOnDrmConfigHelper(OnDrmConfigHelper listener) {
+        synchronized (mDrmLock) {
+            mOnDrmConfigHelper = listener;
+        }
+    }
+
+    private OnDrmConfigHelper mOnDrmConfigHelper;
 
     /**
      * Interface definition for callbacks to be invoked when the player has the corresponding
      * DRM events.
      */
-    public abstract static class DrmEventCallback {
+    public static class DrmEventCallback {
         /**
          * Called to indicate DRM info is available
          *
@@ -1891,8 +3225,8 @@
         public void onDrmInfo(MediaPlayer2 mp, DataSourceDesc dsd, DrmInfo drmInfo) { }
 
         /**
-         * Called to notify the client that {@link #prepareDrm} is finished and ready for
-         * key request/response.
+         * Called to notify the client that {@link MediaPlayer2#prepareDrm(DataSourceDesc, UUID)}
+         * is finished and ready for key request/response.
          *
          * @param mp the {@code MediaPlayer2} associated with this callback
          * @param dsd the DataSourceDesc of this data source
@@ -1902,6 +3236,10 @@
                 MediaPlayer2 mp, DataSourceDesc dsd, @PrepareDrmStatusCode int status) { }
     }
 
+    private final Object mDrmEventCbLock = new Object();
+    private ArrayList<Pair<Executor, DrmEventCallback>> mDrmEventCallbackRecords =
+            new ArrayList<Pair<Executor, DrmEventCallback>>();
+
     /**
      * Registers the callback to be invoked for various DRM events.
      *
@@ -1909,8 +3247,19 @@
      * @param executor the executor through which the callback should be invoked
      */
     // This is a synchronous call.
-    public abstract void registerDrmEventCallback(@NonNull @CallbackExecutor Executor executor,
-            @NonNull DrmEventCallback eventCallback);
+    public void registerDrmEventCallback(@NonNull @CallbackExecutor Executor executor,
+            @NonNull DrmEventCallback eventCallback) {
+        if (eventCallback == null) {
+            throw new IllegalArgumentException("Illegal null EventCallback");
+        }
+        if (executor == null) {
+            throw new IllegalArgumentException(
+                    "Illegal null Executor for the EventCallback");
+        }
+        synchronized (mDrmEventCbLock) {
+            mDrmEventCallbackRecords.add(new Pair(executor, eventCallback));
+        }
+    }
 
     /**
      * Unregisters the {@link DrmEventCallback}.
@@ -1918,7 +3267,15 @@
      * @param eventCallback the callback to be unregistered
      */
     // This is a synchronous call.
-    public abstract void unregisterDrmEventCallback(DrmEventCallback eventCallback);
+    public void unregisterDrmEventCallback(DrmEventCallback eventCallback) {
+        synchronized (mDrmEventCbLock) {
+            for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
+                if (cb.second == eventCallback) {
+                    mDrmEventCallbackRecords.remove(cb);
+                }
+            }
+        }
+    }
 
     /**
      * The status codes for {@link DrmEventCallback#onDrmPrepared} listener.
@@ -1966,19 +3323,42 @@
     public @interface PrepareDrmStatusCode {}
 
     /**
-     * Retrieves the DRM Info associated with the current source
+     * Retrieves the DRM Info associated with the given source
+     *
+     * @param dsd The DRM protected data source
      *
      * @throws IllegalStateException if called before being prepared
      */
-    public abstract DrmInfo getDrmInfo();
+    public DrmInfo getDrmInfo(@NonNull DataSourceDesc dsd) {
+        // TODO: this implementation only works when dsd is the only data source
+        DrmInfo drmInfo = null;
+
+        // there is not much point if the app calls getDrmInfo within an OnDrmInfoListenet;
+        // regardless below returns drmInfo anyway instead of raising an exception
+        synchronized (mDrmLock) {
+            if (!mDrmInfoResolved && mDrmInfo == null) {
+                final String msg = "The Player has not been prepared yet";
+                Log.v(TAG, msg);
+                throw new IllegalStateException(msg);
+            }
+
+            if (mDrmInfo != null) {
+                drmInfo = mDrmInfo.makeCopy();
+            }
+        }  // synchronized
+
+        return drmInfo;
+    }
 
     /**
-     * Prepares the DRM for the current source
+     * Prepares the DRM for the given data source
      * <p>
      * If {@link OnDrmConfigHelper} is registered, it will be called during
      * preparation to allow configuration of the DRM properties before opening the
-     * DRM session. It should be used only for a series of {@link #getDrmPropertyString}
-     * and {@link #setDrmPropertyString} calls and refrain from any lengthy operation.
+     * DRM session. It should be used only for a series of
+     * {@link #getDrmPropertyString(DataSourceDesc, String)} and
+     * {@link #setDrmPropertyString(DataSourceDesc, String, String)} calls
+     * and refrain from any lengthy operation.
      * <p>
      * If the device has not been provisioned before, this call also provisions the device
      * which involves accessing the provisioning server and can take a variable time to
@@ -1993,40 +3373,233 @@
      * sequence (e.g., before or after prepareDrm returns).
      * <p>
      *
+     * @param dsd The DRM protected data source
+     *
      * @param uuid The UUID of the crypto scheme. If not known beforehand, it can be retrieved
-     * from the source through {@code getDrmInfo} or registering a
+     * from the source through {@link #getDrmInfo(DataSourceDesc)} or registering a
      * {@link DrmEventCallback#onDrmInfo}.
      *
-     * @return a token which can be used to cancel the operation later with {@link #cancel}.
+     * @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
      */
     // This is an asynchronous call.
-    public abstract Object prepareDrm(@NonNull UUID uuid);
+    public Object prepareDrm(@NonNull DataSourceDesc dsd, @NonNull UUID uuid) {
+        // TODO: this implementation only works when dsd is the only data source
+        return addTask(new Task(CALL_COMPLETED_PREPARE_DRM, true) {
+            @Override
+            void process() {
+                int status = PREPARE_DRM_STATUS_SUCCESS;
+                boolean sendEvent = true;
+
+                try {
+                    doPrepareDrm(dsd, uuid);
+                } catch (ResourceBusyException e) {
+                    status = PREPARE_DRM_STATUS_RESOURCE_BUSY;
+                } catch (UnsupportedSchemeException e) {
+                    status = PREPARE_DRM_STATUS_UNSUPPORTED_SCHEME;
+                } catch (NotProvisionedException e) {
+                    Log.w(TAG, "prepareDrm: NotProvisionedException");
+
+                    // handle provisioning internally; it'll reset mPrepareDrmInProgress
+                    status = handleProvisioninig(dsd, uuid);
+
+                    if (status == PREPARE_DRM_STATUS_SUCCESS) {
+                        // DrmEventCallback will be fired in provisioning
+                        sendEvent = false;
+                    } else {
+                        synchronized (mDrmLock) {
+                            cleanDrmObj();
+                        }
+
+                        switch (status) {
+                            case PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR:
+                                Log.e(TAG, "prepareDrm: Provisioning was required but failed "
+                                        + "due to a network error.");
+                                break;
+
+                            case PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR:
+                                Log.e(TAG, "prepareDrm: Provisioning was required but the request "
+                                        + "was denied by the server.");
+                                break;
+
+                            case PREPARE_DRM_STATUS_PREPARATION_ERROR:
+                            default:
+                                Log.e(TAG, "prepareDrm: Post-provisioning preparation failed.");
+                                break;
+                        }
+                    }
+                } catch (Exception e) {
+                    status = PREPARE_DRM_STATUS_PREPARATION_ERROR;
+                }
+
+                if (sendEvent) {
+                    final int prepareDrmStatus = status;
+                    sendDrmEvent(new DrmEventNotifier() {
+                        @Override
+                        public void notify(DrmEventCallback callback) {
+                            callback.onDrmPrepared(
+                                    MediaPlayer2.this, dsd, prepareDrmStatus);
+                        }
+                    });
+
+                    synchronized (mTaskLock) {
+                        mCurrentTask = null;
+                        processPendingTask_l();
+                    }
+                }
+            }
+        });
+    }
+
+    private void doPrepareDrm(@NonNull DataSourceDesc dsd, @NonNull UUID uuid)
+            throws UnsupportedSchemeException, ResourceBusyException,
+                   NotProvisionedException {
+        Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigHelper: " + mOnDrmConfigHelper);
+
+        synchronized (mDrmLock) {
+            // only allowing if tied to a protected source; might relax for releasing offline keys
+            if (mDrmInfo == null) {
+                final String msg = "prepareDrm(): Wrong usage: The player must be prepared and "
+                        + "DRM info be retrieved before this call.";
+                Log.e(TAG, msg);
+                throw new IllegalStateException(msg);
+            }
+
+            if (mActiveDrmScheme) {
+                final String msg = "prepareDrm(): Wrong usage: There is already "
+                        + "an active DRM scheme with " + mDrmUUID;
+                Log.e(TAG, msg);
+                throw new IllegalStateException(msg);
+            }
+
+            if (mPrepareDrmInProgress) {
+                final String msg = "prepareDrm(): Wrong usage: There is already "
+                        + "a pending prepareDrm call.";
+                Log.e(TAG, msg);
+                throw new IllegalStateException(msg);
+            }
+
+            if (mDrmProvisioningInProgress) {
+                final String msg = "prepareDrm(): Unexpectd: Provisioning is already in progress.";
+                Log.e(TAG, msg);
+                throw new IllegalStateException(msg);
+            }
+
+            // shouldn't need this; just for safeguard
+            cleanDrmObj();
+
+            mPrepareDrmInProgress = true;
+
+            try {
+                // only creating the DRM object to allow pre-openSession configuration
+                prepareDrm_createDrmStep(uuid);
+            } catch (Exception e) {
+                Log.w(TAG, "prepareDrm(): Exception ", e);
+                mPrepareDrmInProgress = false;
+                throw e;
+            }
+
+            mDrmConfigAllowed = true;
+        }  // synchronized
+
+        // call the callback outside the lock
+        if (mOnDrmConfigHelper != null)  {
+            mOnDrmConfigHelper.onDrmConfig(this, dsd);
+        }
+
+        synchronized (mDrmLock) {
+            mDrmConfigAllowed = false;
+            boolean earlyExit = false;
+
+            try {
+                prepareDrm_openSessionStep(uuid);
+
+                mDrmUUID = uuid;
+                mActiveDrmScheme = true;
+                mPrepareDrmInProgress = false;
+            } catch (IllegalStateException e) {
+                final String msg = "prepareDrm(): Wrong usage: The player must be "
+                        + "in the prepared state to call prepareDrm().";
+                Log.e(TAG, msg);
+                earlyExit = true;
+                mPrepareDrmInProgress = false;
+                throw new IllegalStateException(msg);
+            } catch (NotProvisionedException e) {
+                Log.w(TAG, "prepareDrm: NotProvisionedException", e);
+                throw e;
+            } catch (Exception e) {
+                Log.e(TAG, "prepareDrm: Exception " + e);
+                earlyExit = true;
+                mPrepareDrmInProgress = false;
+                throw e;
+            } finally {
+                if (earlyExit) {  // clean up object if didn't succeed
+                    cleanDrmObj();
+                }
+            }  // finally
+        }  // synchronized
+    }
 
     /**
-     * Releases the DRM session
+     * Releases the DRM session for the given data source
      * <p>
      * The player has to have an active DRM session and be in stopped, or prepared
      * state before this call is made.
-     * A {@code reset()} call will release the DRM session implicitly.
+     * A {@link #reset()} call will release the DRM session implicitly.
+     *
+     * @param dsd The DRM protected data source
      *
      * @throws NoDrmSchemeException if there is no active DRM session to release
      */
     // This is a synchronous call.
-    public abstract void releaseDrm()
-            throws NoDrmSchemeException;
+    public void releaseDrm(@NonNull DataSourceDesc dsd)
+            throws NoDrmSchemeException {
+        // TODO: this implementation only works when dsd is the only data source
+        synchronized (mDrmLock) {
+            Log.v(TAG, "releaseDrm:");
+
+            if (!mActiveDrmScheme) {
+                Log.e(TAG, "releaseDrm(): No active DRM scheme to release.");
+                throw new NoDrmSchemeException(
+                        "releaseDrm: No active DRM scheme to release.");
+            }
+
+            try {
+                // we don't have the player's state in this layer. The below call raises
+                // exception if we're in a non-stopped/prepared state.
+
+                // for cleaning native/mediaserver crypto object
+                native_releaseDrm();
+
+                // for cleaning client-side MediaDrm object; only called if above has succeeded
+                cleanDrmObj();
+
+                mActiveDrmScheme = false;
+            } catch (IllegalStateException e) {
+                Log.w(TAG, "releaseDrm: Exception ", e);
+                throw new IllegalStateException(
+                        "releaseDrm: The player is not in a valid state.");
+            } catch (Exception e) {
+                Log.e(TAG, "releaseDrm: Exception ", e);
+            }
+        }  // synchronized
+    }
+
+    private native void native_releaseDrm();
 
     /**
      * A key request/response exchange occurs between the app and a license server
-     * to obtain or release keys used to decrypt encrypted content.
+     * to obtain or release keys used to decrypt the given data source.
      * <p>
-     * getDrmKeyRequest() is used to obtain an opaque key request byte array that is
+     * {@code getDrmKeyRequest()} is used to obtain an opaque key request byte array that is
      * delivered to the license server.  The opaque key request byte array is returned
      * in KeyRequest.data.  The recommended URL to deliver the key request to is
-     * returned in KeyRequest.defaultUrl.
+     * returned in {@code KeyRequest.defaultUrl}.
      * <p>
      * After the app has received the key request response from the server,
      * it should deliver to the response to the DRM engine plugin using the method
-     * {@link #provideDrmKeyResponse}.
+     * {@link #provideDrmKeyResponse(DataSourceDesc, byte[], byte[])}.
+     *
+     * @param dsd the DRM protected data source
      *
      * @param keySetId is the key-set identifier of the offline keys being released when keyType is
      * {@link MediaDrm#KEY_TYPE_RELEASE}. It should be set to null for other key requests, when
@@ -2053,24 +3626,67 @@
      * @throws NoDrmSchemeException if there is no active DRM session
      */
     @NonNull
-    public abstract MediaDrm.KeyRequest getDrmKeyRequest(
+    public MediaDrm.KeyRequest getDrmKeyRequest(
+            @NonNull DataSourceDesc dsd,
             @Nullable byte[] keySetId, @Nullable byte[] initData,
             @Nullable String mimeType, @MediaDrm.KeyType int keyType,
             @Nullable Map<String, String> optionalParameters)
-            throws NoDrmSchemeException;
+            throws NoDrmSchemeException {
+        // TODO: this implementation only works when dsd is the only data source
+        Log.v(TAG, "getDrmKeyRequest: "
+                + " keySetId: " + keySetId + " initData:" + initData + " mimeType: " + mimeType
+                + " keyType: " + keyType + " optionalParameters: " + optionalParameters);
+
+        synchronized (mDrmLock) {
+            if (!mActiveDrmScheme) {
+                Log.e(TAG, "getDrmKeyRequest NoDrmSchemeException");
+                throw new NoDrmSchemeException(
+                        "getDrmKeyRequest: Has to set a DRM scheme first.");
+            }
+
+            try {
+                byte[] scope = (keyType != MediaDrm.KEY_TYPE_RELEASE)
+                        ? mDrmSessionId :  // sessionId for KEY_TYPE_STREAMING/OFFLINE
+                        keySetId;  // keySetId for KEY_TYPE_RELEASE
+
+                HashMap<String, String> hmapOptionalParameters =
+                                                (optionalParameters != null)
+                                                ? new HashMap<String, String>(optionalParameters) :
+                                                null;
+
+                MediaDrm.KeyRequest request = mDrmObj.getKeyRequest(scope, initData, mimeType,
+                                                              keyType, hmapOptionalParameters);
+                Log.v(TAG, "getDrmKeyRequest:   --> request: " + request);
+
+                return request;
+
+            } catch (NotProvisionedException e) {
+                Log.w(TAG, "getDrmKeyRequest NotProvisionedException: "
+                        + "Unexpected. Shouldn't have reached here.");
+                throw new IllegalStateException("getDrmKeyRequest: Unexpected provisioning error.");
+            } catch (Exception e) {
+                Log.w(TAG, "getDrmKeyRequest Exception " + e);
+                throw e;
+            }
+
+        }  // synchronized
+    }
 
     /**
-     * A key response is received from the license server by the app, then it is
-     * provided to the DRM engine plugin using provideDrmKeyResponse. When the
-     * response is for an offline key request, a key-set identifier is returned that
+     * A key response is received from the license server by the app for the given DRM protected
+     * data source, then provided to the DRM engine plugin using {@code provideDrmKeyResponse}.
+     * <p>
+     * When the response is for an offline key request, a key-set identifier is returned that
      * can be used to later restore the keys to a new session with the method
-     * {@link # restoreDrmKeys}.
+     * {@link #restoreDrmKeys(DataSourceDesc, byte[])}.
      * When the response is for a streaming or release request, null is returned.
      *
-     * @param keySetId When the response is for a release request, keySetId identifies
-     * the saved key associated with the release request (i.e., the same keySetId
-     * passed to the earlier {@ link # getDrmKeyRequest} call. It MUST be null when the
-     * response is for either streaming or offline key requests.
+     * @param dsd the DRM protected data source
+     *
+     * @param keySetId When the response is for a release request, keySetId identifies the saved
+     * key associated with the release request (i.e., the same keySetId passed to the earlier
+     * {@link # getDrmKeyRequest(DataSourceDesc, byte[], byte[], String, int, Map)} call).
+     * It MUST be null when the response is for either streaming or offline key requests.
      *
      * @param response the byte array response from the server
      *
@@ -2079,76 +3695,827 @@
      * server rejected the request
      */
     // This is a synchronous call.
-    public abstract byte[] provideDrmKeyResponse(
+    public byte[] provideDrmKeyResponse(
+            @NonNull DataSourceDesc dsd,
             @Nullable byte[] keySetId, @NonNull byte[] response)
-            throws NoDrmSchemeException, DeniedByServerException;
+            throws NoDrmSchemeException, DeniedByServerException {
+        // TODO: this implementation only works when dsd is the only data source
+        Log.v(TAG, "provideDrmKeyResponse: keySetId: " + keySetId + " response: " + response);
+
+        synchronized (mDrmLock) {
+
+            if (!mActiveDrmScheme) {
+                Log.e(TAG, "getDrmKeyRequest NoDrmSchemeException");
+                throw new NoDrmSchemeException(
+                        "getDrmKeyRequest: Has to set a DRM scheme first.");
+            }
+
+            try {
+                byte[] scope = (keySetId == null)
+                                ? mDrmSessionId :     // sessionId for KEY_TYPE_STREAMING/OFFLINE
+                                keySetId;           // keySetId for KEY_TYPE_RELEASE
+
+                byte[] keySetResult = mDrmObj.provideKeyResponse(scope, response);
+
+                Log.v(TAG, "provideDrmKeyResponse: keySetId: " + keySetId + " response: " + response
+                        + " --> " + keySetResult);
+
+
+                return keySetResult;
+
+            } catch (NotProvisionedException e) {
+                Log.w(TAG, "provideDrmKeyResponse NotProvisionedException: "
+                        + "Unexpected. Shouldn't have reached here.");
+                throw new IllegalStateException("provideDrmKeyResponse: "
+                        + "Unexpected provisioning error.");
+            } catch (Exception e) {
+                Log.w(TAG, "provideDrmKeyResponse Exception " + e);
+                throw e;
+            }
+        }  // synchronized
+    }
 
     /**
-     * Restore persisted offline keys into a new session.  keySetId identifies the
-     * keys to load, obtained from a prior call to {@link #provideDrmKeyResponse}.
+     * Restore persisted offline keys into a new session for the given DRM protected data source.
+     * {@code keySetId} identifies the keys to load, obtained from a prior call to
+     * {@link #provideDrmKeyResponse(DataSourceDesc, byte[], byte[])}.
+     *
+     * @param dsd the DRM protected data source
      *
      * @param keySetId identifies the saved key set to restore
      *
      * @throws NoDrmSchemeException if there is no active DRM session
      */
     // This is a synchronous call.
-    public abstract void restoreDrmKeys(@NonNull byte[] keySetId)
-            throws NoDrmSchemeException;
+    public void restoreDrmKeys(
+            @NonNull DataSourceDesc dsd,
+            @NonNull byte[] keySetId)
+            throws NoDrmSchemeException {
+        // TODO: this implementation only works when dsd is the only data source
+        Log.v(TAG, "restoreDrmKeys: keySetId: " + keySetId);
+
+        synchronized (mDrmLock) {
+            if (!mActiveDrmScheme) {
+                Log.w(TAG, "restoreDrmKeys NoDrmSchemeException");
+                throw new NoDrmSchemeException(
+                        "restoreDrmKeys: Has to set a DRM scheme first.");
+            }
+
+            try {
+                mDrmObj.restoreKeys(mDrmSessionId, keySetId);
+            } catch (Exception e) {
+                Log.w(TAG, "restoreKeys Exception " + e);
+                throw e;
+            }
+        }  // synchronized
+    }
 
     /**
-     * Read a DRM engine plugin String property value, given the property name string.
-     * <p>
+     * Read a DRM engine plugin String property value, given the DRM protected data source
+     * and property name string.
+     *
+     * @param dsd the DRM protected data source
+     *
      * @param propertyName the property name
      *
      * Standard fields names are:
      * {@link MediaDrm#PROPERTY_VENDOR}, {@link MediaDrm#PROPERTY_VERSION},
      * {@link MediaDrm#PROPERTY_DESCRIPTION}, {@link MediaDrm#PROPERTY_ALGORITHMS}
+     *
+     * @throws NoDrmSchemeException if there is no active DRM session
      */
     @NonNull
-    public abstract String getDrmPropertyString(
+    public String getDrmPropertyString(
+            @NonNull DataSourceDesc dsd,
             @NonNull @MediaDrm.StringProperty String propertyName)
-            throws NoDrmSchemeException;
+            throws NoDrmSchemeException {
+        // TODO: this implementation only works when dsd is the only data source
+        Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName);
+
+        String value;
+        synchronized (mDrmLock) {
+
+            if (!mActiveDrmScheme && !mDrmConfigAllowed) {
+                Log.w(TAG, "getDrmPropertyString NoDrmSchemeException");
+                throw new NoDrmSchemeException(
+                        "getDrmPropertyString: Has to prepareDrm() first.");
+            }
+
+            try {
+                value = mDrmObj.getPropertyString(propertyName);
+            } catch (Exception e) {
+                Log.w(TAG, "getDrmPropertyString Exception " + e);
+                throw e;
+            }
+        }  // synchronized
+
+        Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName + " --> value: " + value);
+
+        return value;
+    }
 
     /**
-     * Set a DRM engine plugin String property value.
-     * <p>
+     * Set a DRM engine plugin String property value for the given data source.
+     *
+     * @param dsd the DRM protected data source
      * @param propertyName the property name
      * @param value the property value
      *
      * Standard fields names are:
      * {@link MediaDrm#PROPERTY_VENDOR}, {@link MediaDrm#PROPERTY_VERSION},
      * {@link MediaDrm#PROPERTY_DESCRIPTION}, {@link MediaDrm#PROPERTY_ALGORITHMS}
+     *
+     * @throws NoDrmSchemeException if there is no active DRM session
      */
     // This is a synchronous call.
-    public abstract void setDrmPropertyString(
+    public void setDrmPropertyString(
+            @NonNull DataSourceDesc dsd,
             @NonNull @MediaDrm.StringProperty String propertyName, @NonNull String value)
-            throws NoDrmSchemeException;
+            throws NoDrmSchemeException {
+        // TODO: this implementation only works when dsd is the only data source
+        Log.v(TAG, "setDrmPropertyString: propertyName: " + propertyName + " value: " + value);
+
+        synchronized (mDrmLock) {
+
+            if (!mActiveDrmScheme && !mDrmConfigAllowed) {
+                Log.w(TAG, "setDrmPropertyString NoDrmSchemeException");
+                throw new NoDrmSchemeException(
+                        "setDrmPropertyString: Has to prepareDrm() first.");
+            }
+
+            try {
+                mDrmObj.setPropertyString(propertyName, value);
+            } catch (Exception e) {
+                Log.w(TAG, "setDrmPropertyString Exception " + e);
+                throw e;
+            }
+        }  // synchronized
+    }
 
     /**
      * Encapsulates the DRM properties of the source.
      */
-    public abstract static class DrmInfo {
+    public static final class DrmInfo {
+        private Map<UUID, byte[]> mMapPssh;
+        private UUID[] mSupportedSchemes;
+
         /**
          * Returns the PSSH info of the data source for each supported DRM scheme.
          */
-        public abstract Map<UUID, byte[]> getPssh();
+        public Map<UUID, byte[]> getPssh() {
+            return mMapPssh;
+        }
 
         /**
          * Returns the intersection of the data source and the device DRM schemes.
          * It effectively identifies the subset of the source's DRM schemes which
          * are supported by the device too.
          */
-        public abstract List<UUID> getSupportedSchemes();
+        public List<UUID> getSupportedSchemes() {
+            return Arrays.asList(mSupportedSchemes);
+        }
+
+        private DrmInfo(Map<UUID, byte[]> pssh, UUID[] supportedSchemes) {
+            mMapPssh = pssh;
+            mSupportedSchemes = supportedSchemes;
+        }
+
+        private DrmInfo(PlayerMessage msg) {
+            Log.v(TAG, "DrmInfo(" + msg + ")");
+
+            Iterator<Value> in = msg.getValuesList().iterator();
+            byte[] pssh = in.next().getBytesValue().toByteArray();
+
+            Log.v(TAG, "DrmInfo() PSSH: " + arrToHex(pssh));
+            mMapPssh = parsePSSH(pssh, pssh.length);
+            Log.v(TAG, "DrmInfo() PSSH: " + mMapPssh);
+
+            int supportedDRMsCount = in.next().getInt32Value();
+            mSupportedSchemes = new UUID[supportedDRMsCount];
+            for (int i = 0; i < supportedDRMsCount; i++) {
+                byte[] uuid = new byte[16];
+                in.next().getBytesValue().copyTo(uuid, 0);
+
+                mSupportedSchemes[i] = bytesToUUID(uuid);
+
+                Log.v(TAG, "DrmInfo() supportedScheme[" + i + "]: " + mSupportedSchemes[i]);
+            }
+
+            Log.v(TAG, "DrmInfo() psshsize: " + pssh.length
+                    + " supportedDRMsCount: " + supportedDRMsCount);
+        }
+
+        private DrmInfo makeCopy() {
+            return new DrmInfo(this.mMapPssh, this.mSupportedSchemes);
+        }
+
+        private String arrToHex(byte[] bytes) {
+            String out = "0x";
+            for (int i = 0; i < bytes.length; i++) {
+                out += String.format("%02x", bytes[i]);
+            }
+
+            return out;
+        }
+
+        private UUID bytesToUUID(byte[] uuid) {
+            long msb = 0, lsb = 0;
+            for (int i = 0; i < 8; i++) {
+                msb |= (((long) uuid[i]     & 0xff) << (8 * (7 - i)));
+                lsb |= (((long) uuid[i + 8] & 0xff) << (8 * (7 - i)));
+            }
+
+            return new UUID(msb, lsb);
+        }
+
+        private Map<UUID, byte[]> parsePSSH(byte[] pssh, int psshsize) {
+            Map<UUID, byte[]> result = new HashMap<UUID, byte[]>();
+
+            final int uuidSize = 16;
+            final int dataLenSize = 4;
+
+            int len = psshsize;
+            int numentries = 0;
+            int i = 0;
+
+            while (len > 0) {
+                if (len < uuidSize) {
+                    Log.w(TAG, String.format("parsePSSH: len is too short to parse "
+                                             + "UUID: (%d < 16) pssh: %d", len, psshsize));
+                    return null;
+                }
+
+                byte[] subset = Arrays.copyOfRange(pssh, i, i + uuidSize);
+                UUID uuid = bytesToUUID(subset);
+                i += uuidSize;
+                len -= uuidSize;
+
+                // get data length
+                if (len < 4) {
+                    Log.w(TAG, String.format("parsePSSH: len is too short to parse "
+                                             + "datalen: (%d < 4) pssh: %d", len, psshsize));
+                    return null;
+                }
+
+                subset = Arrays.copyOfRange(pssh, i, i + dataLenSize);
+                int datalen = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN)
+                        ? ((subset[3] & 0xff) << 24) | ((subset[2] & 0xff) << 16)
+                        | ((subset[1] & 0xff) <<  8) |  (subset[0] & 0xff)        :
+                        ((subset[0] & 0xff) << 24) | ((subset[1] & 0xff) << 16)
+                        | ((subset[2] & 0xff) <<  8) |  (subset[3] & 0xff);
+                i += dataLenSize;
+                len -= dataLenSize;
+
+                if (len < datalen) {
+                    Log.w(TAG, String.format("parsePSSH: len is too short to parse "
+                                             + "data: (%d < %d) pssh: %d", len, datalen, psshsize));
+                    return null;
+                }
+
+                byte[] data = Arrays.copyOfRange(pssh, i, i + datalen);
+
+                // skip the data
+                i += datalen;
+                len -= datalen;
+
+                Log.v(TAG, String.format("parsePSSH[%d]: <%s, %s> pssh: %d",
+                                         numentries, uuid, arrToHex(data), psshsize));
+                numentries++;
+                result.put(uuid, data);
+            }
+
+            return result;
+        }
     };  // DrmInfo
 
     /**
-     * Thrown when a DRM method is called before preparing a DRM scheme through prepareDrm().
+     * Thrown when a DRM method is called before preparing a DRM scheme through
+     * {@link MediaPlayer2#prepareDrm(DataSourceDesc, UUID)}.
      * Extends MediaDrm.MediaDrmException
      */
-    public abstract static class NoDrmSchemeException extends MediaDrmException {
-          protected NoDrmSchemeException(String detailMessage) {
-              super(detailMessage);
-          }
+    public static final class NoDrmSchemeException extends MediaDrmException {
+        public NoDrmSchemeException(String detailMessage) {
+            super(detailMessage);
+        }
+    }
+
+    private native void native_prepareDrm(@NonNull byte[] uuid, @NonNull byte[] drmSessionId);
+
+    // Modular DRM helpers
+
+    private void prepareDrm_createDrmStep(@NonNull UUID uuid)
+            throws UnsupportedSchemeException {
+        Log.v(TAG, "prepareDrm_createDrmStep: UUID: " + uuid);
+
+        try {
+            mDrmObj = new MediaDrm(uuid);
+            Log.v(TAG, "prepareDrm_createDrmStep: Created mDrmObj=" + mDrmObj);
+        } catch (Exception e) { // UnsupportedSchemeException
+            Log.e(TAG, "prepareDrm_createDrmStep: MediaDrm failed with " + e);
+            throw e;
+        }
+    }
+
+    private void prepareDrm_openSessionStep(@NonNull UUID uuid)
+            throws NotProvisionedException, ResourceBusyException {
+        Log.v(TAG, "prepareDrm_openSessionStep: uuid: " + uuid);
+
+        // TODO: don't need an open session for a future specialKeyReleaseDrm mode but we should do
+        // it anyway so it raises provisioning error if needed. We'd rather handle provisioning
+        // at prepareDrm/openSession rather than getDrmKeyRequest/provideDrmKeyResponse
+        try {
+            mDrmSessionId = mDrmObj.openSession();
+            Log.v(TAG, "prepareDrm_openSessionStep: mDrmSessionId=" + mDrmSessionId);
+
+            // Sending it down to native/mediaserver to create the crypto object
+            // This call could simply fail due to bad player state, e.g., after play().
+            native_prepareDrm(getByteArrayFromUUID(uuid), mDrmSessionId);
+            Log.v(TAG, "prepareDrm_openSessionStep: native_prepareDrm/Crypto succeeded");
+
+        } catch (Exception e) { //ResourceBusyException, NotProvisionedException
+            Log.e(TAG, "prepareDrm_openSessionStep: open/crypto failed with " + e);
+            throw e;
+        }
+    }
+
+    // Instantiated from the native side
+    @SuppressWarnings("unused")
+    private static class StreamEventCallback extends AudioTrack.StreamEventCallback {
+        public long mJAudioTrackPtr;
+        public long mNativeCallbackPtr;
+        public long mUserDataPtr;
+
+        StreamEventCallback(long jAudioTrackPtr, long nativeCallbackPtr, long userDataPtr) {
+            super();
+            mJAudioTrackPtr = jAudioTrackPtr;
+            mNativeCallbackPtr = nativeCallbackPtr;
+            mUserDataPtr = userDataPtr;
+        }
+
+        @Override
+        public void onTearDown(AudioTrack track) {
+            native_stream_event_onTearDown(mNativeCallbackPtr, mUserDataPtr);
+        }
+
+        @Override
+        public void onPresentationEnded(AudioTrack track) {
+            native_stream_event_onStreamPresentationEnd(mNativeCallbackPtr, mUserDataPtr);
+        }
+
+        @Override
+        public void onDataRequest(AudioTrack track, int size) {
+            native_stream_event_onStreamDataRequest(
+                    mJAudioTrackPtr, mNativeCallbackPtr, mUserDataPtr);
+        }
+    }
+
+    private class ProvisioningThread extends Thread {
+        public static final int TIMEOUT_MS = 60000;
+
+        private final DataSourceDesc mDSD;
+        private UUID mUuid;
+        private String mUrlStr;
+        private Object mDrmLock;
+        private MediaPlayer2 mMediaPlayer;
+        private int mStatus;
+        public  int status() {
+            return mStatus;
+        }
+
+        public ProvisioningThread(MediaDrm.ProvisionRequest request,
+                DataSourceDesc dsd,
+                UUID uuid, MediaPlayer2 mediaPlayer) {
+            // lock is held by the caller
+            mDSD = dsd;
+            mDrmLock = mediaPlayer.mDrmLock;
+            mMediaPlayer = mediaPlayer;
+
+            mUrlStr = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData());
+            mUuid = uuid;
+
+            mStatus = PREPARE_DRM_STATUS_PREPARATION_ERROR;
+
+            Log.v(TAG, "handleProvisioninig: Thread is initialised url: " + mUrlStr);
+        }
+
+        public void run() {
+
+            byte[] response = null;
+            boolean provisioningSucceeded = false;
+            try {
+                URL url = new URL(mUrlStr);
+                final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+                try {
+                    connection.setRequestMethod("POST");
+                    connection.setDoOutput(false);
+                    connection.setDoInput(true);
+                    connection.setConnectTimeout(TIMEOUT_MS);
+                    connection.setReadTimeout(TIMEOUT_MS);
+
+                    connection.connect();
+                    response = readInputStreamFully(connection.getInputStream());
+
+                    Log.v(TAG, "handleProvisioninig: Thread run: response "
+                            + response.length + " " + response);
+                } catch (Exception e) {
+                    mStatus = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
+                    Log.w(TAG, "handleProvisioninig: Thread run: connect " + e + " url: " + url);
+                } finally {
+                    connection.disconnect();
+                }
+            } catch (Exception e)   {
+                mStatus = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
+                Log.w(TAG, "handleProvisioninig: Thread run: openConnection " + e);
+            }
+
+            if (response != null) {
+                try {
+                    mDrmObj.provideProvisionResponse(response);
+                    Log.v(TAG, "handleProvisioninig: Thread run: "
+                            + "provideProvisionResponse SUCCEEDED!");
+
+                    provisioningSucceeded = true;
+                } catch (Exception e) {
+                    mStatus = PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR;
+                    Log.w(TAG, "handleProvisioninig: Thread run: "
+                            + "provideProvisionResponse " + e);
+                }
+            }
+
+            boolean succeeded = false;
+
+            synchronized (mDrmLock) {
+                // continuing with prepareDrm
+                if (provisioningSucceeded) {
+                    succeeded = mMediaPlayer.resumePrepareDrm(mUuid);
+                    mStatus = (succeeded)
+                            ? PREPARE_DRM_STATUS_SUCCESS :
+                            PREPARE_DRM_STATUS_PREPARATION_ERROR;
+                }
+                mMediaPlayer.mDrmProvisioningInProgress = false;
+                mMediaPlayer.mPrepareDrmInProgress = false;
+                if (!succeeded) {
+                    cleanDrmObj();  // cleaning up if it hasn't gone through while in the lock
+                }
+            }  // synchronized
+
+            // calling the callback outside the lock
+            sendDrmEvent(new DrmEventNotifier() {
+                @Override
+                public void notify(DrmEventCallback callback) {
+                    callback.onDrmPrepared(
+                            mMediaPlayer, mDSD, mStatus);
+                }
+            });
+
+            synchronized (mTaskLock) {
+                if (mCurrentTask != null
+                        && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE_DRM
+                        && mCurrentTask.mNeedToWaitForEventToComplete) {
+                    mCurrentTask = null;
+                    processPendingTask_l();
+                }
+            }
+        }
+
+        /**
+         * Returns a byte[] containing the remainder of 'in', closing it when done.
+         */
+        private byte[] readInputStreamFully(InputStream in) throws IOException {
+            try {
+                return readInputStreamFullyNoClose(in);
+            } finally {
+                in.close();
+            }
+        }
+
+        /**
+         * Returns a byte[] containing the remainder of 'in'.
+         */
+        private byte[] readInputStreamFullyNoClose(InputStream in) throws IOException {
+            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int count;
+            while ((count = in.read(buffer)) != -1) {
+                bytes.write(buffer, 0, count);
+            }
+            return bytes.toByteArray();
+        }
+    }  // ProvisioningThread
+
+    private int handleProvisioninig(DataSourceDesc dsd, UUID uuid) {
+        synchronized (mDrmLock) {
+            if (mDrmProvisioningInProgress) {
+                Log.e(TAG, "handleProvisioninig: Unexpected mDrmProvisioningInProgress");
+                return PREPARE_DRM_STATUS_PREPARATION_ERROR;
+            }
+
+            MediaDrm.ProvisionRequest provReq = mDrmObj.getProvisionRequest();
+            if (provReq == null) {
+                Log.e(TAG, "handleProvisioninig: getProvisionRequest returned null.");
+                return PREPARE_DRM_STATUS_PREPARATION_ERROR;
+            }
+
+            Log.v(TAG, "handleProvisioninig provReq "
+                    + " data: " + provReq.getData() + " url: " + provReq.getDefaultUrl());
+
+            // networking in a background thread
+            mDrmProvisioningInProgress = true;
+
+            mDrmProvisioningThread = new ProvisioningThread(provReq, dsd, uuid, this);
+            mDrmProvisioningThread.start();
+
+            return PREPARE_DRM_STATUS_SUCCESS;
+        }
+    }
+
+    private boolean resumePrepareDrm(UUID uuid) {
+        Log.v(TAG, "resumePrepareDrm: uuid: " + uuid);
+
+        // mDrmLock is guaranteed to be held
+        boolean success = false;
+        try {
+            // resuming
+            prepareDrm_openSessionStep(uuid);
+
+            mDrmUUID = uuid;
+            mActiveDrmScheme = true;
+
+            success = true;
+        } catch (Exception e) {
+            Log.w(TAG, "handleProvisioninig: Thread run native_prepareDrm resume failed with " + e);
+            // mDrmObj clean up is done by the caller
+        }
+
+        return success;
+    }
+
+    private void resetDrmState() {
+        synchronized (mDrmLock) {
+            Log.v(TAG, "resetDrmState:"
+                    + " mDrmInfo=" + mDrmInfo
+                    + " mDrmProvisioningThread=" + mDrmProvisioningThread
+                    + " mPrepareDrmInProgress=" + mPrepareDrmInProgress
+                    + " mActiveDrmScheme=" + mActiveDrmScheme);
+
+            mDrmInfoResolved = false;
+            mDrmInfo = null;
+
+            if (mDrmProvisioningThread != null) {
+                // timeout; relying on HttpUrlConnection
+                try {
+                    mDrmProvisioningThread.join();
+                } catch (InterruptedException e) {
+                    Log.w(TAG, "resetDrmState: ProvThread.join Exception " + e);
+                }
+                mDrmProvisioningThread = null;
+            }
+
+            mPrepareDrmInProgress = false;
+            mActiveDrmScheme = false;
+
+            cleanDrmObj();
+        }  // synchronized
+    }
+
+    private void cleanDrmObj() {
+        // the caller holds mDrmLock
+        Log.v(TAG, "cleanDrmObj: mDrmObj=" + mDrmObj + " mDrmSessionId=" + mDrmSessionId);
+
+        if (mDrmSessionId != null)    {
+            mDrmObj.closeSession(mDrmSessionId);
+            mDrmSessionId = null;
+        }
+        if (mDrmObj != null) {
+            mDrmObj.release();
+            mDrmObj = null;
+        }
+    }
+
+    private static byte[] getByteArrayFromUUID(@NonNull UUID uuid) {
+        long msb = uuid.getMostSignificantBits();
+        long lsb = uuid.getLeastSignificantBits();
+
+        byte[] uuidBytes = new byte[16];
+        for (int i = 0; i < 8; ++i) {
+            uuidBytes[i] = (byte) (msb >>> (8 * (7 - i)));
+            uuidBytes[8 + i] = (byte) (lsb >>> (8 * (7 - i)));
+        }
+
+        return uuidBytes;
+    }
+
+    // Modular DRM end
+
+    private static class TimedTextUtil {
+        // These keys must be in sync with the keys in TextDescription2.h
+        private static final int KEY_START_TIME                     = 7; // int
+        private static final int KEY_STRUCT_TEXT_POS               = 14; // TextPos
+        private static final int KEY_STRUCT_TEXT                   = 16; // Text
+        private static final int KEY_GLOBAL_SETTING               = 101;
+        private static final int KEY_LOCAL_SETTING                = 102;
+
+        private static TimedText parsePlayerMessage(PlayerMessage playerMsg) {
+            if (playerMsg.getValuesCount() == 0) {
+                return null;
+            }
+
+            String textChars = null;
+            Rect textBounds = null;
+            Iterator<Value> in = playerMsg.getValuesList().iterator();
+            int type = in.next().getInt32Value();
+            if (type == KEY_LOCAL_SETTING) {
+                type = in.next().getInt32Value();
+                if (type != KEY_START_TIME) {
+                    return null;
+                }
+                int startTimeMs = in.next().getInt32Value();
+
+                type = in.next().getInt32Value();
+                if (type != KEY_STRUCT_TEXT) {
+                    return null;
+                }
+
+                byte[] text = in.next().getBytesValue().toByteArray();
+                if (text == null || text.length == 0) {
+                    textChars = null;
+                } else {
+                    textChars = new String(text);
+                }
+
+            } else if (type != KEY_GLOBAL_SETTING) {
+                Log.w(TAG, "Invalid timed text key found: " + type);
+                return null;
+            }
+            if (in.hasNext()) {
+                type = in.next().getInt32Value();
+                if (type == KEY_STRUCT_TEXT_POS) {
+                    int top = in.next().getInt32Value();
+                    int left = in.next().getInt32Value();
+                    int bottom = in.next().getInt32Value();
+                    int right = in.next().getInt32Value();
+                    textBounds = new Rect(left, top, right, bottom);
+                }
+            }
+            return new TimedText(textChars, textBounds);
+        }
+    }
+
+    private Object addTask(Task task) {
+        synchronized (mTaskLock) {
+            mPendingTasks.add(task);
+            processPendingTask_l();
+        }
+        return task;
+    }
+
+    @GuardedBy("mTaskLock")
+    private void processPendingTask_l() {
+        if (mCurrentTask != null) {
+            return;
+        }
+        if (!mPendingTasks.isEmpty()) {
+            Task task = mPendingTasks.remove(0);
+            mCurrentTask = task;
+            mTaskHandler.post(task);
+        }
+    }
+
+    private abstract class Task implements Runnable {
+        private final int mMediaCallType;
+        private final boolean mNeedToWaitForEventToComplete;
+        private DataSourceDesc mDSD;
+
+        Task(int mediaCallType, boolean needToWaitForEventToComplete) {
+            mMediaCallType = mediaCallType;
+            mNeedToWaitForEventToComplete = needToWaitForEventToComplete;
+        }
+
+        abstract void process() throws IOException, NoDrmSchemeException;
+
+        @Override
+        public void run() {
+            int status = CALL_STATUS_NO_ERROR;
+            try {
+                if (mMediaCallType != CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED
+                        && getState() == PLAYER_STATE_ERROR) {
+                    status = CALL_STATUS_INVALID_OPERATION;
+                } else {
+                    if (mMediaCallType == CALL_COMPLETED_SEEK_TO) {
+                        synchronized (mTaskLock) {
+                            if (!mPendingTasks.isEmpty()) {
+                                Task nextTask = mPendingTasks.get(0);
+                                if (nextTask.mMediaCallType == mMediaCallType) {
+                                    throw new CommandSkippedException(
+                                            "consecutive seekTo is skipped except last one");
+                                }
+                            }
+                        }
+                    }
+                    process();
+                }
+            } catch (IllegalStateException e) {
+                status = CALL_STATUS_INVALID_OPERATION;
+            } catch (IllegalArgumentException e) {
+                status = CALL_STATUS_BAD_VALUE;
+            } catch (SecurityException e) {
+                status = CALL_STATUS_PERMISSION_DENIED;
+            } catch (IOException e) {
+                status = CALL_STATUS_ERROR_IO;
+            } catch (NoDrmSchemeException e) {
+                status = CALL_STATUS_NO_DRM_SCHEME;
+            } catch (CommandSkippedException e) {
+                status = CALL_STATUS_SKIPPED;
+            } catch (Exception e) {
+                status = CALL_STATUS_ERROR_UNKNOWN;
+            }
+            mDSD = getCurrentDataSource();
+
+            if (mMediaCallType != CALL_COMPLETED_SEEK_TO) {
+                synchronized (mTaskLock) {
+                    mIsPreviousCommandSeekTo = false;
+                }
+            }
+
+            // TODO: Make native implementations asynchronous and let them send notifications.
+            if (!mNeedToWaitForEventToComplete || status != CALL_STATUS_NO_ERROR) {
+
+                sendCompleteNotification(status);
+
+                synchronized (mTaskLock) {
+                    mCurrentTask = null;
+                    processPendingTask_l();
+                }
+            }
+        }
+
+        private void sendCompleteNotification(int status) {
+            // In {@link #notifyWhenCommandLabelReached} case, a separate callback
+            // {@link #onCommandLabelReached} is already called in {@code process()}.
+            // CALL_COMPLETED_PREPARE_DRM is sent via DrmEventCallback#onDrmPrepared
+            if (mMediaCallType == CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED
+                    || mMediaCallType == CALL_COMPLETED_PREPARE_DRM) {
+                return;
+            }
+            sendEvent(new EventNotifier() {
+                @Override
+                public void notify(EventCallback callback) {
+                    callback.onCallCompleted(
+                            MediaPlayer2.this, mDSD, mMediaCallType, status);
+                }
+            });
+        }
+    };
+
+    private final class CommandSkippedException extends RuntimeException {
+        CommandSkippedException(String detailMessage) {
+            super(detailMessage);
+        }
+    };
+
+    private final class SourceInfo {
+        final DataSourceDesc mDSD;
+        final long mId = mSrcIdGenerator.getAndIncrement();
+        AtomicInteger mBufferedPercentage = new AtomicInteger(0);
+
+        // m*AsNextSource (below) only applies to pending data sources in the playlist;
+        // the meanings of mCurrentSourceInfo.{mStateAsNextSource,mPlayPendingAsNextSource}
+        // are undefined.
+        int mStateAsNextSource = NEXT_SOURCE_STATE_INIT;
+        boolean mPlayPendingAsNextSource = false;
+
+        SourceInfo(DataSourceDesc dsd) {
+            this.mDSD = dsd;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%s(%d)", SourceInfo.class.getName(), mId);
+        }
+
+    }
+
+    private SourceInfo getSourceInfoById(long srcId) {
+        synchronized (mSrcLock) {
+            if (isCurrentSource(srcId)) {
+                return mCurrentSourceInfo;
+            }
+            if (isNextSource(srcId)) {
+                return mNextSourceInfos.peek();
+            }
+        }
+        return null;
+    }
+
+    private boolean isCurrentSource(long srcId) {
+        synchronized (mSrcLock) {
+            return mCurrentSourceInfo != null && mCurrentSourceInfo.mId == srcId;
+        }
+    }
+
+    private boolean isNextSource(long srcId) {
+        SourceInfo nextSourceInfo = mNextSourceInfos.peek();
+        return nextSourceInfo != null && nextSourceInfo.mId == srcId;
     }
 
     public static final class MetricsConstants {
@@ -2243,4 +4610,19 @@
         public static final String ERROR_CODE = "android.media.mediaplayer.errcode";
 
     }
+
+    private void keepAudioSessionIdAlive(int sessionId) {
+        synchronized (mSessionIdLock) {
+            if (mDummyAudioTrack != null) {
+                if (mDummyAudioTrack.getAudioSessionId() == sessionId) {
+                    return;
+                }
+                mDummyAudioTrack.release();
+            }
+            // TODO: parameters can be optimized
+            mDummyAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 44100,
+                    AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, 2,
+                    AudioTrack.MODE_STATIC, sessionId);
+        }
+    }
 }
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
deleted file mode 100644
index ef8db1d..0000000
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ /dev/null
@@ -1,3540 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.CallbackExecutor;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ContentProvider;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.AssetFileDescriptor;
-import android.graphics.SurfaceTexture;
-import android.graphics.Rect;
-import android.media.MediaPlayer2Proto.PlayerMessage;
-import android.media.MediaPlayer2Proto.Value;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PersistableBundle;
-import android.os.PowerManager;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.Pair;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-
-import com.android.framework.protobuf.InvalidProtocolBufferException;
-import com.android.internal.annotations.GuardedBy;
-
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.ref.WeakReference;
-import java.net.HttpCookie;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.nio.ByteOrder;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.Executor;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * @hide
- */
-public final class MediaPlayer2Impl extends MediaPlayer2 {
-    static {
-        System.loadLibrary("media2_jni");
-        native_init();
-    }
-
-    private final static String TAG = "MediaPlayer2Impl";
-
-    private Context mContext;
-
-    private long mNativeContext; // accessed by native methods
-    private long mNativeSurfaceTexture;  // accessed by native methods
-    private int mListenerContext; // accessed by native methods
-    private SurfaceHolder mSurfaceHolder;
-    private PowerManager.WakeLock mWakeLock = null;
-    private boolean mScreenOnWhilePlaying;
-    private boolean mStayAwake;
-    private int mStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
-
-    private final Object mSrcLock = new Object();
-    //--- guarded by |mSrcLock| start
-    private long mSrcIdGenerator = 0;
-    private DataSourceDesc mCurrentDSD;
-    private long mCurrentSrcId = mSrcIdGenerator++;
-    private List<DataSourceDesc> mNextDSDs;
-    private long mNextSrcId = mSrcIdGenerator++;
-    private int mNextSourceState = NEXT_SOURCE_STATE_INIT;
-    private boolean mNextSourcePlayPending = false;
-    //--- guarded by |mSrcLock| end
-
-    private AtomicInteger mBufferedPercentageCurrent = new AtomicInteger(0);
-    private AtomicInteger mBufferedPercentageNext = new AtomicInteger(0);
-    private volatile float mVolume = 1.0f;
-
-    // Modular DRM
-    private final Object mDrmLock = new Object();
-    //--- guarded by |mDrmLock| start
-    private UUID mDrmUUID;
-    private DrmInfoImpl mDrmInfoImpl;
-    private MediaDrm mDrmObj;
-    private byte[] mDrmSessionId;
-    private boolean mDrmInfoResolved;
-    private boolean mActiveDrmScheme;
-    private boolean mDrmConfigAllowed;
-    private boolean mDrmProvisioningInProgress;
-    private boolean mPrepareDrmInProgress;
-    private ProvisioningThread mDrmProvisioningThread;
-    //--- guarded by |mDrmLock| end
-
-    private HandlerThread mHandlerThread;
-    private final TaskHandler mTaskHandler;
-    private final Object mTaskLock = new Object();
-    @GuardedBy("mTaskLock")
-    private final List<Task> mPendingTasks = new LinkedList<>();
-    @GuardedBy("mTaskLock")
-    private Task mCurrentTask;
-
-    @GuardedBy("this")
-    private boolean mReleased;
-
-    /**
-     * Default constructor.
-     * <p>When done with the MediaPlayer2Impl, you should call  {@link #close()},
-     * to free the resources. If not released, too many MediaPlayer2Impl instances may
-     * result in an exception.</p>
-     */
-    public MediaPlayer2Impl(Context context) {
-        mContext = context;
-        mHandlerThread = new HandlerThread("MediaPlayer2TaskThread");
-        mHandlerThread.start();
-        Looper looper = mHandlerThread.getLooper();
-        mTaskHandler = new TaskHandler(this, looper);
-
-        /* Native setup requires a weak reference to our object.
-         * It's easier to create it here than in C++.
-         */
-        native_setup(new WeakReference<MediaPlayer2Impl>(this));
-    }
-
-    @Override
-    public MediaPlayerBase getMediaPlayerBase() {
-        return null;
-    }
-
-    /**
-     * Releases the resources held by this {@code MediaPlayer2} object.
-     *
-     * It is considered good practice to call this method when you're
-     * done using the MediaPlayer2. In particular, whenever an Activity
-     * of an application is paused (its onPause() method is called),
-     * or stopped (its onStop() method is called), this method should be
-     * invoked to release the MediaPlayer2 object, unless the application
-     * has a special need to keep the object around. In addition to
-     * unnecessary resources (such as memory and instances of codecs)
-     * being held, failure to call this method immediately if a
-     * MediaPlayer2 object is no longer needed may also lead to
-     * continuous battery consumption for mobile devices, and playback
-     * failure for other applications if no multiple instances of the
-     * same codec are supported on a device. Even if multiple instances
-     * of the same codec are supported, some performance degradation
-     * may be expected when unnecessary multiple instances are used
-     * at the same time.
-     *
-     * {@code close()} may be safely called after a prior {@code close()}.
-     * This class implements the Java {@code AutoCloseable} interface and
-     * may be used with try-with-resources.
-     */
-    @Override
-    public void close() {
-        super.close();
-        release();
-    }
-
-    /**
-     * Starts or resumes playback. If playback had previously been paused,
-     * playback will continue from where it was paused. If playback had
-     * been stopped, or never started before, playback will start at the
-     * beginning.
-     */
-    @Override
-    public Object play() {
-        return addTask(new Task(CALL_COMPLETED_PLAY, false) {
-            @Override
-            void process() {
-                stayAwake(true);
-                _start();
-            }
-        });
-    }
-
-    private native void _start() throws IllegalStateException;
-
-    /**
-     * Prepares the player for playback, asynchronously.
-     *
-     * After setting the datasource and the display surface, you need to either
-     * call prepare(). For streams, you should call prepare(),
-     * which returns immediately, rather than blocking until enough data has been
-     * buffered.
-     */
-    @Override
-    public Object prepare() {
-        return addTask(new Task(CALL_COMPLETED_PREPARE, true) {
-            @Override
-            void process() {
-                _prepare();
-            }
-        });
-    }
-
-    public native void _prepare();
-
-    /**
-     * Pauses playback. Call play() to resume.
-     */
-    @Override
-    public Object pause() {
-        return addTask(new Task(CALL_COMPLETED_PAUSE, false) {
-            @Override
-            void process() {
-                stayAwake(false);
-
-                _pause();
-            }
-        });
-    }
-
-    private native void _pause() throws IllegalStateException;
-
-    /**
-     * Tries to play next data source if applicable.
-     *
-     * @throws IllegalStateException if it is called in an invalid state
-     */
-    @Override
-    public Object skipToNext() {
-        return addTask(new Task(CALL_COMPLETED_SKIP_TO_NEXT, false) {
-            @Override
-            void process() {
-                if (getState() == PLAYER_STATE_PLAYING) {
-                    pause();
-                }
-                playNextDataSource();
-            }
-        });
-    }
-
-    /**
-     * Gets the current playback position.
-     *
-     * @return the current position in milliseconds
-     */
-    @Override
-    public native long getCurrentPosition();
-
-    /**
-     * Gets the duration of the file.
-     *
-     * @return the duration in milliseconds, if no duration is available
-     *         (for example, if streaming live content), -1 is returned.
-     */
-    @Override
-    public native long getDuration();
-
-    /**
-     * Gets the current buffered media source position received through progressive downloading.
-     * The received buffering percentage indicates how much of the content has been buffered
-     * or played. For example a buffering update of 80 percent when half the content
-     * has already been played indicates that the next 30 percent of the
-     * content to play has been buffered.
-     *
-     * @return the current buffered media source position in milliseconds
-     */
-    @Override
-    public long getBufferedPosition() {
-        // Use cached buffered percent for now.
-        return getDuration() * mBufferedPercentageCurrent.get() / 100;
-    }
-
-    @Override
-    public @MediaPlayer2State int getState() {
-        return native_getState();
-    }
-
-    private native int native_getState();
-
-    /**
-     * Sets the audio attributes for this MediaPlayer2.
-     * See {@link AudioAttributes} for how to build and configure an instance of this class.
-     * You must call this method before {@link #prepare()} in order
-     * for the audio attributes to become effective thereafter.
-     * @param attributes a non-null set of audio attributes
-     * @throws IllegalArgumentException if the attributes are null or invalid.
-     */
-    @Override
-    public Object setAudioAttributes(@NonNull AudioAttributes attributes) {
-        return addTask(new Task(CALL_COMPLETED_SET_AUDIO_ATTRIBUTES, false) {
-            @Override
-            void process() {
-                if (attributes == null) {
-                    final String msg = "Cannot set AudioAttributes to null";
-                    throw new IllegalArgumentException(msg);
-                }
-                setParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES, attributes);
-            }
-        });
-    }
-
-    @Override
-    public @NonNull AudioAttributes getAudioAttributes() {
-        AudioAttributes attributes = (AudioAttributes) getParameter(KEY_PARAMETER_AUDIO_ATTRIBUTES);
-        return attributes;
-    }
-
-    /**
-     * Sets the data source as described by a DataSourceDesc.
-     *
-     * @param dsd the descriptor of data source you want to play
-     */
-    @Override
-    public Object setDataSource(@NonNull DataSourceDesc dsd) {
-        return addTask(new Task(CALL_COMPLETED_SET_DATA_SOURCE, false) {
-            @Override
-            void process() throws IOException {
-                checkArgument(dsd != null, "the DataSourceDesc cannot be null");
-                int state = getState();
-                if (state != PLAYER_STATE_ERROR && state != PLAYER_STATE_IDLE) {
-                    throw new IllegalStateException("called in wrong state " + state);
-                }
-
-                synchronized (mSrcLock) {
-                    mCurrentDSD = dsd;
-                    mCurrentSrcId = mSrcIdGenerator++;
-                    handleDataSource(true /* isCurrent */, dsd, mCurrentSrcId);
-                }
-            }
-        });
-    }
-
-    /**
-     * Sets a single data source as described by a DataSourceDesc which will be played
-     * after current data source is finished.
-     *
-     * @param dsd the descriptor of data source you want to play after current one
-     */
-    @Override
-    public Object setNextDataSource(@NonNull DataSourceDesc dsd) {
-        return addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCE, false) {
-            @Override
-            void process() {
-                checkArgument(dsd != null, "the DataSourceDesc cannot be null");
-                synchronized (mSrcLock) {
-                    mNextDSDs = new ArrayList<DataSourceDesc>(1);
-                    mNextDSDs.add(dsd);
-                    mNextSrcId = mSrcIdGenerator++;
-                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
-                }
-                prepareNextDataSource();
-            }
-        });
-    }
-
-    /**
-     * Sets a list of data sources to be played sequentially after current data source is done.
-     *
-     * @param dsds the list of data sources you want to play after current one
-     */
-    @Override
-    public Object setNextDataSources(@NonNull List<DataSourceDesc> dsds) {
-        return addTask(new Task(CALL_COMPLETED_SET_NEXT_DATA_SOURCES, false) {
-            @Override
-            void process() {
-                if (dsds == null || dsds.size() == 0) {
-                    throw new IllegalArgumentException("data source list cannot be null or empty.");
-                }
-                for (DataSourceDesc dsd : dsds) {
-                    if (dsd == null) {
-                        throw new IllegalArgumentException(
-                                "DataSourceDesc in the source list cannot be null.");
-                    }
-                }
-
-                synchronized (mSrcLock) {
-                    mNextDSDs = new ArrayList(dsds);
-                    mNextSrcId = mSrcIdGenerator++;
-                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
-                }
-                prepareNextDataSource();
-            }
-        });
-    }
-
-    @Override
-    public Object clearNextDataSources() {
-        return addTask(new Task(CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES, false) {
-            @Override
-            void process() {
-                synchronized (mSrcLock) {
-                    if (mNextDSDs != null) {
-                        mNextDSDs.clear();
-                        mNextDSDs = null;
-                    }
-                    mNextSrcId = mSrcIdGenerator++;
-                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
-                }
-            }
-        });
-    }
-
-    @Override
-    public @NonNull DataSourceDesc getCurrentDataSource() {
-        synchronized (mSrcLock) {
-            return mCurrentDSD;
-        }
-    }
-
-    /**
-     * Configures the player to loop on the current data source.
-     * @param loop true if the current data source is meant to loop.
-     */
-    @Override
-    public Object loopCurrent(boolean loop) {
-        return addTask(new Task(CALL_COMPLETED_LOOP_CURRENT, false) {
-            @Override
-            void process() {
-                // TODO: set the looping mode, send notification
-                setLooping(loop);
-            }
-        });
-    }
-
-    private native void setLooping(boolean looping);
-
-    /**
-     * Sets the volume of the audio of the media to play, expressed as a linear multiplier
-     * on the audio samples.
-     * Note that this volume is specific to the player, and is separate from stream volume
-     * used across the platform.<br>
-     * A value of 0.0f indicates muting, a value of 1.0f is the nominal unattenuated and unamplified
-     * gain. See {@link #getMaxPlayerVolume()} for the volume range supported by this player.
-     * @param volume a value between 0.0f and {@link #getMaxPlayerVolume()}.
-     */
-    @Override
-    public Object setPlayerVolume(float volume) {
-        return addTask(new Task(CALL_COMPLETED_SET_PLAYER_VOLUME, false) {
-            @Override
-            void process() {
-                mVolume = volume;
-                _setVolume(volume);
-            }
-        });
-    }
-
-    private native void _setVolume(float volume);
-
-    /**
-     * Returns the current volume of this player to this player.
-     * Note that it does not take into account the associated stream volume.
-     * @return the player volume.
-     */
-    @Override
-    public float getPlayerVolume() {
-        return mVolume;
-    }
-
-    /**
-     * @return the maximum volume that can be used in {@link #setPlayerVolume(float)}.
-     */
-    @Override
-    public float getMaxPlayerVolume() {
-        return 1.0f;
-    }
-
-    private static final int NEXT_SOURCE_STATE_ERROR = -1;
-    private static final int NEXT_SOURCE_STATE_INIT = 0;
-    private static final int NEXT_SOURCE_STATE_PREPARING = 1;
-    private static final int NEXT_SOURCE_STATE_PREPARED = 2;
-
-    /*
-     * Update the MediaPlayer2Impl SurfaceTexture.
-     * Call after setting a new display surface.
-     */
-    private native void _setVideoSurface(Surface surface);
-
-    /* Do not change these values (starting with INVOKE_ID) without updating
-     * their counterparts in include/media/mediaplayer2.h!
-     */
-    private static final int INVOKE_ID_GET_TRACK_INFO = 1;
-    private static final int INVOKE_ID_ADD_EXTERNAL_SOURCE = 2;
-    private static final int INVOKE_ID_ADD_EXTERNAL_SOURCE_FD = 3;
-    private static final int INVOKE_ID_SELECT_TRACK = 4;
-    private static final int INVOKE_ID_DESELECT_TRACK = 5;
-    private static final int INVOKE_ID_SET_VIDEO_SCALE_MODE = 6;
-    private static final int INVOKE_ID_GET_SELECTED_TRACK = 7;
-
-    /**
-     * Invoke a generic method on the native player using opaque protocol
-     * buffer message for the request and reply. Both payloads' format is a
-     * convention between the java caller and the native player.
-     *
-     * @param msg PlayerMessage for the extension.
-     *
-     * @return PlayerMessage with the data returned by the
-     * native player.
-     */
-    private PlayerMessage invoke(PlayerMessage msg) {
-        byte[] ret = _invoke(msg.toByteArray());
-        if (ret == null) {
-            return null;
-        }
-        try {
-            return PlayerMessage.parseFrom(ret);
-        } catch (InvalidProtocolBufferException e) {
-            return null;
-        }
-    }
-
-    private native byte[] _invoke(byte[] request);
-
-    @Override
-    public Object notifyWhenCommandLabelReached(Object label) {
-        return addTask(new Task(CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED, false) {
-            @Override
-            void process() {
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onCommandLabelReached(
-                                MediaPlayer2Impl.this, label);
-                    }
-                });
-            }
-        });
-    }
-
-    @Override
-    public Object setDisplay(SurfaceHolder sh) {
-        return addTask(new Task(CALL_COMPLETED_SET_DISPLAY, false) {
-            @Override
-            void process() {
-                mSurfaceHolder = sh;
-                Surface surface;
-                if (sh != null) {
-                    surface = sh.getSurface();
-                } else {
-                    surface = null;
-                }
-                _setVideoSurface(surface);
-                updateSurfaceScreenOn();
-            }
-        });
-    }
-
-    @Override
-    public Object setSurface(Surface surface) {
-        return addTask(new Task(CALL_COMPLETED_SET_SURFACE, false) {
-            @Override
-            void process() {
-                if (mScreenOnWhilePlaying && surface != null) {
-                    Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective for Surface");
-                }
-                mSurfaceHolder = null;
-                _setVideoSurface(surface);
-                updateSurfaceScreenOn();
-            }
-        });
-    }
-
-    /**
-     * Sets video scaling mode. To make the target video scaling mode
-     * effective during playback, this method must be called after
-     * data source is set. If not called, the default video
-     * scaling mode is {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT}.
-     *
-     * <p> The supported video scaling modes are:
-     * <ul>
-     * <li> {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT}
-     * <li> {@link #VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING}
-     * </ul>
-     *
-     * @param mode target video scaling mode. Must be one of the supported
-     * video scaling modes; otherwise, IllegalArgumentException will be thrown.
-     *
-     * @see MediaPlayer2#VIDEO_SCALING_MODE_SCALE_TO_FIT
-     * @see MediaPlayer2#VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
-     * @hide
-     */
-    @Override
-    public Object setVideoScalingMode(int mode) {
-        return addTask(new Task(CALL_COMPLETED_SET_VIDEO_SCALING_MODE, false) {
-            @Override
-            void process() {
-                if (!isVideoScalingModeSupported(mode)) {
-                    final String msg = "Scaling mode " + mode + " is not supported";
-                    throw new IllegalArgumentException(msg);
-                }
-                PlayerMessage request = PlayerMessage.newBuilder()
-                        .addValues(Value.newBuilder()
-                                .setInt32Value(INVOKE_ID_SET_VIDEO_SCALE_MODE))
-                        .addValues(Value.newBuilder().setInt32Value(mode))
-                        .build();
-                invoke(request);
-            }
-        });
-    }
-
-    @Override
-    public boolean cancelCommand(Object token) {
-        synchronized (mTaskLock) {
-            return mPendingTasks.remove(token);
-        }
-    }
-
-    @Override
-    public void clearPendingCommands() {
-        synchronized (mTaskLock) {
-            mPendingTasks.clear();
-        }
-    }
-
-    private Object addTask(Task task) {
-        synchronized (mTaskLock) {
-            mPendingTasks.add(task);
-            processPendingTask_l();
-        }
-        return task;
-    }
-
-    @GuardedBy("mTaskLock")
-    private void processPendingTask_l() {
-        if (mCurrentTask != null) {
-            return;
-        }
-        if (!mPendingTasks.isEmpty()) {
-            Task task = mPendingTasks.remove(0);
-            mCurrentTask = task;
-            mTaskHandler.post(task);
-        }
-    }
-
-    private void handleDataSource(boolean isCurrent, @NonNull DataSourceDesc dsd, long srcId)
-            throws IOException {
-        checkArgument(dsd != null, "the DataSourceDesc cannot be null");
-
-        switch (dsd.getType()) {
-            case DataSourceDesc.TYPE_CALLBACK:
-                handleDataSource(isCurrent,
-                                 srcId,
-                                 dsd.getMedia2DataSource(),
-                                 dsd.getStartPosition(),
-                                 dsd.getEndPosition());
-                break;
-
-            case DataSourceDesc.TYPE_FD:
-                handleDataSource(isCurrent,
-                                 srcId,
-                                 dsd.getFileDescriptor(),
-                                 dsd.getFileDescriptorOffset(),
-                                 dsd.getFileDescriptorLength(),
-                                 dsd.getStartPosition(),
-                                 dsd.getEndPosition());
-                break;
-
-            case DataSourceDesc.TYPE_URI:
-                handleDataSource(isCurrent,
-                                 srcId,
-                                 dsd.getUriContext(),
-                                 dsd.getUri(),
-                                 dsd.getUriHeaders(),
-                                 dsd.getUriCookies(),
-                                 dsd.getStartPosition(),
-                                 dsd.getEndPosition());
-                break;
-
-            default:
-                break;
-        }
-    }
-
-    /**
-     * To provide cookies for the subsequent HTTP requests, you can install your own default cookie
-     * handler and use other variants of setDataSource APIs instead. Alternatively, you can use
-     * this API to pass the cookies as a list of HttpCookie. If the app has not installed
-     * a CookieHandler already, this API creates a CookieManager and populates its CookieStore with
-     * the provided cookies. If the app has installed its own handler already, this API requires the
-     * handler to be of CookieManager type such that the API can update the manager’s CookieStore.
-     *
-     * <p><strong>Note</strong> that the cross domain redirection is allowed by default,
-     * but that can be changed with key/value pairs through the headers parameter with
-     * "android-allow-cross-domain-redirect" as the key and "0" or "1" as the value to
-     * disallow or allow cross domain redirection.
-     *
-     * @throws IllegalArgumentException if cookies are provided and the installed handler is not
-     *                                  a CookieManager
-     * @throws IllegalStateException    if it is called in an invalid state
-     * @throws NullPointerException     if context or uri is null
-     * @throws IOException              if uri has a file scheme and an I/O error occurs
-     */
-    private void handleDataSource(
-            boolean isCurrent, long srcId,
-            @NonNull Context context, @NonNull Uri uri,
-            @Nullable Map<String, String> headers, @Nullable List<HttpCookie> cookies,
-            long startPos, long endPos)
-            throws IOException {
-        // The context and URI usually belong to the calling user. Get a resolver for that user.
-        final ContentResolver resolver = context.getContentResolver();
-        final String scheme = uri.getScheme();
-        if (ContentResolver.SCHEME_FILE.equals(scheme)) {
-            handleDataSource(isCurrent, srcId, uri.getPath(), null, null, startPos, endPos);
-            return;
-        }
-
-        final int ringToneType = RingtoneManager.getDefaultType(uri);
-        try {
-            AssetFileDescriptor afd;
-            // Try requested Uri locally first
-            if (ContentResolver.SCHEME_CONTENT.equals(scheme) && ringToneType != -1) {
-                afd = RingtoneManager.openDefaultRingtoneUri(context, uri);
-                if (attemptDataSource(isCurrent, srcId, afd, startPos, endPos)) {
-                    return;
-                }
-                final Uri actualUri = RingtoneManager.getActualDefaultRingtoneUri(
-                        context, ringToneType);
-                afd = resolver.openAssetFileDescriptor(actualUri, "r");
-            } else {
-                afd = resolver.openAssetFileDescriptor(uri, "r");
-            }
-            if (attemptDataSource(isCurrent, srcId, afd, startPos, endPos)) {
-                return;
-            }
-        } catch (NullPointerException | SecurityException | IOException ex) {
-            Log.w(TAG, "Couldn't open " + uri + ": " + ex);
-            // Fallback to media server
-        }
-        handleDataSource(isCurrent, srcId, uri.toString(), headers, cookies, startPos, endPos);
-    }
-
-    private boolean attemptDataSource(boolean isCurrent, long srcId, AssetFileDescriptor afd,
-            long startPos, long endPos) throws IOException {
-        try {
-            if (afd.getDeclaredLength() < 0) {
-                handleDataSource(isCurrent,
-                        srcId,
-                        afd.getFileDescriptor(),
-                        0,
-                        DataSourceDesc.LONG_MAX,
-                        startPos,
-                        endPos);
-            } else {
-                handleDataSource(isCurrent,
-                        srcId,
-                        afd.getFileDescriptor(),
-                        afd.getStartOffset(),
-                        afd.getDeclaredLength(),
-                        startPos,
-                        endPos);
-            }
-            return true;
-        } catch (NullPointerException | SecurityException | IOException ex) {
-            Log.w(TAG, "Couldn't open srcId:" + srcId + ": " + ex);
-            return false;
-        } finally {
-            if (afd != null) {
-                afd.close();
-            }
-        }
-    }
-
-    private void handleDataSource(
-            boolean isCurrent, long srcId,
-            String path, Map<String, String> headers, List<HttpCookie> cookies,
-            long startPos, long endPos)
-            throws IOException {
-        String[] keys = null;
-        String[] values = null;
-
-        if (headers != null) {
-            keys = new String[headers.size()];
-            values = new String[headers.size()];
-
-            int i = 0;
-            for (Map.Entry<String, String> entry: headers.entrySet()) {
-                keys[i] = entry.getKey();
-                values[i] = entry.getValue();
-                ++i;
-            }
-        }
-        handleDataSource(isCurrent, srcId, path, keys, values, cookies, startPos, endPos);
-    }
-
-    private void handleDataSource(boolean isCurrent, long srcId,
-            String path, String[] keys, String[] values, List<HttpCookie> cookies,
-            long startPos, long endPos)
-            throws IOException {
-        final Uri uri = Uri.parse(path);
-        final String scheme = uri.getScheme();
-        if ("file".equals(scheme)) {
-            path = uri.getPath();
-        } else if (scheme != null) {
-            // handle non-file sources
-            Media2Utils.storeCookies(cookies);
-            nativeHandleDataSourceUrl(
-                isCurrent,
-                srcId,
-                Media2HTTPService.createHTTPService(path),
-                path,
-                keys,
-                values,
-                startPos,
-                endPos);
-            return;
-        }
-
-        final File file = new File(path);
-        if (file.exists()) {
-            FileInputStream is = new FileInputStream(file);
-            FileDescriptor fd = is.getFD();
-            handleDataSource(isCurrent, srcId, fd, 0, DataSourceDesc.LONG_MAX, startPos, endPos);
-            is.close();
-        } else {
-            throw new IOException("handleDataSource failed.");
-        }
-    }
-
-    private native void nativeHandleDataSourceUrl(
-            boolean isCurrent, long srcId,
-            Media2HTTPService httpService, String path, String[] keys, String[] values,
-            long startPos, long endPos)
-            throws IOException;
-
-    /**
-     * Sets the data source (FileDescriptor) to use. The FileDescriptor must be
-     * seekable (N.B. a LocalSocket is not seekable). It is the caller's responsibility
-     * to close the file descriptor. It is safe to do so as soon as this call returns.
-     *
-     * @throws IllegalStateException if it is called in an invalid state
-     * @throws IllegalArgumentException if fd is not a valid FileDescriptor
-     * @throws IOException if fd can not be read
-     */
-    private void handleDataSource(
-            boolean isCurrent, long srcId,
-            FileDescriptor fd, long offset, long length,
-            long startPos, long endPos) throws IOException {
-        nativeHandleDataSourceFD(isCurrent, srcId, fd, offset, length, startPos, endPos);
-    }
-
-    private native void nativeHandleDataSourceFD(boolean isCurrent, long srcId,
-            FileDescriptor fd, long offset, long length,
-            long startPos, long endPos) throws IOException;
-
-    /**
-     * @throws IllegalStateException if it is called in an invalid state
-     * @throws IllegalArgumentException if dataSource is not a valid Media2DataSource
-     */
-    private void handleDataSource(boolean isCurrent, long srcId, Media2DataSource dataSource,
-            long startPos, long endPos) {
-        nativeHandleDataSourceCallback(isCurrent, srcId, dataSource, startPos, endPos);
-    }
-
-    private native void nativeHandleDataSourceCallback(
-            boolean isCurrent, long srcId, Media2DataSource dataSource,
-            long startPos, long endPos);
-
-    /**
-     * @return true if there is a next data source, false otherwise.
-     */
-    // This function should be always called on |mHandlerThread|.
-    private boolean prepareNextDataSource() {
-        if (Looper.myLooper() != mHandlerThread.getLooper()) {
-            Log.e(TAG, "prepareNextDataSource: called on wrong looper");
-        }
-
-        boolean hasNextDSD;
-        synchronized (mSrcLock) {
-            hasNextDSD = (mNextDSDs != null && !mNextDSDs.isEmpty());
-        }
-
-        int state = getState();
-        if (state == PLAYER_STATE_ERROR || state == PLAYER_STATE_IDLE) {
-            // Current source has not been prepared yet.
-            return hasNextDSD;
-        }
-
-        synchronized (mSrcLock) {
-            if (!hasNextDSD || mNextSourceState != NEXT_SOURCE_STATE_INIT) {
-                // There is no next source or it's in preparing or prepared state.
-                return hasNextDSD;
-            }
-
-            try {
-                mNextSourceState = NEXT_SOURCE_STATE_PREPARING;
-                handleDataSource(false /* isCurrent */, mNextDSDs.get(0), mNextSrcId);
-            } catch (Exception e) {
-                Message msg = mTaskHandler.obtainMessage(
-                        MEDIA_ERROR, MEDIA_ERROR_IO, MEDIA_ERROR_UNKNOWN, null);
-                mTaskHandler.handleMessage(msg, mNextSrcId);
-
-                mNextDSDs.remove(0);
-                // make a new SrcId to obsolete notification for previous one.
-                mNextSrcId = mSrcIdGenerator++;
-                mNextSourceState = NEXT_SOURCE_STATE_INIT;
-                return prepareNextDataSource();
-            }
-        }
-        return hasNextDSD;
-    }
-
-    // This function should be always called on |mHandlerThread|.
-    private void playNextDataSource() {
-        if (Looper.myLooper() != mHandlerThread.getLooper()) {
-            Log.e(TAG, "playNextDataSource: called on wrong looper");
-        }
-
-        boolean hasNextDSD = false;
-        synchronized (mSrcLock) {
-            if (mNextDSDs != null && !mNextDSDs.isEmpty()) {
-                hasNextDSD = true;
-                if (mNextSourceState == NEXT_SOURCE_STATE_PREPARED) {
-                    // Switch to next source only when it has been prepared.
-                    mCurrentDSD = mNextDSDs.get(0);
-                    mCurrentSrcId = mNextSrcId;
-                    mBufferedPercentageCurrent.set(mBufferedPercentageNext.get());
-                    mNextDSDs.remove(0);
-                    mNextSrcId = mSrcIdGenerator++;  // make it different from |mCurrentSrcId|
-                    mBufferedPercentageNext.set(0);
-                    mNextSourceState = NEXT_SOURCE_STATE_INIT;
-
-                    long srcId = mCurrentSrcId;
-                    try {
-                        nativePlayNextDataSource(srcId);
-                    } catch (Exception e) {
-                        Message msg2 = mTaskHandler.obtainMessage(
-                                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
-                        mTaskHandler.handleMessage(msg2, srcId);
-                        // Keep |mNextSourcePlayPending|
-                        hasNextDSD = prepareNextDataSource();
-                    }
-                    if (hasNextDSD) {
-                        stayAwake(true);
-
-                        // Now a new current src is playing.
-                        // Wait for MEDIA_INFO_DATA_SOURCE_START to prepare next source.
-                        mNextSourcePlayPending = false;
-                    }
-                } else if (mNextSourceState == NEXT_SOURCE_STATE_INIT) {
-                    hasNextDSD = prepareNextDataSource();
-                }
-            }
-        }
-
-        if (!hasNextDSD) {
-            sendEvent(new EventNotifier() {
-                @Override
-                public void notify(EventCallback callback) {
-                    callback.onInfo(
-                            MediaPlayer2Impl.this, null, MEDIA_INFO_DATA_SOURCE_LIST_END, 0);
-                }
-            });
-        }
-    }
-
-    private native void nativePlayNextDataSource(long srcId);
-
-
-    private int getAudioStreamType() {
-        if (mStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
-            mStreamType = _getAudioStreamType();
-        }
-        return mStreamType;
-    }
-
-    private native int _getAudioStreamType() throws IllegalStateException;
-
-
-    //--------------------------------------------------------------------------
-    // Explicit Routing
-    //--------------------
-    private AudioDeviceInfo mPreferredDevice = null;
-
-    /**
-     * Specifies an audio device (via an {@link AudioDeviceInfo} object) to route
-     * the output from this MediaPlayer2.
-     * @param deviceInfo The {@link AudioDeviceInfo} specifying the audio sink or source.
-     *  If deviceInfo is null, default routing is restored.
-     * @return true if succesful, false if the specified {@link AudioDeviceInfo} is non-null and
-     * does not correspond to a valid audio device.
-     */
-    @Override
-    public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) {
-        if (deviceInfo != null && !deviceInfo.isSink()) {
-            return false;
-        }
-        int preferredDeviceId = deviceInfo != null ? deviceInfo.getId() : 0;
-        boolean status = native_setOutputDevice(preferredDeviceId);
-        if (status == true) {
-            synchronized (this) {
-                mPreferredDevice = deviceInfo;
-            }
-        }
-        return status;
-    }
-
-    /**
-     * Returns the selected output specified by {@link #setPreferredDevice}. Note that this
-     * is not guaranteed to correspond to the actual device being used for playback.
-     */
-    @Override
-    public AudioDeviceInfo getPreferredDevice() {
-        synchronized (this) {
-            return mPreferredDevice;
-        }
-    }
-
-    /**
-     * Returns an {@link AudioDeviceInfo} identifying the current routing of this MediaPlayer2
-     * Note: The query is only valid if the MediaPlayer2 is currently playing.
-     * If the player is not playing, the returned device can be null or correspond to previously
-     * selected device when the player was last active.
-     */
-    @Override
-    public AudioDeviceInfo getRoutedDevice() {
-        int deviceId = native_getRoutedDeviceId();
-        if (deviceId == 0) {
-            return null;
-        }
-        AudioDeviceInfo[] devices =
-                AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS);
-        for (int i = 0; i < devices.length; i++) {
-            if (devices[i].getId() == deviceId) {
-                return devices[i];
-            }
-        }
-        return null;
-    }
-
-    /*
-     * Call BEFORE adding a routing callback handler or AFTER removing a routing callback handler.
-     */
-    @GuardedBy("mRoutingChangeListeners")
-    private void enableNativeRoutingCallbacksLocked(boolean enabled) {
-        if (mRoutingChangeListeners.size() == 0) {
-            native_enableDeviceCallback(enabled);
-        }
-    }
-
-    /**
-     * The list of AudioRouting.OnRoutingChangedListener interfaces added (with
-     * {@link #addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, Handler)}
-     * by an app to receive (re)routing notifications.
-     */
-    @GuardedBy("mRoutingChangeListeners")
-    private ArrayMap<AudioRouting.OnRoutingChangedListener,
-            NativeRoutingEventHandlerDelegate> mRoutingChangeListeners = new ArrayMap<>();
-
-    /**
-     * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of routing
-     * changes on this MediaPlayer2.
-     * @param listener The {@link AudioRouting.OnRoutingChangedListener} interface to receive
-     * notifications of rerouting events.
-     * @param handler  Specifies the {@link Handler} object for the thread on which to execute
-     * the callback. If <code>null</code>, the handler on the main looper will be used.
-     */
-    @Override
-    public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener,
-            Handler handler) {
-        synchronized (mRoutingChangeListeners) {
-            if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
-                enableNativeRoutingCallbacksLocked(true);
-                mRoutingChangeListeners.put(
-                        listener, new NativeRoutingEventHandlerDelegate(this, listener,
-                                handler != null ? handler : mTaskHandler));
-            }
-        }
-    }
-
-    /**
-     * Removes an {@link AudioRouting.OnRoutingChangedListener} which has been previously added
-     * to receive rerouting notifications.
-     * @param listener The previously added {@link AudioRouting.OnRoutingChangedListener} interface
-     * to remove.
-     */
-    @Override
-    public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) {
-        synchronized (mRoutingChangeListeners) {
-            if (mRoutingChangeListeners.containsKey(listener)) {
-                mRoutingChangeListeners.remove(listener);
-                enableNativeRoutingCallbacksLocked(false);
-            }
-        }
-    }
-
-    private native final boolean native_setOutputDevice(int deviceId);
-    private native final int native_getRoutedDeviceId();
-    private native final void native_enableDeviceCallback(boolean enabled);
-
-    /**
-     * Set the low-level power management behavior for this MediaPlayer2.  This
-     * can be used when the MediaPlayer2 is not playing through a SurfaceHolder
-     * set with {@link #setDisplay(SurfaceHolder)} and thus can use the
-     * high-level {@link #setScreenOnWhilePlaying(boolean)} feature.
-     *
-     * <p>This function has the MediaPlayer2 access the low-level power manager
-     * service to control the device's power usage while playing is occurring.
-     * The parameter is a combination of {@link android.os.PowerManager} wake flags.
-     * Use of this method requires {@link android.Manifest.permission#WAKE_LOCK}
-     * permission.
-     * By default, no attempt is made to keep the device awake during playback.
-     *
-     * @param context the Context to use
-     * @param mode    the power/wake mode to set
-     * @see android.os.PowerManager
-     * @hide
-     */
-    @Override
-    public void setWakeMode(Context context, int mode) {
-        boolean washeld = false;
-
-        /* Disable persistant wakelocks in media player based on property */
-        if (SystemProperties.getBoolean("audio.offload.ignore_setawake", false) == true) {
-            Log.w(TAG, "IGNORING setWakeMode " + mode);
-            return;
-        }
-
-        if (mWakeLock != null) {
-            if (mWakeLock.isHeld()) {
-                washeld = true;
-                mWakeLock.release();
-            }
-            mWakeLock = null;
-        }
-
-        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(mode|PowerManager.ON_AFTER_RELEASE, MediaPlayer2Impl.class.getName());
-        mWakeLock.setReferenceCounted(false);
-        if (washeld) {
-            mWakeLock.acquire();
-        }
-    }
-
-    /**
-     * Control whether we should use the attached SurfaceHolder to keep the
-     * screen on while video playback is occurring.  This is the preferred
-     * method over {@link #setWakeMode} where possible, since it doesn't
-     * require that the application have permission for low-level wake lock
-     * access.
-     *
-     * @param screenOn Supply true to keep the screen on, false to allow it
-     * to turn off.
-     * @hide
-     */
-    @Override
-    public void setScreenOnWhilePlaying(boolean screenOn) {
-        if (mScreenOnWhilePlaying != screenOn) {
-            if (screenOn && mSurfaceHolder == null) {
-                Log.w(TAG, "setScreenOnWhilePlaying(true) is ineffective without a SurfaceHolder");
-            }
-            mScreenOnWhilePlaying = screenOn;
-            updateSurfaceScreenOn();
-        }
-    }
-
-    private void stayAwake(boolean awake) {
-        if (mWakeLock != null) {
-            if (awake && !mWakeLock.isHeld()) {
-                mWakeLock.acquire();
-            } else if (!awake && mWakeLock.isHeld()) {
-                mWakeLock.release();
-            }
-        }
-        mStayAwake = awake;
-        updateSurfaceScreenOn();
-    }
-
-    private void updateSurfaceScreenOn() {
-        if (mSurfaceHolder != null) {
-            mSurfaceHolder.setKeepScreenOn(mScreenOnWhilePlaying && mStayAwake);
-        }
-    }
-
-    /**
-     * Returns the width of the video.
-     *
-     * @return the width of the video, or 0 if there is no video,
-     * no display surface was set, or the width has not been determined
-     * yet. The {@code EventCallback} can be registered via
-     * {@link #setEventCallback(Executor, EventCallback)} to provide a
-     * notification {@code EventCallback.onVideoSizeChanged} when the width
-     * is available.
-     */
-    @Override
-    public native int getVideoWidth();
-
-    /**
-     * Returns the height of the video.
-     *
-     * @return the height of the video, or 0 if there is no video,
-     * no display surface was set, or the height has not been determined
-     * yet. The {@code EventCallback} can be registered via
-     * {@link #setEventCallback(Executor, EventCallback)} to provide a
-     * notification {@code EventCallback.onVideoSizeChanged} when the height
-     * is available.
-     */
-    @Override
-    public native int getVideoHeight();
-
-    /**
-     * Return Metrics data about the current player.
-     *
-     * @return a {@link PersistableBundle} containing the set of attributes and values
-     * available for the media being handled by this instance of MediaPlayer2
-     * The attributes are descibed in {@link MetricsConstants}.
-     *
-     *  Additional vendor-specific fields may also be present in
-     *  the return value.
-     */
-    @Override
-    public PersistableBundle getMetrics() {
-        PersistableBundle bundle = native_getMetrics();
-        return bundle;
-    }
-
-    private native PersistableBundle native_getMetrics();
-
-    /**
-     * Checks whether the MediaPlayer2 is playing.
-     *
-     * @return true if currently playing, false otherwise
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized or has been released.
-     * @hide
-     */
-    @Override
-    public native boolean isPlaying();
-
-    /**
-     * Gets the current buffering management params used by the source component.
-     * Calling it only after {@code setDataSource} has been called.
-     * Each type of data source might have different set of default params.
-     *
-     * @return the current buffering management params used by the source component.
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized, or {@code setDataSource} has not been called.
-     * @hide
-     */
-    @Override
-    @NonNull
-    public native BufferingParams getBufferingParams();
-
-    @Override
-    public Object setBufferingParams(@NonNull BufferingParams params) {
-        return addTask(new Task(CALL_COMPLETED_SET_BUFFERING_PARAMS, false) {
-            @Override
-            void process() {
-                checkArgument(params != null, "the BufferingParams cannot be null");
-                _setBufferingParams(params);
-            }
-        });
-    }
-
-    private native void _setBufferingParams(@NonNull BufferingParams params);
-
-    /**
-     * Sets playback rate and audio mode.
-     *
-     * @param rate the ratio between desired playback rate and normal one.
-     * @param audioMode audio playback mode. Must be one of the supported
-     * audio modes.
-     *
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized.
-     * @throws IllegalArgumentException if audioMode is not supported.
-     *
-     * @hide
-     */
-    @Override
-    @NonNull
-    public PlaybackParams easyPlaybackParams(float rate, @PlaybackRateAudioMode int audioMode) {
-        PlaybackParams params = new PlaybackParams();
-        params.allowDefaults();
-        switch (audioMode) {
-        case PLAYBACK_RATE_AUDIO_MODE_DEFAULT:
-            params.setSpeed(rate).setPitch(1.0f);
-            break;
-        case PLAYBACK_RATE_AUDIO_MODE_STRETCH:
-            params.setSpeed(rate).setPitch(1.0f)
-                    .setAudioFallbackMode(params.AUDIO_FALLBACK_MODE_FAIL);
-            break;
-        case PLAYBACK_RATE_AUDIO_MODE_RESAMPLE:
-            params.setSpeed(rate).setPitch(rate);
-            break;
-        default:
-            final String msg = "Audio playback mode " + audioMode + " is not supported";
-            throw new IllegalArgumentException(msg);
-        }
-        return params;
-    }
-
-    @Override
-    public Object setPlaybackParams(@NonNull PlaybackParams params) {
-        return addTask(new Task(CALL_COMPLETED_SET_PLAYBACK_PARAMS, false) {
-            @Override
-            void process() {
-                checkArgument(params != null, "the PlaybackParams cannot be null");
-                _setPlaybackParams(params);
-            }
-        });
-    }
-
-    private native void _setPlaybackParams(@NonNull PlaybackParams params);
-
-    /**
-     * Gets the playback params, containing the current playback rate.
-     *
-     * @return the playback params.
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized.
-     */
-    @Override
-    @NonNull
-    public native PlaybackParams getPlaybackParams();
-
-    /**
-     * Sets A/V sync mode.
-     *
-     * @param params the A/V sync params to apply
-     *
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized.
-     * @throws IllegalArgumentException if params are not supported.
-     */
-    @Override
-    public Object setSyncParams(@NonNull SyncParams params) {
-        return addTask(new Task(CALL_COMPLETED_SET_SYNC_PARAMS, false) {
-            @Override
-            void process() {
-                checkArgument(params != null, "the SyncParams cannot be null");
-                _setSyncParams(params);
-            }
-        });
-    }
-
-    private native void _setSyncParams(@NonNull SyncParams params);
-
-    /**
-     * Gets the A/V sync mode.
-     *
-     * @return the A/V sync params
-     *
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized.
-     */
-    @Override
-    @NonNull
-    public native SyncParams getSyncParams();
-
-    /**
-     * Moves the media to specified time position by considering the given mode.
-     * <p>
-     * When seekTo is finished, the user will be notified via OnSeekComplete supplied by the user.
-     * There is at most one active seekTo processed at any time. If there is a to-be-completed
-     * seekTo, new seekTo requests will be queued in such a way that only the last request
-     * is kept. When current seekTo is completed, the queued request will be processed if
-     * that request is different from just-finished seekTo operation, i.e., the requested
-     * position or mode is different.
-     *
-     * @param msec the offset in milliseconds from the start to seek to.
-     * When seeking to the given time position, there is no guarantee that the data source
-     * has a frame located at the position. When this happens, a frame nearby will be rendered.
-     * If msec is negative, time position zero will be used.
-     * If msec is larger than duration, duration will be used.
-     * @param mode the mode indicating where exactly to seek to.
-     * Use {@link #SEEK_PREVIOUS_SYNC} if one wants to seek to a sync frame
-     * that has a timestamp earlier than or the same as msec. Use
-     * {@link #SEEK_NEXT_SYNC} if one wants to seek to a sync frame
-     * that has a timestamp later than or the same as msec. Use
-     * {@link #SEEK_CLOSEST_SYNC} if one wants to seek to a sync frame
-     * that has a timestamp closest to or the same as msec. Use
-     * {@link #SEEK_CLOSEST} if one wants to seek to a frame that may
-     * or may not be a sync frame but is closest to or the same as msec.
-     * {@link #SEEK_CLOSEST} often has larger performance overhead compared
-     * to the other options if there is no sync frame located at msec.
-     * @throws IllegalStateException if the internal player engine has not been
-     * initialized
-     * @throws IllegalArgumentException if the mode is invalid.
-     */
-    @Override
-    public Object seekTo(final long msec, @SeekMode int mode) {
-        return addTask(new Task(CALL_COMPLETED_SEEK_TO, true) {
-            @Override
-            void process() {
-                if (mode < SEEK_PREVIOUS_SYNC || mode > SEEK_CLOSEST) {
-                    final String msg = "Illegal seek mode: " + mode;
-                    throw new IllegalArgumentException(msg);
-                }
-                // TODO: pass long to native, instead of truncating here.
-                long posMs = msec;
-                if (posMs > Integer.MAX_VALUE) {
-                    Log.w(TAG, "seekTo offset " + posMs + " is too large, cap to "
-                            + Integer.MAX_VALUE);
-                    posMs = Integer.MAX_VALUE;
-                } else if (posMs < Integer.MIN_VALUE) {
-                    Log.w(TAG, "seekTo offset " + posMs + " is too small, cap to "
-                            + Integer.MIN_VALUE);
-                    posMs = Integer.MIN_VALUE;
-                }
-                _seekTo(posMs, mode);
-            }
-        });
-    }
-
-    private native final void _seekTo(long msec, int mode);
-
-    /**
-     * Get current playback position as a {@link MediaTimestamp}.
-     * <p>
-     * The MediaTimestamp represents how the media time correlates to the system time in
-     * a linear fashion using an anchor and a clock rate. During regular playback, the media
-     * time moves fairly constantly (though the anchor frame may be rebased to a current
-     * system time, the linear correlation stays steady). Therefore, this method does not
-     * need to be called often.
-     * <p>
-     * To help users get current playback position, this method always anchors the timestamp
-     * to the current {@link System#nanoTime system time}, so
-     * {@link MediaTimestamp#getAnchorMediaTimeUs} can be used as current playback position.
-     *
-     * @return a MediaTimestamp object if a timestamp is available, or {@code null} if no timestamp
-     *         is available, e.g. because the media player has not been initialized.
-     *
-     * @see MediaTimestamp
-     */
-    @Override
-    @Nullable
-    public MediaTimestamp getTimestamp()
-    {
-        try {
-            // TODO: get the timestamp from native side
-            return new MediaTimestamp(
-                    getCurrentPosition() * 1000L,
-                    System.nanoTime(),
-                    isPlaying() ? getPlaybackParams().getSpeed() : 0.f);
-        } catch (IllegalStateException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Resets the MediaPlayer2 to its uninitialized state. After calling
-     * this method, you will have to initialize it again by setting the
-     * data source and calling prepare().
-     */
-    @Override
-    public void reset() {
-        synchronized (mEventCbLock) {
-            mEventCallbackRecords.clear();
-        }
-        synchronized (mDrmEventCbLock) {
-            mDrmEventCallbackRecords.clear();
-        }
-        synchronized (mSrcLock) {
-            if (mNextDSDs != null) {
-                mNextDSDs.clear();
-                mNextDSDs = null;
-            }
-            mNextSrcId = mSrcIdGenerator++;
-            mNextSourceState = NEXT_SOURCE_STATE_INIT;
-        }
-
-        stayAwake(false);
-        _reset();
-        // make sure none of the listeners get called anymore
-        if (mTaskHandler != null) {
-            mTaskHandler.removeCallbacksAndMessages(null);
-        }
-
-        resetDrmState();
-    }
-
-    private native void _reset();
-
-    // Keep KEY_PARAMETER_* in sync with include/media/mediaplayer2.h
-    private final static int KEY_PARAMETER_AUDIO_ATTRIBUTES = 1400;
-    /**
-     * Sets the parameter indicated by key.
-     * @param key key indicates the parameter to be set.
-     * @param value value of the parameter to be set.
-     * @return true if the parameter is set successfully, false otherwise
-     */
-    private native boolean setParameter(int key, Object value);
-
-    private native Object getParameter(int key);
-
-
-    /**
-     * Checks whether the MediaPlayer2 is looping or non-looping.
-     *
-     * @return true if the MediaPlayer2 is currently looping, false otherwise
-     * @hide
-     */
-    @Override
-    public native boolean isLooping();
-
-    /**
-     * Sets the audio session ID.
-     *
-     * @param sessionId the audio session ID.
-     * The audio session ID is a system wide unique identifier for the audio stream played by
-     * this MediaPlayer2 instance.
-     * The primary use of the audio session ID  is to associate audio effects to a particular
-     * instance of MediaPlayer2: if an audio session ID is provided when creating an audio effect,
-     * this effect will be applied only to the audio content of media players within the same
-     * audio session and not to the output mix.
-     * When created, a MediaPlayer2 instance automatically generates its own audio session ID.
-     * However, it is possible to force this player to be part of an already existing audio session
-     * by calling this method.
-     * This method must be called before one of the overloaded <code> setDataSource </code> methods.
-     * @throws IllegalStateException if it is called in an invalid state
-     * @throws IllegalArgumentException if the sessionId is invalid.
-     */
-    @Override
-    public Object setAudioSessionId(int sessionId) {
-        return addTask(new Task(CALL_COMPLETED_SET_AUDIO_SESSION_ID, false) {
-            @Override
-            void process() {
-                _setAudioSessionId(sessionId);
-            }
-        });
-    }
-
-    private native void _setAudioSessionId(int sessionId);
-
-    /**
-     * Returns the audio session ID.
-     *
-     * @return the audio session ID. {@see #setAudioSessionId(int)}
-     * Note that the audio session ID is 0 only if a problem occured when the MediaPlayer2 was contructed.
-     */
-    @Override
-    public native int getAudioSessionId();
-
-    /**
-     * Attaches an auxiliary effect to the player. A typical auxiliary effect is a reverberation
-     * effect which can be applied on any sound source that directs a certain amount of its
-     * energy to this effect. This amount is defined by setAuxEffectSendLevel().
-     * See {@link #setAuxEffectSendLevel(float)}.
-     * <p>After creating an auxiliary effect (e.g.
-     * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with
-     * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling this method
-     * to attach the player to the effect.
-     * <p>To detach the effect from the player, call this method with a null effect id.
-     * <p>This method must be called after one of the overloaded <code> setDataSource </code>
-     * methods.
-     * @param effectId system wide unique id of the effect to attach
-     */
-    @Override
-    public Object attachAuxEffect(int effectId) {
-        return addTask(new Task(CALL_COMPLETED_ATTACH_AUX_EFFECT, false) {
-            @Override
-            void process() {
-                _attachAuxEffect(effectId);
-            }
-        });
-    }
-
-    private native void _attachAuxEffect(int effectId);
-
-    /**
-     * Sets the send level of the player to the attached auxiliary effect.
-     * See {@link #attachAuxEffect(int)}. The level value range is 0 to 1.0.
-     * <p>By default the send level is 0, so even if an effect is attached to the player
-     * this method must be called for the effect to be applied.
-     * <p>Note that the passed level value is a raw scalar. UI controls should be scaled
-     * logarithmically: the gain applied by audio framework ranges from -72dB to 0dB,
-     * so an appropriate conversion from linear UI input x to level is:
-     * x == 0 -> level = 0
-     * 0 < x <= R -> level = 10^(72*(x-R)/20/R)
-     * @param level send level scalar
-     */
-    @Override
-    public Object setAuxEffectSendLevel(float level) {
-        return addTask(new Task(CALL_COMPLETED_SET_AUX_EFFECT_SEND_LEVEL, false) {
-            @Override
-            void process() {
-                _setAuxEffectSendLevel(level);
-            }
-        });
-    }
-
-    private native void _setAuxEffectSendLevel(float level);
-
-    private static native final void native_init();
-    private native final void native_setup(Object mediaplayer2_this);
-    private native final void native_finalize();
-
-    private static native final void native_stream_event_onTearDown(
-            long nativeCallbackPtr, long userDataPtr);
-    private static native final void native_stream_event_onStreamPresentationEnd(
-            long nativeCallbackPtr, long userDataPtr);
-    private static native final void native_stream_event_onStreamDataRequest(
-            long jAudioTrackPtr, long nativeCallbackPtr, long userDataPtr);
-
-    /**
-     * Class for MediaPlayer2 to return each audio/video/subtitle track's metadata.
-     *
-     * @see android.media.MediaPlayer2#getTrackInfo
-     */
-    public static final class TrackInfoImpl extends TrackInfo {
-        /**
-         * Gets the track type.
-         * @return TrackType which indicates if the track is video, audio, timed text.
-         */
-        @Override
-        public int getTrackType() {
-            return mTrackType;
-        }
-
-        /**
-         * Gets the language code of the track.
-         * @return a language code in either way of ISO-639-1 or ISO-639-2.
-         * When the language is unknown or could not be determined,
-         * ISO-639-2 language code, "und", is returned.
-         */
-        @Override
-        public String getLanguage() {
-            String language = mFormat.getString(MediaFormat.KEY_LANGUAGE);
-            return language == null ? "und" : language;
-        }
-
-        /**
-         * Gets the {@link MediaFormat} of the track.  If the format is
-         * unknown or could not be determined, null is returned.
-         */
-        @Override
-        public MediaFormat getFormat() {
-            if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT
-                    || mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
-                return mFormat;
-            }
-            return null;
-        }
-
-        final int mTrackType;
-        final MediaFormat mFormat;
-
-        TrackInfoImpl(Iterator<Value> in) {
-            mTrackType = in.next().getInt32Value();
-            // TODO: build the full MediaFormat; currently we are using createSubtitleFormat
-            // even for audio/video tracks, meaning we only set the mime and language.
-            String mime = in.next().getStringValue();
-            String language = in.next().getStringValue();
-            mFormat = MediaFormat.createSubtitleFormat(mime, language);
-
-            if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
-                mFormat.setInteger(MediaFormat.KEY_IS_AUTOSELECT, in.next().getInt32Value());
-                mFormat.setInteger(MediaFormat.KEY_IS_DEFAULT, in.next().getInt32Value());
-                mFormat.setInteger(MediaFormat.KEY_IS_FORCED_SUBTITLE, in.next().getInt32Value());
-            }
-        }
-
-        /** @hide */
-        TrackInfoImpl(int type, MediaFormat format) {
-            mTrackType = type;
-            mFormat = format;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder out = new StringBuilder(128);
-            out.append(getClass().getName());
-            out.append('{');
-            switch (mTrackType) {
-            case MEDIA_TRACK_TYPE_VIDEO:
-                out.append("VIDEO");
-                break;
-            case MEDIA_TRACK_TYPE_AUDIO:
-                out.append("AUDIO");
-                break;
-            case MEDIA_TRACK_TYPE_TIMEDTEXT:
-                out.append("TIMEDTEXT");
-                break;
-            case MEDIA_TRACK_TYPE_SUBTITLE:
-                out.append("SUBTITLE");
-                break;
-            default:
-                out.append("UNKNOWN");
-                break;
-            }
-            out.append(", " + mFormat.toString());
-            out.append("}");
-            return out.toString();
-        }
-    };
-
-    /**
-     * Returns a List of track information.
-     *
-     * @return List of track info. The total number of tracks is the array length.
-     * Must be called again if an external timed text source has been added after
-     * addTimedTextSource method is called.
-     * @throws IllegalStateException if it is called in an invalid state.
-     */
-    @Override
-    public List<TrackInfo> getTrackInfo() {
-        TrackInfoImpl trackInfo[] = getInbandTrackInfoImpl();
-        return Arrays.asList(trackInfo);
-    }
-
-    private TrackInfoImpl[] getInbandTrackInfoImpl() throws IllegalStateException {
-        PlayerMessage request = PlayerMessage.newBuilder()
-                .addValues(Value.newBuilder().setInt32Value(INVOKE_ID_GET_TRACK_INFO))
-                .build();
-        PlayerMessage response = invoke(request);
-        if (response == null) {
-            return null;
-        }
-        Iterator<Value> in = response.getValuesList().iterator();
-        int size = in.next().getInt32Value();
-        if (size == 0) {
-            return null;
-        }
-        TrackInfoImpl trackInfo[] = new TrackInfoImpl[size];
-        for (int i = 0; i < size; ++i) {
-            trackInfo[i] = new TrackInfoImpl(in);
-        }
-        return trackInfo;
-    }
-
-    /*
-     * A helper function to check if the mime type is supported by media framework.
-     */
-    private static boolean availableMimeTypeForExternalSource(String mimeType) {
-        if (MEDIA_MIMETYPE_TEXT_SUBRIP.equals(mimeType)) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Returns the index of the audio, video, or subtitle track currently selected for playback,
-     * The return value is an index into the array returned by {@link #getTrackInfo()}, and can
-     * be used in calls to {@link #selectTrack(int)} or {@link #deselectTrack(int)}.
-     *
-     * @param trackType should be one of {@link TrackInfo#MEDIA_TRACK_TYPE_VIDEO},
-     * {@link TrackInfo#MEDIA_TRACK_TYPE_AUDIO}, or
-     * {@link TrackInfo#MEDIA_TRACK_TYPE_SUBTITLE}
-     * @return index of the audio, video, or subtitle track currently selected for playback;
-     * a negative integer is returned when there is no selected track for {@code trackType} or
-     * when {@code trackType} is not one of audio, video, or subtitle.
-     * @throws IllegalStateException if called after {@link #close()}
-     *
-     * @see #getTrackInfo()
-     * @see #selectTrack(int)
-     * @see #deselectTrack(int)
-     */
-    @Override
-    public int getSelectedTrack(int trackType) {
-        PlayerMessage request = PlayerMessage.newBuilder()
-                .addValues(Value.newBuilder().setInt32Value(INVOKE_ID_GET_SELECTED_TRACK))
-                .addValues(Value.newBuilder().setInt32Value(trackType))
-                .build();
-        PlayerMessage response = invoke(request);
-        if (response == null) {
-            return -1;
-        }
-        return response.getValues(0).getInt32Value();
-    }
-
-    /**
-     * Selects a track.
-     * <p>
-     * If a MediaPlayer2 is in invalid state, it throws an IllegalStateException exception.
-     * If a MediaPlayer2 is in <em>Started</em> state, the selected track is presented immediately.
-     * If a MediaPlayer2 is not in Started state, it just marks the track to be played.
-     * </p>
-     * <p>
-     * In any valid state, if it is called multiple times on the same type of track (ie. Video,
-     * Audio, Timed Text), the most recent one will be chosen.
-     * </p>
-     * <p>
-     * The first audio and video tracks are selected by default if available, even though
-     * this method is not called. However, no timed text track will be selected until
-     * this function is called.
-     * </p>
-     * <p>
-     * Currently, only timed text tracks or audio tracks can be selected via this method.
-     * In addition, the support for selecting an audio track at runtime is pretty limited
-     * in that an audio track can only be selected in the <em>Prepared</em> state.
-     * </p>
-     * @param index the index of the track to be selected. The valid range of the index
-     * is 0..total number of track - 1. The total number of tracks as well as the type of
-     * each individual track can be found by calling {@link #getTrackInfo()} method.
-     * @throws IllegalStateException if called in an invalid state.
-     *
-     * @see android.media.MediaPlayer2#getTrackInfo
-     */
-    @Override
-    public Object selectTrack(int index) {
-        return addTask(new Task(CALL_COMPLETED_SELECT_TRACK, false) {
-            @Override
-            void process() {
-                selectOrDeselectTrack(index, true /* select */);
-            }
-        });
-    }
-
-    /**
-     * Deselect a track.
-     * <p>
-     * Currently, the track must be a timed text track and no audio or video tracks can be
-     * deselected. If the timed text track identified by index has not been
-     * selected before, it throws an exception.
-     * </p>
-     * @param index the index of the track to be deselected. The valid range of the index
-     * is 0..total number of tracks - 1. The total number of tracks as well as the type of
-     * each individual track can be found by calling {@link #getTrackInfo()} method.
-     * @throws IllegalStateException if called in an invalid state.
-     *
-     * @see android.media.MediaPlayer2#getTrackInfo
-     */
-    @Override
-    public Object deselectTrack(int index) {
-        return addTask(new Task(CALL_COMPLETED_DESELECT_TRACK, false) {
-            @Override
-            void process() {
-                selectOrDeselectTrack(index, false /* select */);
-            }
-        });
-    }
-
-    private void selectOrDeselectTrack(int index, boolean select)
-            throws IllegalStateException {
-        PlayerMessage request = PlayerMessage.newBuilder()
-                .addValues(Value.newBuilder().setInt32Value(
-                            select? INVOKE_ID_SELECT_TRACK: INVOKE_ID_DESELECT_TRACK))
-                .addValues(Value.newBuilder().setInt32Value(index))
-                .build();
-        invoke(request);
-    }
-
-    // Have to declare protected for finalize() since it is protected
-    // in the base class Object.
-    @Override
-    protected void finalize() throws Throwable {
-        super.finalize();
-        native_finalize();
-    }
-
-    private synchronized void release() {
-        if (mReleased) {
-            return;
-        }
-        stayAwake(false);
-        updateSurfaceScreenOn();
-        synchronized (mEventCbLock) {
-            mEventCallbackRecords.clear();
-        }
-        if (mHandlerThread != null) {
-            mHandlerThread.quitSafely();
-            mHandlerThread = null;
-        }
-
-        // Modular DRM clean up
-        mOnDrmConfigHelper = null;
-        synchronized (mDrmEventCbLock) {
-            mDrmEventCallbackRecords.clear();
-        }
-        resetDrmState();
-
-        _release();
-        mReleased = true;
-    }
-
-    private native void _release();
-
-    /* Do not change these values without updating their counterparts
-     * in include/media/mediaplayer2.h!
-     */
-    private static final int MEDIA_NOP = 0; // interface test message
-    private static final int MEDIA_PREPARED = 1;
-    private static final int MEDIA_PLAYBACK_COMPLETE = 2;
-    private static final int MEDIA_BUFFERING_UPDATE = 3;
-    private static final int MEDIA_SEEK_COMPLETE = 4;
-    private static final int MEDIA_SET_VIDEO_SIZE = 5;
-    private static final int MEDIA_STARTED = 6;
-    private static final int MEDIA_PAUSED = 7;
-    private static final int MEDIA_STOPPED = 8;
-    private static final int MEDIA_SKIPPED = 9;
-    private static final int MEDIA_NOTIFY_TIME = 98;
-    private static final int MEDIA_TIMED_TEXT = 99;
-    private static final int MEDIA_ERROR = 100;
-    private static final int MEDIA_INFO = 200;
-    private static final int MEDIA_SUBTITLE_DATA = 201;
-    private static final int MEDIA_META_DATA = 202;
-    private static final int MEDIA_DRM_INFO = 210;
-    private static final int MEDIA_AUDIO_ROUTING_CHANGED = 10000;
-
-    private class TaskHandler extends Handler {
-        private MediaPlayer2Impl mMediaPlayer;
-
-        public TaskHandler(MediaPlayer2Impl mp, Looper looper) {
-            super(looper);
-            mMediaPlayer = mp;
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            handleMessage(msg, 0);
-        }
-
-        public void handleMessage(Message msg, long srcId) {
-            if (mMediaPlayer.mNativeContext == 0) {
-                Log.w(TAG, "mediaplayer2 went away with unhandled events");
-                return;
-            }
-            final int what = msg.arg1;
-            final int extra = msg.arg2;
-
-            final DataSourceDesc dsd;
-            boolean isCurrentSrcId = false;
-            boolean isNextSrcId = false;
-            synchronized (mSrcLock) {
-                if (srcId == mCurrentSrcId) {
-                    dsd = mCurrentDSD;
-                    isCurrentSrcId = true;
-                } else if (mNextDSDs != null && !mNextDSDs.isEmpty() && srcId == mNextSrcId) {
-                    dsd = mNextDSDs.get(0);
-                    isNextSrcId = true;
-                } else {
-                    return;
-                }
-            }
-
-            switch(msg.what) {
-            case MEDIA_PREPARED:
-            {
-                if (dsd != null) {
-                    sendEvent(new EventNotifier() {
-                        @Override
-                        public void notify(EventCallback callback) {
-                            callback.onInfo(
-                                    mMediaPlayer, dsd, MEDIA_INFO_PREPARED, 0);
-                        }
-                    });
-                }
-
-                synchronized (mSrcLock) {
-                    Log.i(TAG, "MEDIA_PREPARED: srcId=" + srcId
-                            + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
-
-                    if (isCurrentSrcId) {
-                        prepareNextDataSource();
-                    } else if (isNextSrcId) {
-                        mNextSourceState = NEXT_SOURCE_STATE_PREPARED;
-                        if (mNextSourcePlayPending) {
-                            playNextDataSource();
-                        }
-                    }
-                }
-
-                synchronized (mTaskLock) {
-                    if (mCurrentTask != null
-                            && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE
-                            && mCurrentTask.mDSD == dsd
-                            && mCurrentTask.mNeedToWaitForEventToComplete) {
-                        mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
-                        mCurrentTask = null;
-                        processPendingTask_l();
-                    }
-                }
-                return;
-            }
-
-            case MEDIA_DRM_INFO:
-            {
-                if (msg.obj == null) {
-                    Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
-                } else if (msg.obj instanceof byte[]) {
-                    // The PlayerMessage was parsed already in postEventFromNative
-                    final DrmInfoImpl drmInfo;
-
-                    synchronized (mDrmLock) {
-                        if (mDrmInfoImpl != null) {
-                            drmInfo = mDrmInfoImpl.makeCopy();
-                        } else {
-                            drmInfo = null;
-                        }
-                    }
-
-                    // notifying the client outside the lock
-                    if (drmInfo != null) {
-                        sendDrmEvent(new DrmEventNotifier() {
-                            @Override
-                            public void notify(DrmEventCallback callback) {
-                                callback.onDrmInfo(
-                                        mMediaPlayer, dsd, drmInfo);
-                            }
-                        });
-                    }
-                } else {
-                    Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + msg.obj);
-                }
-                return;
-            }
-
-            case MEDIA_PLAYBACK_COMPLETE:
-            {
-                if (isCurrentSrcId) {
-                    sendEvent(new EventNotifier() {
-                        @Override
-                        public void notify(EventCallback callback) {
-                            callback.onInfo(
-                                    mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0);
-                        }
-                    });
-                    stayAwake(false);
-
-                    synchronized (mSrcLock) {
-                        mNextSourcePlayPending = true;
-
-                        Log.i(TAG, "MEDIA_PLAYBACK_COMPLETE: srcId=" + srcId
-                                + ", currentSrcId=" + mCurrentSrcId + ", nextSrcId=" + mNextSrcId);
-                    }
-
-                    playNextDataSource();
-                }
-
-                return;
-            }
-
-            case MEDIA_STOPPED:
-            case MEDIA_STARTED:
-            case MEDIA_PAUSED:
-            case MEDIA_SKIPPED:
-            case MEDIA_NOTIFY_TIME:
-            {
-                // Do nothing. The client should have enough information with
-                // {@link EventCallback#onMediaTimeDiscontinuity}.
-                break;
-            }
-
-            case MEDIA_BUFFERING_UPDATE:
-            {
-                final int percent = msg.arg1;
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onInfo(
-                                mMediaPlayer, dsd, MEDIA_INFO_BUFFERING_UPDATE, percent);
-                    }
-                });
-
-                synchronized (mSrcLock) {
-                    if (isCurrentSrcId) {
-                        mBufferedPercentageCurrent.set(percent);
-                    } else if (isNextSrcId) {
-                        mBufferedPercentageNext.set(percent);
-                    }
-                }
-                return;
-            }
-
-            case MEDIA_SEEK_COMPLETE:
-            {
-                synchronized (mTaskLock) {
-                    if (mCurrentTask != null
-                            && mCurrentTask.mMediaCallType == CALL_COMPLETED_SEEK_TO
-                            && mCurrentTask.mNeedToWaitForEventToComplete) {
-                        mCurrentTask.sendCompleteNotification(CALL_STATUS_NO_ERROR);
-                        mCurrentTask = null;
-                        processPendingTask_l();
-                    }
-                }
-                return;
-            }
-
-            case MEDIA_SET_VIDEO_SIZE:
-            {
-                final int width = msg.arg1;
-                final int height = msg.arg2;
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onVideoSizeChanged(
-                                mMediaPlayer, dsd, width, height);
-                    }
-                });
-                return;
-            }
-
-            case MEDIA_ERROR:
-            {
-                Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onError(
-                                mMediaPlayer, dsd, what, extra);
-                    }
-                });
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onInfo(
-                                mMediaPlayer, dsd, MEDIA_INFO_DATA_SOURCE_END, 0);
-                    }
-                });
-                stayAwake(false);
-                return;
-            }
-
-            case MEDIA_INFO:
-            {
-                switch (msg.arg1) {
-                    case MEDIA_INFO_VIDEO_TRACK_LAGGING:
-                        Log.i(TAG, "Info (" + msg.arg1 + "," + msg.arg2 + ")");
-                        break;
-                }
-
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onInfo(
-                                mMediaPlayer, dsd, what, extra);
-                    }
-                });
-
-                if (msg.arg1 == MEDIA_INFO_DATA_SOURCE_START) {
-                    if (isCurrentSrcId) {
-                        prepareNextDataSource();
-                    }
-                }
-
-                // No real default action so far.
-                return;
-            }
-
-            case MEDIA_TIMED_TEXT:
-            {
-                final TimedText text;
-                if (msg.obj instanceof byte[]) {
-                    PlayerMessage playerMsg;
-                    try {
-                        playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
-                    } catch (InvalidProtocolBufferException e) {
-                        Log.w(TAG, "Failed to parse timed text.", e);
-                        return;
-                    }
-                    text = TimedTextUtil.parsePlayerMessage(playerMsg);
-                } else {
-                    text = null;
-                }
-
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onTimedText(
-                                mMediaPlayer, dsd, text);
-                    }
-                });
-                return;
-            }
-
-            case MEDIA_SUBTITLE_DATA:
-            {
-                if (msg.obj instanceof byte[]) {
-                    PlayerMessage playerMsg;
-                    try {
-                        playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
-                    } catch (InvalidProtocolBufferException e) {
-                        Log.w(TAG, "Failed to parse subtitle data.", e);
-                        return;
-                    }
-                    Iterator<Value> in = playerMsg.getValuesList().iterator();
-                    SubtitleData data = new SubtitleData(
-                            in.next().getInt32Value(),  // trackIndex
-                            in.next().getInt64Value(),  // startTimeUs
-                            in.next().getInt64Value(),  // durationUs
-                            in.next().getBytesValue().toByteArray());  // data
-                    sendEvent(new EventNotifier() {
-                        @Override
-                        public void notify(EventCallback callback) {
-                            callback.onSubtitleData(
-                                    mMediaPlayer, dsd, data);
-                        }
-                    });
-                }
-                return;
-            }
-
-            case MEDIA_META_DATA:
-            {
-                final TimedMetaData data;
-                if (msg.obj instanceof byte[]) {
-                    PlayerMessage playerMsg;
-                    try {
-                        playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
-                    } catch (InvalidProtocolBufferException e) {
-                        Log.w(TAG, "Failed to parse timed meta data.", e);
-                        return;
-                    }
-                    Iterator<Value> in = playerMsg.getValuesList().iterator();
-                    data = new TimedMetaData(
-                            in.next().getInt64Value(),  // timestampUs
-                            in.next().getBytesValue().toByteArray());  // metaData
-                } else {
-                    data = null;
-                }
-
-                sendEvent(new EventNotifier() {
-                    @Override
-                    public void notify(EventCallback callback) {
-                        callback.onTimedMetaDataAvailable(
-                                mMediaPlayer, dsd, data);
-                    }
-                });
-                return;
-            }
-
-            case MEDIA_NOP: // interface test message - ignore
-            {
-                break;
-            }
-
-            case MEDIA_AUDIO_ROUTING_CHANGED:
-            {
-                AudioManager.resetAudioPortGeneration();
-                synchronized (mRoutingChangeListeners) {
-                    for (NativeRoutingEventHandlerDelegate delegate
-                            : mRoutingChangeListeners.values()) {
-                        delegate.notifyClient();
-                    }
-                }
-                return;
-            }
-
-            default:
-            {
-                Log.e(TAG, "Unknown message type " + msg.what);
-                return;
-            }
-            }
-        }
-    }
-
-    /*
-     * Called from native code when an interesting event happens.  This method
-     * just uses the TaskHandler system to post the event back to the main app thread.
-     * We use a weak reference to the original MediaPlayer2 object so that the native
-     * code is safe from the object disappearing from underneath it.  (This is
-     * the cookie passed to native_setup().)
-     */
-    private static void postEventFromNative(Object mediaplayer2_ref, long srcId,
-                                            int what, int arg1, int arg2, byte[] obj)
-    {
-        final MediaPlayer2Impl mp = (MediaPlayer2Impl)((WeakReference)mediaplayer2_ref).get();
-        if (mp == null) {
-            return;
-        }
-
-        switch (what) {
-        case MEDIA_DRM_INFO:
-            // We need to derive mDrmInfoImpl before prepare() returns so processing it here
-            // before the notification is sent to TaskHandler below. TaskHandler runs in the
-            // notification looper so its handleMessage might process the event after prepare()
-            // has returned.
-            Log.v(TAG, "postEventFromNative MEDIA_DRM_INFO");
-            if (obj != null) {
-                PlayerMessage playerMsg;
-                try {
-                    playerMsg = PlayerMessage.parseFrom(obj);
-                } catch (InvalidProtocolBufferException e) {
-                    Log.w(TAG, "MEDIA_DRM_INFO failed to parse msg.obj " + obj);
-                    break;
-                }
-                DrmInfoImpl drmInfo = new DrmInfoImpl(playerMsg);
-                synchronized (mp.mDrmLock) {
-                    mp.mDrmInfoImpl = drmInfo;
-                }
-            } else {
-                Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + obj);
-            }
-            break;
-
-        case MEDIA_PREPARED:
-            // By this time, we've learned about DrmInfo's presence or absence. This is meant
-            // mainly for prepare() use case. For prepare(), this still can run to a race
-            // condition b/c MediaPlayerNative releases the prepare() lock before calling notify
-            // so we also set mDrmInfoResolved in prepare().
-            synchronized (mp.mDrmLock) {
-                mp.mDrmInfoResolved = true;
-            }
-            break;
-
-        }
-
-        if (mp.mTaskHandler != null) {
-            Message m = mp.mTaskHandler.obtainMessage(what, arg1, arg2, obj);
-
-            mp.mTaskHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mp.mTaskHandler.handleMessage(m, srcId);
-                }
-            });
-        }
-    }
-
-    private final Object mEventCbLock = new Object();
-    private ArrayList<Pair<Executor, EventCallback> > mEventCallbackRecords
-        = new ArrayList<Pair<Executor, EventCallback> >();
-
-    /**
-     * Register a callback to be invoked when the media source is ready
-     * for playback.
-     *
-     * @param eventCallback the callback that will be run
-     * @param executor the executor through which the callback should be invoked
-     */
-    @Override
-    public void registerEventCallback(@NonNull @CallbackExecutor Executor executor,
-            @NonNull EventCallback eventCallback) {
-        if (eventCallback == null) {
-            throw new IllegalArgumentException("Illegal null EventCallback");
-        }
-        if (executor == null) {
-            throw new IllegalArgumentException(
-                    "Illegal null Executor for the EventCallback");
-        }
-        synchronized (mEventCbLock) {
-            mEventCallbackRecords.add(new Pair(executor, eventCallback));
-        }
-    }
-
-    /**
-     * Clears the {@link EventCallback}.
-     */
-    @Override
-    public void unregisterEventCallback(EventCallback eventCallback) {
-        synchronized (mEventCbLock) {
-            for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                if (cb.second == eventCallback) {
-                    mEventCallbackRecords.remove(cb);
-                }
-            }
-        }
-    }
-
-    private static void checkArgument(boolean expression, String errorMessage) {
-        if (!expression) {
-            throw new IllegalArgumentException(errorMessage);
-        }
-    }
-
-    private void sendEvent(final EventNotifier notifier) {
-        synchronized (mEventCbLock) {
-            try {
-                for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
-                    cb.first.execute(() -> notifier.notify(cb.second));
-                }
-            } catch (RejectedExecutionException e) {
-                // The executor has been shut down.
-                Log.w(TAG, "The executor has been shut down. Ignoring event.");
-            }
-        }
-    }
-
-    private void sendDrmEvent(final DrmEventNotifier notifier) {
-        synchronized (mDrmEventCbLock) {
-            try {
-                for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
-                    cb.first.execute(() -> notifier.notify(cb.second));
-                }
-            } catch (RejectedExecutionException e) {
-                // The executor has been shut down.
-                Log.w(TAG, "The executor has been shut down. Ignoring drm event.");
-            }
-        }
-    }
-
-    private interface EventNotifier {
-        void notify(EventCallback callback);
-    }
-
-    private interface DrmEventNotifier {
-        void notify(DrmEventCallback callback);
-    }
-
-    // Modular DRM begin
-
-    /**
-     * Register a callback to be invoked for configuration of the DRM object before
-     * the session is created.
-     * The callback will be invoked synchronously during the execution
-     * of {@link #prepareDrm(UUID uuid)}.
-     *
-     * @param listener the callback that will be run
-     */
-    @Override
-    public void setOnDrmConfigHelper(OnDrmConfigHelper listener)
-    {
-        synchronized (mDrmLock) {
-            mOnDrmConfigHelper = listener;
-        } // synchronized
-    }
-
-    private OnDrmConfigHelper mOnDrmConfigHelper;
-
-    private final Object mDrmEventCbLock = new Object();
-    private ArrayList<Pair<Executor, DrmEventCallback> > mDrmEventCallbackRecords
-        = new ArrayList<Pair<Executor, DrmEventCallback> >();
-
-    @Override
-    public void registerDrmEventCallback(@NonNull @CallbackExecutor Executor executor,
-            @NonNull DrmEventCallback eventCallback) {
-        if (eventCallback == null) {
-            throw new IllegalArgumentException("Illegal null EventCallback");
-        }
-        if (executor == null) {
-            throw new IllegalArgumentException(
-                    "Illegal null Executor for the EventCallback");
-        }
-        synchronized (mDrmEventCbLock) {
-            mDrmEventCallbackRecords.add(new Pair(executor, eventCallback));
-        }
-    }
-
-    @Override
-    public void unregisterDrmEventCallback(DrmEventCallback eventCallback) {
-        synchronized (mDrmEventCbLock) {
-            for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
-                if (cb.second == eventCallback) {
-                    mDrmEventCallbackRecords.remove(cb);
-                }
-            }
-        }
-    }
-
-    /**
-     * Retrieves the DRM Info associated with the current source
-     *
-     * @throws IllegalStateException if called before prepare()
-     */
-    @Override
-    public DrmInfo getDrmInfo() {
-        DrmInfoImpl drmInfo = null;
-
-        // there is not much point if the app calls getDrmInfo within an OnDrmInfoListenet;
-        // regardless below returns drmInfo anyway instead of raising an exception
-        synchronized (mDrmLock) {
-            if (!mDrmInfoResolved && mDrmInfoImpl == null) {
-                final String msg = "The Player has not been prepared yet";
-                Log.v(TAG, msg);
-                throw new IllegalStateException(msg);
-            }
-
-            if (mDrmInfoImpl != null) {
-                drmInfo = mDrmInfoImpl.makeCopy();
-            }
-        }   // synchronized
-
-        return drmInfo;
-    }
-
-    @Override
-    public Object prepareDrm(@NonNull UUID uuid) {
-        return addTask(new Task(CALL_COMPLETED_PREPARE_DRM, true) {
-            @Override
-            void process() {
-                int status = PREPARE_DRM_STATUS_SUCCESS;
-                boolean sendEvent = true;
-
-                try {
-                    doPrepareDrm(uuid);
-                } catch (ResourceBusyException e) {
-                    status = PREPARE_DRM_STATUS_RESOURCE_BUSY;
-                } catch (UnsupportedSchemeException e) {
-                    status = PREPARE_DRM_STATUS_UNSUPPORTED_SCHEME;
-                } catch (NotProvisionedException e) {
-                    Log.w(TAG, "prepareDrm: NotProvisionedException");
-
-                    // handle provisioning internally; it'll reset mPrepareDrmInProgress
-                    status = HandleProvisioninig(uuid);
-
-                    if (status == PREPARE_DRM_STATUS_SUCCESS) {
-                        // DrmEventCallback will be fired in provisioning
-                        sendEvent = false;
-                    } else {
-                        synchronized (mDrmLock) {
-                            cleanDrmObj();
-                        }
-
-                        switch (status) {
-                        case PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR:
-                            Log.e(TAG, "prepareDrm: Provisioning was required but failed " +
-                                    "due to a network error.");
-                            break;
-
-                        case PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR:
-                            Log.e(TAG, "prepareDrm: Provisioning was required but the request " +
-                                    "was denied by the server.");
-                            break;
-
-                        case PREPARE_DRM_STATUS_PREPARATION_ERROR:
-                        default:
-                            Log.e(TAG, "prepareDrm: Post-provisioning preparation failed.");
-                            break;
-                        }
-                    }
-                } catch (Exception e) {
-                    status = PREPARE_DRM_STATUS_PREPARATION_ERROR;
-                }
-
-                if (sendEvent) {
-                    final int prepareDrmStatus = status;
-                    sendDrmEvent(new DrmEventNotifier() {
-                        @Override
-                        public void notify(DrmEventCallback callback) {
-                            callback.onDrmPrepared(
-                                    MediaPlayer2Impl.this, mCurrentDSD, prepareDrmStatus);
-                        }
-                    });
-
-                    synchronized (mTaskLock) {
-                        mCurrentTask = null;
-                        processPendingTask_l();
-                    }
-                }
-            }
-        });
-    }
-
-    private void doPrepareDrm(@NonNull UUID uuid)
-            throws UnsupportedSchemeException, ResourceBusyException,
-                   NotProvisionedException {
-        Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigHelper: " + mOnDrmConfigHelper);
-
-        synchronized (mDrmLock) {
-            // only allowing if tied to a protected source; might relax for releasing offline keys
-            if (mDrmInfoImpl == null) {
-                final String msg = "prepareDrm(): Wrong usage: The player must be prepared and " +
-                        "DRM info be retrieved before this call.";
-                Log.e(TAG, msg);
-                throw new IllegalStateException(msg);
-            }
-
-            if (mActiveDrmScheme) {
-                final String msg = "prepareDrm(): Wrong usage: There is already " +
-                        "an active DRM scheme with " + mDrmUUID;
-                Log.e(TAG, msg);
-                throw new IllegalStateException(msg);
-            }
-
-            if (mPrepareDrmInProgress) {
-                final String msg = "prepareDrm(): Wrong usage: There is already " +
-                        "a pending prepareDrm call.";
-                Log.e(TAG, msg);
-                throw new IllegalStateException(msg);
-            }
-
-            if (mDrmProvisioningInProgress) {
-                final String msg = "prepareDrm(): Unexpectd: Provisioning is already in progress.";
-                Log.e(TAG, msg);
-                throw new IllegalStateException(msg);
-            }
-
-            // shouldn't need this; just for safeguard
-            cleanDrmObj();
-
-            mPrepareDrmInProgress = true;
-
-            try {
-                // only creating the DRM object to allow pre-openSession configuration
-                prepareDrm_createDrmStep(uuid);
-            } catch (Exception e) {
-                Log.w(TAG, "prepareDrm(): Exception ", e);
-                mPrepareDrmInProgress = false;
-                throw e;
-            }
-
-            mDrmConfigAllowed = true;
-        }  // synchronized
-
-        // call the callback outside the lock
-        if (mOnDrmConfigHelper != null)  {
-            mOnDrmConfigHelper.onDrmConfig(this, mCurrentDSD);
-        }
-
-        synchronized (mDrmLock) {
-            mDrmConfigAllowed = false;
-            boolean earlyExit = false;
-
-            try {
-                prepareDrm_openSessionStep(uuid);
-
-                mDrmUUID = uuid;
-                mActiveDrmScheme = true;
-                mPrepareDrmInProgress = false;
-            } catch (IllegalStateException e) {
-                final String msg = "prepareDrm(): Wrong usage: The player must be " +
-                        "in the prepared state to call prepareDrm().";
-                Log.e(TAG, msg);
-                earlyExit = true;
-                mPrepareDrmInProgress = false;
-                throw new IllegalStateException(msg);
-            } catch (NotProvisionedException e) {
-                Log.w(TAG, "prepareDrm: NotProvisionedException", e);
-                throw e;
-            } catch (Exception e) {
-                Log.e(TAG, "prepareDrm: Exception " + e);
-                earlyExit = true;
-                mPrepareDrmInProgress = false;
-                throw e;
-            } finally {
-                if (earlyExit) {  // clean up object if didn't succeed
-                    cleanDrmObj();
-                }
-            }  // finally
-        }  // synchronized
-    }
-
-    @Override
-    public void releaseDrm()
-            throws NoDrmSchemeException {
-        synchronized (mDrmLock) {
-            Log.v(TAG, "releaseDrm:");
-
-            if (!mActiveDrmScheme) {
-                Log.e(TAG, "releaseDrm(): No active DRM scheme to release.");
-                throw new NoDrmSchemeExceptionImpl(
-                        "releaseDrm: No active DRM scheme to release.");
-            }
-
-            try {
-                // we don't have the player's state in this layer. The below call raises
-                // exception if we're in a non-stopped/prepared state.
-
-                // for cleaning native/mediaserver crypto object
-                _releaseDrm();
-
-                // for cleaning client-side MediaDrm object; only called if above has succeeded
-                cleanDrmObj();
-
-                mActiveDrmScheme = false;
-            } catch (IllegalStateException e) {
-                Log.w(TAG, "releaseDrm: Exception ", e);
-                throw new IllegalStateException(
-                        "releaseDrm: The player is not in a valid state.");
-            } catch (Exception e) {
-                Log.e(TAG, "releaseDrm: Exception ", e);
-            }
-        }  // synchronized
-    }
-
-    private native void _releaseDrm();
-
-    /**
-     * A key request/response exchange occurs between the app and a license server
-     * to obtain or release keys used to decrypt encrypted content.
-     * <p>
-     * getDrmKeyRequest() is used to obtain an opaque key request byte array that is
-     * delivered to the license server.  The opaque key request byte array is returned
-     * in KeyRequest.data.  The recommended URL to deliver the key request to is
-     * returned in KeyRequest.defaultUrl.
-     * <p>
-     * After the app has received the key request response from the server,
-     * it should deliver to the response to the DRM engine plugin using the method
-     * {@link #provideDrmKeyResponse}.
-     *
-     * @param keySetId is the key-set identifier of the offline keys being released when keyType is
-     * {@link MediaDrm#KEY_TYPE_RELEASE}. It should be set to null for other key requests, when
-     * keyType is {@link MediaDrm#KEY_TYPE_STREAMING} or {@link MediaDrm#KEY_TYPE_OFFLINE}.
-     *
-     * @param initData is the container-specific initialization data when the keyType is
-     * {@link MediaDrm#KEY_TYPE_STREAMING} or {@link MediaDrm#KEY_TYPE_OFFLINE}. Its meaning is
-     * interpreted based on the mime type provided in the mimeType parameter.  It could
-     * contain, for example, the content ID, key ID or other data obtained from the content
-     * metadata that is required in generating the key request.
-     * When the keyType is {@link MediaDrm#KEY_TYPE_RELEASE}, it should be set to null.
-     *
-     * @param mimeType identifies the mime type of the content
-     *
-     * @param keyType specifies the type of the request. The request may be to acquire
-     * keys for streaming, {@link MediaDrm#KEY_TYPE_STREAMING}, or for offline content
-     * {@link MediaDrm#KEY_TYPE_OFFLINE}, or to release previously acquired
-     * keys ({@link MediaDrm#KEY_TYPE_RELEASE}), which are identified by a keySetId.
-     *
-     * @param optionalParameters are included in the key request message to
-     * allow a client application to provide additional message parameters to the server.
-     * This may be {@code null} if no additional parameters are to be sent.
-     *
-     * @throws NoDrmSchemeException if there is no active DRM session
-     */
-    @Override
-    @NonNull
-    public MediaDrm.KeyRequest getDrmKeyRequest(@Nullable byte[] keySetId, @Nullable byte[] initData,
-            @Nullable String mimeType, @MediaDrm.KeyType int keyType,
-            @Nullable Map<String, String> optionalParameters)
-            throws NoDrmSchemeException
-    {
-        Log.v(TAG, "getDrmKeyRequest: " +
-                " keySetId: " + keySetId + " initData:" + initData + " mimeType: " + mimeType +
-                " keyType: " + keyType + " optionalParameters: " + optionalParameters);
-
-        synchronized (mDrmLock) {
-            if (!mActiveDrmScheme) {
-                Log.e(TAG, "getDrmKeyRequest NoDrmSchemeException");
-                throw new NoDrmSchemeExceptionImpl(
-                        "getDrmKeyRequest: Has to set a DRM scheme first.");
-            }
-
-            try {
-                byte[] scope = (keyType != MediaDrm.KEY_TYPE_RELEASE) ?
-                        mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE
-                        keySetId;       // keySetId for KEY_TYPE_RELEASE
-
-                HashMap<String, String> hmapOptionalParameters =
-                                                (optionalParameters != null) ?
-                                                new HashMap<String, String>(optionalParameters) :
-                                                null;
-
-                MediaDrm.KeyRequest request = mDrmObj.getKeyRequest(scope, initData, mimeType,
-                                                              keyType, hmapOptionalParameters);
-                Log.v(TAG, "getDrmKeyRequest:   --> request: " + request);
-
-                return request;
-
-            } catch (NotProvisionedException e) {
-                Log.w(TAG, "getDrmKeyRequest NotProvisionedException: " +
-                        "Unexpected. Shouldn't have reached here.");
-                throw new IllegalStateException("getDrmKeyRequest: Unexpected provisioning error.");
-            } catch (Exception e) {
-                Log.w(TAG, "getDrmKeyRequest Exception " + e);
-                throw e;
-            }
-
-        }   // synchronized
-    }
-
-
-    /**
-     * A key response is received from the license server by the app, then it is
-     * provided to the DRM engine plugin using provideDrmKeyResponse. When the
-     * response is for an offline key request, a key-set identifier is returned that
-     * can be used to later restore the keys to a new session with the method
-     * {@link # restoreDrmKeys}.
-     * When the response is for a streaming or release request, null is returned.
-     *
-     * @param keySetId When the response is for a release request, keySetId identifies
-     * the saved key associated with the release request (i.e., the same keySetId
-     * passed to the earlier {@ link #getDrmKeyRequest} call. It MUST be null when the
-     * response is for either streaming or offline key requests.
-     *
-     * @param response the byte array response from the server
-     *
-     * @throws NoDrmSchemeException if there is no active DRM session
-     * @throws DeniedByServerException if the response indicates that the
-     * server rejected the request
-     */
-    @Override
-    public byte[] provideDrmKeyResponse(@Nullable byte[] keySetId, @NonNull byte[] response)
-            throws NoDrmSchemeException, DeniedByServerException
-    {
-        Log.v(TAG, "provideDrmKeyResponse: keySetId: " + keySetId + " response: " + response);
-
-        synchronized (mDrmLock) {
-
-            if (!mActiveDrmScheme) {
-                Log.e(TAG, "getDrmKeyRequest NoDrmSchemeException");
-                throw new NoDrmSchemeExceptionImpl(
-                        "getDrmKeyRequest: Has to set a DRM scheme first.");
-            }
-
-            try {
-                byte[] scope = (keySetId == null) ?
-                                mDrmSessionId :     // sessionId for KEY_TYPE_STREAMING/OFFLINE
-                                keySetId;           // keySetId for KEY_TYPE_RELEASE
-
-                byte[] keySetResult = mDrmObj.provideKeyResponse(scope, response);
-
-                Log.v(TAG, "provideDrmKeyResponse: keySetId: " + keySetId + " response: " + response
-                        + " --> " + keySetResult);
-
-
-                return keySetResult;
-
-            } catch (NotProvisionedException e) {
-                Log.w(TAG, "provideDrmKeyResponse NotProvisionedException: " +
-                        "Unexpected. Shouldn't have reached here.");
-                throw new IllegalStateException("provideDrmKeyResponse: " +
-                        "Unexpected provisioning error.");
-            } catch (Exception e) {
-                Log.w(TAG, "provideDrmKeyResponse Exception " + e);
-                throw e;
-            }
-        }   // synchronized
-    }
-
-    @Override
-    public void restoreDrmKeys(@NonNull byte[] keySetId)
-            throws NoDrmSchemeException {
-        Log.v(TAG, "restoreDrmKeys: keySetId: " + keySetId);
-
-        synchronized (mDrmLock) {
-            if (!mActiveDrmScheme) {
-                Log.w(TAG, "restoreDrmKeys NoDrmSchemeException");
-                throw new NoDrmSchemeExceptionImpl(
-                        "restoreDrmKeys: Has to set a DRM scheme first.");
-            }
-
-            try {
-                mDrmObj.restoreKeys(mDrmSessionId, keySetId);
-            } catch (Exception e) {
-                Log.w(TAG, "restoreKeys Exception " + e);
-                throw e;
-            }
-        }  // synchronized
-    }
-
-    /**
-     * Read a DRM engine plugin String property value, given the property name string.
-     * <p>
-     * @param propertyName the property name
-     *
-     * Standard fields names are:
-     * {@link MediaDrm#PROPERTY_VENDOR}, {@link MediaDrm#PROPERTY_VERSION},
-     * {@link MediaDrm#PROPERTY_DESCRIPTION}, {@link MediaDrm#PROPERTY_ALGORITHMS}
-     */
-    @Override
-    @NonNull
-    public String getDrmPropertyString(@NonNull @MediaDrm.StringProperty String propertyName)
-            throws NoDrmSchemeException
-    {
-        Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName);
-
-        String value;
-        synchronized (mDrmLock) {
-
-            if (!mActiveDrmScheme && !mDrmConfigAllowed) {
-                Log.w(TAG, "getDrmPropertyString NoDrmSchemeException");
-                throw new NoDrmSchemeExceptionImpl(
-                        "getDrmPropertyString: Has to prepareDrm() first.");
-            }
-
-            try {
-                value = mDrmObj.getPropertyString(propertyName);
-            } catch (Exception e) {
-                Log.w(TAG, "getDrmPropertyString Exception " + e);
-                throw e;
-            }
-        }   // synchronized
-
-        Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName + " --> value: " + value);
-
-        return value;
-    }
-
-
-    /**
-     * Set a DRM engine plugin String property value.
-     * <p>
-     * @param propertyName the property name
-     * @param value the property value
-     *
-     * Standard fields names are:
-     * {@link MediaDrm#PROPERTY_VENDOR}, {@link MediaDrm#PROPERTY_VERSION},
-     * {@link MediaDrm#PROPERTY_DESCRIPTION}, {@link MediaDrm#PROPERTY_ALGORITHMS}
-     */
-    @Override
-    public void setDrmPropertyString(@NonNull @MediaDrm.StringProperty String propertyName,
-                                     @NonNull String value)
-            throws NoDrmSchemeException
-    {
-        Log.v(TAG, "setDrmPropertyString: propertyName: " + propertyName + " value: " + value);
-
-        synchronized (mDrmLock) {
-
-            if ( !mActiveDrmScheme && !mDrmConfigAllowed ) {
-                Log.w(TAG, "setDrmPropertyString NoDrmSchemeException");
-                throw new NoDrmSchemeExceptionImpl(
-                        "setDrmPropertyString: Has to prepareDrm() first.");
-            }
-
-            try {
-                mDrmObj.setPropertyString(propertyName, value);
-            } catch ( Exception e ) {
-                Log.w(TAG, "setDrmPropertyString Exception " + e);
-                throw e;
-            }
-        }   // synchronized
-    }
-
-    /**
-     * Encapsulates the DRM properties of the source.
-     */
-    public static final class DrmInfoImpl extends DrmInfo {
-        private Map<UUID, byte[]> mapPssh;
-        private UUID[] supportedSchemes;
-
-        /**
-         * Returns the PSSH info of the data source for each supported DRM scheme.
-         */
-        @Override
-        public Map<UUID, byte[]> getPssh() {
-            return mapPssh;
-        }
-
-        /**
-         * Returns the intersection of the data source and the device DRM schemes.
-         * It effectively identifies the subset of the source's DRM schemes which
-         * are supported by the device too.
-         */
-        @Override
-        public List<UUID> getSupportedSchemes() {
-            return Arrays.asList(supportedSchemes);
-        }
-
-        private DrmInfoImpl(Map<UUID, byte[]> Pssh, UUID[] SupportedSchemes) {
-            mapPssh = Pssh;
-            supportedSchemes = SupportedSchemes;
-        }
-
-        private DrmInfoImpl(PlayerMessage msg) {
-            Log.v(TAG, "DrmInfoImpl(" + msg + ")");
-
-            Iterator<Value> in = msg.getValuesList().iterator();
-            byte[] pssh = in.next().getBytesValue().toByteArray();
-
-            Log.v(TAG, "DrmInfoImpl() PSSH: " + arrToHex(pssh));
-            mapPssh = parsePSSH(pssh, pssh.length);
-            Log.v(TAG, "DrmInfoImpl() PSSH: " + mapPssh);
-
-            int supportedDRMsCount = in.next().getInt32Value();
-            supportedSchemes = new UUID[supportedDRMsCount];
-            for (int i = 0; i < supportedDRMsCount; i++) {
-                byte[] uuid = new byte[16];
-                in.next().getBytesValue().copyTo(uuid, 0);
-
-                supportedSchemes[i] = bytesToUUID(uuid);
-
-                Log.v(TAG, "DrmInfoImpl() supportedScheme[" + i + "]: " +
-                      supportedSchemes[i]);
-            }
-
-            Log.v(TAG, "DrmInfoImpl() psshsize: " + pssh.length +
-                  " supportedDRMsCount: " + supportedDRMsCount);
-        }
-
-        private DrmInfoImpl makeCopy() {
-            return new DrmInfoImpl(this.mapPssh, this.supportedSchemes);
-        }
-
-        private String arrToHex(byte[] bytes) {
-            String out = "0x";
-            for (int i = 0; i < bytes.length; i++) {
-                out += String.format("%02x", bytes[i]);
-            }
-
-            return out;
-        }
-
-        private UUID bytesToUUID(byte[] uuid) {
-            long msb = 0, lsb = 0;
-            for (int i = 0; i < 8; i++) {
-                msb |= ( ((long)uuid[i]   & 0xff) << (8 * (7 - i)) );
-                lsb |= ( ((long)uuid[i+8] & 0xff) << (8 * (7 - i)) );
-            }
-
-            return new UUID(msb, lsb);
-        }
-
-        private Map<UUID, byte[]> parsePSSH(byte[] pssh, int psshsize) {
-            Map<UUID, byte[]> result = new HashMap<UUID, byte[]>();
-
-            final int UUID_SIZE = 16;
-            final int DATALEN_SIZE = 4;
-
-            int len = psshsize;
-            int numentries = 0;
-            int i = 0;
-
-            while (len > 0) {
-                if (len < UUID_SIZE) {
-                    Log.w(TAG, String.format("parsePSSH: len is too short to parse " +
-                                             "UUID: (%d < 16) pssh: %d", len, psshsize));
-                    return null;
-                }
-
-                byte[] subset = Arrays.copyOfRange(pssh, i, i + UUID_SIZE);
-                UUID uuid = bytesToUUID(subset);
-                i += UUID_SIZE;
-                len -= UUID_SIZE;
-
-                // get data length
-                if (len < 4) {
-                    Log.w(TAG, String.format("parsePSSH: len is too short to parse " +
-                                             "datalen: (%d < 4) pssh: %d", len, psshsize));
-                    return null;
-                }
-
-                subset = Arrays.copyOfRange(pssh, i, i+DATALEN_SIZE);
-                int datalen = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) ?
-                    ((subset[3] & 0xff) << 24) | ((subset[2] & 0xff) << 16) |
-                    ((subset[1] & 0xff) <<  8) |  (subset[0] & 0xff)          :
-                    ((subset[0] & 0xff) << 24) | ((subset[1] & 0xff) << 16) |
-                    ((subset[2] & 0xff) <<  8) |  (subset[3] & 0xff) ;
-                i += DATALEN_SIZE;
-                len -= DATALEN_SIZE;
-
-                if (len < datalen) {
-                    Log.w(TAG, String.format("parsePSSH: len is too short to parse " +
-                                             "data: (%d < %d) pssh: %d", len, datalen, psshsize));
-                    return null;
-                }
-
-                byte[] data = Arrays.copyOfRange(pssh, i, i+datalen);
-
-                // skip the data
-                i += datalen;
-                len -= datalen;
-
-                Log.v(TAG, String.format("parsePSSH[%d]: <%s, %s> pssh: %d",
-                                         numentries, uuid, arrToHex(data), psshsize));
-                numentries++;
-                result.put(uuid, data);
-            }
-
-            return result;
-        }
-
-    };  // DrmInfoImpl
-
-    /**
-     * Thrown when a DRM method is called before preparing a DRM scheme through prepareDrm().
-     * Extends MediaDrm.MediaDrmException
-     */
-    public static final class NoDrmSchemeExceptionImpl extends NoDrmSchemeException {
-        public NoDrmSchemeExceptionImpl(String detailMessage) {
-            super(detailMessage);
-        }
-    }
-
-    private native void _prepareDrm(@NonNull byte[] uuid, @NonNull byte[] drmSessionId);
-
-    // Modular DRM helpers
-
-    private void prepareDrm_createDrmStep(@NonNull UUID uuid)
-            throws UnsupportedSchemeException {
-        Log.v(TAG, "prepareDrm_createDrmStep: UUID: " + uuid);
-
-        try {
-            mDrmObj = new MediaDrm(uuid);
-            Log.v(TAG, "prepareDrm_createDrmStep: Created mDrmObj=" + mDrmObj);
-        } catch (Exception e) { // UnsupportedSchemeException
-            Log.e(TAG, "prepareDrm_createDrmStep: MediaDrm failed with " + e);
-            throw e;
-        }
-    }
-
-    private void prepareDrm_openSessionStep(@NonNull UUID uuid)
-            throws NotProvisionedException, ResourceBusyException {
-        Log.v(TAG, "prepareDrm_openSessionStep: uuid: " + uuid);
-
-        // TODO: don't need an open session for a future specialKeyReleaseDrm mode but we should do
-        // it anyway so it raises provisioning error if needed. We'd rather handle provisioning
-        // at prepareDrm/openSession rather than getDrmKeyRequest/provideDrmKeyResponse
-        try {
-            mDrmSessionId = mDrmObj.openSession();
-            Log.v(TAG, "prepareDrm_openSessionStep: mDrmSessionId=" + mDrmSessionId);
-
-            // Sending it down to native/mediaserver to create the crypto object
-            // This call could simply fail due to bad player state, e.g., after play().
-            _prepareDrm(getByteArrayFromUUID(uuid), mDrmSessionId);
-            Log.v(TAG, "prepareDrm_openSessionStep: _prepareDrm/Crypto succeeded");
-
-        } catch (Exception e) { //ResourceBusyException, NotProvisionedException
-            Log.e(TAG, "prepareDrm_openSessionStep: open/crypto failed with " + e);
-            throw e;
-        }
-
-    }
-
-    // Called from the native side
-    @SuppressWarnings("unused")
-    private static boolean setAudioOutputDeviceById(AudioTrack track, int deviceId) {
-        if (track == null) {
-            return false;
-        }
-
-        if (deviceId == 0) {
-            // Use default routing.
-            track.setPreferredDevice(null);
-            return true;
-        }
-
-        // TODO: Unhide AudioManager.getDevicesStatic.
-        AudioDeviceInfo[] outputDevices =
-                AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_OUTPUTS);
-
-        boolean success = false;
-        for (AudioDeviceInfo device : outputDevices) {
-            if (device.getId() == deviceId) {
-                track.setPreferredDevice(device);
-                success = true;
-                break;
-            }
-        }
-        return success;
-    }
-
-    // Instantiated from the native side
-    @SuppressWarnings("unused")
-    private static class StreamEventCallback extends AudioTrack.StreamEventCallback {
-        public long mJAudioTrackPtr;
-        public long mNativeCallbackPtr;
-        public long mUserDataPtr;
-
-        public StreamEventCallback(long jAudioTrackPtr, long nativeCallbackPtr, long userDataPtr) {
-            super();
-            mJAudioTrackPtr = jAudioTrackPtr;
-            mNativeCallbackPtr = nativeCallbackPtr;
-            mUserDataPtr = userDataPtr;
-        }
-
-        @Override
-        public void onTearDown(AudioTrack track) {
-            native_stream_event_onTearDown(mNativeCallbackPtr, mUserDataPtr);
-        }
-
-        @Override
-        public void onPresentationEnded(AudioTrack track) {
-            native_stream_event_onStreamPresentationEnd(mNativeCallbackPtr, mUserDataPtr);
-        }
-
-        @Override
-        public void onDataRequest(AudioTrack track, int size) {
-            native_stream_event_onStreamDataRequest(
-                    mJAudioTrackPtr, mNativeCallbackPtr, mUserDataPtr);
-        }
-    }
-
-    private class ProvisioningThread extends Thread {
-        public static final int TIMEOUT_MS = 60000;
-
-        private UUID uuid;
-        private String urlStr;
-        private Object drmLock;
-        private MediaPlayer2Impl mediaPlayer;
-        private int status;
-        public  int status() {
-            return status;
-        }
-
-        public ProvisioningThread initialize(MediaDrm.ProvisionRequest request,
-                                          UUID uuid, MediaPlayer2Impl mediaPlayer) {
-            // lock is held by the caller
-            drmLock = mediaPlayer.mDrmLock;
-            this.mediaPlayer = mediaPlayer;
-
-            urlStr = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData());
-            this.uuid = uuid;
-
-            status = PREPARE_DRM_STATUS_PREPARATION_ERROR;
-
-            Log.v(TAG, "HandleProvisioninig: Thread is initialised url: " + urlStr);
-            return this;
-        }
-
-        public void run() {
-
-            byte[] response = null;
-            boolean provisioningSucceeded = false;
-            try {
-                URL url = new URL(urlStr);
-                final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
-                try {
-                    connection.setRequestMethod("POST");
-                    connection.setDoOutput(false);
-                    connection.setDoInput(true);
-                    connection.setConnectTimeout(TIMEOUT_MS);
-                    connection.setReadTimeout(TIMEOUT_MS);
-
-                    connection.connect();
-                    response = readInputStreamFully(connection.getInputStream());
-
-                    Log.v(TAG, "HandleProvisioninig: Thread run: response " +
-                            response.length + " " + response);
-                } catch (Exception e) {
-                    status = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
-                    Log.w(TAG, "HandleProvisioninig: Thread run: connect " + e + " url: " + url);
-                } finally {
-                    connection.disconnect();
-                }
-            } catch (Exception e)   {
-                status = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
-                Log.w(TAG, "HandleProvisioninig: Thread run: openConnection " + e);
-            }
-
-            if (response != null) {
-                try {
-                    mDrmObj.provideProvisionResponse(response);
-                    Log.v(TAG, "HandleProvisioninig: Thread run: " +
-                            "provideProvisionResponse SUCCEEDED!");
-
-                    provisioningSucceeded = true;
-                } catch (Exception e) {
-                    status = PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR;
-                    Log.w(TAG, "HandleProvisioninig: Thread run: " +
-                            "provideProvisionResponse " + e);
-                }
-            }
-
-            boolean succeeded = false;
-
-            synchronized (drmLock) {
-                // continuing with prepareDrm
-                if (provisioningSucceeded) {
-                    succeeded = mediaPlayer.resumePrepareDrm(uuid);
-                    status = (succeeded) ?
-                            PREPARE_DRM_STATUS_SUCCESS :
-                            PREPARE_DRM_STATUS_PREPARATION_ERROR;
-                }
-                mediaPlayer.mDrmProvisioningInProgress = false;
-                mediaPlayer.mPrepareDrmInProgress = false;
-                if (!succeeded) {
-                    cleanDrmObj();  // cleaning up if it hasn't gone through while in the lock
-                }
-            }  // synchronized
-
-            // calling the callback outside the lock
-            sendDrmEvent(new DrmEventNotifier() {
-                @Override
-                public void notify(DrmEventCallback callback) {
-                    callback.onDrmPrepared(
-                            mediaPlayer, mCurrentDSD, status);
-                }
-            });
-
-            synchronized (mTaskLock) {
-                if (mCurrentTask != null
-                        && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE_DRM
-                        && mCurrentTask.mNeedToWaitForEventToComplete) {
-                    mCurrentTask = null;
-                    processPendingTask_l();
-                }
-            }
-        }
-
-        /**
-         * Returns a byte[] containing the remainder of 'in', closing it when done.
-         */
-        private byte[] readInputStreamFully(InputStream in) throws IOException {
-            try {
-                return readInputStreamFullyNoClose(in);
-            } finally {
-                in.close();
-            }
-        }
-
-        /**
-         * Returns a byte[] containing the remainder of 'in'.
-         */
-        private byte[] readInputStreamFullyNoClose(InputStream in) throws IOException {
-            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-            byte[] buffer = new byte[1024];
-            int count;
-            while ((count = in.read(buffer)) != -1) {
-                bytes.write(buffer, 0, count);
-            }
-            return bytes.toByteArray();
-        }
-    }   // ProvisioningThread
-
-    private int HandleProvisioninig(UUID uuid) {
-        synchronized (mDrmLock) {
-            if (mDrmProvisioningInProgress) {
-                Log.e(TAG, "HandleProvisioninig: Unexpected mDrmProvisioningInProgress");
-                return PREPARE_DRM_STATUS_PREPARATION_ERROR;
-            }
-
-            MediaDrm.ProvisionRequest provReq = mDrmObj.getProvisionRequest();
-            if (provReq == null) {
-                Log.e(TAG, "HandleProvisioninig: getProvisionRequest returned null.");
-                return PREPARE_DRM_STATUS_PREPARATION_ERROR;
-            }
-
-            Log.v(TAG, "HandleProvisioninig provReq " +
-                    " data: " + provReq.getData() + " url: " + provReq.getDefaultUrl());
-
-            // networking in a background thread
-            mDrmProvisioningInProgress = true;
-
-            mDrmProvisioningThread = new ProvisioningThread().initialize(provReq, uuid, this);
-            mDrmProvisioningThread.start();
-
-            return PREPARE_DRM_STATUS_SUCCESS;
-        }
-    }
-
-    private boolean resumePrepareDrm(UUID uuid) {
-        Log.v(TAG, "resumePrepareDrm: uuid: " + uuid);
-
-        // mDrmLock is guaranteed to be held
-        boolean success = false;
-        try {
-            // resuming
-            prepareDrm_openSessionStep(uuid);
-
-            mDrmUUID = uuid;
-            mActiveDrmScheme = true;
-
-            success = true;
-        } catch (Exception e) {
-            Log.w(TAG, "HandleProvisioninig: Thread run _prepareDrm resume failed with " + e);
-            // mDrmObj clean up is done by the caller
-        }
-
-        return success;
-    }
-
-    private void resetDrmState() {
-        synchronized (mDrmLock) {
-            Log.v(TAG, "resetDrmState: " +
-                    " mDrmInfoImpl=" + mDrmInfoImpl +
-                    " mDrmProvisioningThread=" + mDrmProvisioningThread +
-                    " mPrepareDrmInProgress=" + mPrepareDrmInProgress +
-                    " mActiveDrmScheme=" + mActiveDrmScheme);
-
-            mDrmInfoResolved = false;
-            mDrmInfoImpl = null;
-
-            if (mDrmProvisioningThread != null) {
-                // timeout; relying on HttpUrlConnection
-                try {
-                    mDrmProvisioningThread.join();
-                }
-                catch (InterruptedException e) {
-                    Log.w(TAG, "resetDrmState: ProvThread.join Exception " + e);
-                }
-                mDrmProvisioningThread = null;
-            }
-
-            mPrepareDrmInProgress = false;
-            mActiveDrmScheme = false;
-
-            cleanDrmObj();
-        }   // synchronized
-    }
-
-    private void cleanDrmObj() {
-        // the caller holds mDrmLock
-        Log.v(TAG, "cleanDrmObj: mDrmObj=" + mDrmObj + " mDrmSessionId=" + mDrmSessionId);
-
-        if (mDrmSessionId != null)    {
-            mDrmObj.closeSession(mDrmSessionId);
-            mDrmSessionId = null;
-        }
-        if (mDrmObj != null) {
-            mDrmObj.release();
-            mDrmObj = null;
-        }
-    }
-
-    private static final byte[] getByteArrayFromUUID(@NonNull UUID uuid) {
-        long msb = uuid.getMostSignificantBits();
-        long lsb = uuid.getLeastSignificantBits();
-
-        byte[] uuidBytes = new byte[16];
-        for (int i = 0; i < 8; ++i) {
-            uuidBytes[i] = (byte)(msb >>> (8 * (7 - i)));
-            uuidBytes[8 + i] = (byte)(lsb >>> (8 * (7 - i)));
-        }
-
-        return uuidBytes;
-    }
-
-    // Modular DRM end
-
-    /*
-     * Test whether a given video scaling mode is supported.
-     */
-    private boolean isVideoScalingModeSupported(int mode) {
-        return (mode == VIDEO_SCALING_MODE_SCALE_TO_FIT ||
-                mode == VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
-    }
-
-    private static class TimedTextUtil {
-        // These keys must be in sync with the keys in TextDescription2.h
-        private static final int KEY_START_TIME                     = 7; // int
-        private static final int KEY_STRUCT_TEXT_POS               = 14; // TextPos
-        private static final int KEY_STRUCT_TEXT                   = 16; // Text
-        private static final int KEY_GLOBAL_SETTING               = 101;
-        private static final int KEY_LOCAL_SETTING                = 102;
-
-        private static TimedText parsePlayerMessage(PlayerMessage playerMsg) {
-            if (playerMsg.getValuesCount() == 0) {
-                return null;
-            }
-
-            String textChars = null;
-            Rect textBounds = null;
-            Iterator<Value> in = playerMsg.getValuesList().iterator();
-            int type = in.next().getInt32Value();
-            if (type == KEY_LOCAL_SETTING) {
-                type = in.next().getInt32Value();
-                if (type != KEY_START_TIME) {
-                    return null;
-                }
-                int startTimeMs = in.next().getInt32Value();
-
-                type = in.next().getInt32Value();
-                if (type != KEY_STRUCT_TEXT) {
-                    return null;
-                }
-
-                byte[] text = in.next().getBytesValue().toByteArray();
-                if (text == null || text.length == 0) {
-                    textChars = null;
-                } else {
-                    textChars = new String(text);
-                }
-
-            } else if (type != KEY_GLOBAL_SETTING) {
-                Log.w(TAG, "Invalid timed text key found: " + type);
-                return null;
-            }
-            if (in.hasNext()) {
-                type = in.next().getInt32Value();
-                if (type == KEY_STRUCT_TEXT_POS) {
-                    int top = in.next().getInt32Value();
-                    int left = in.next().getInt32Value();
-                    int bottom = in.next().getInt32Value();
-                    int right = in.next().getInt32Value();
-                    textBounds = new Rect(left, top, right, bottom);
-                }
-            }
-            return new TimedText(textChars, textBounds);
-        }
-    }
-
-    private abstract class Task implements Runnable {
-        private final int mMediaCallType;
-        private final boolean mNeedToWaitForEventToComplete;
-        private DataSourceDesc mDSD;
-
-        public Task (int mediaCallType, boolean needToWaitForEventToComplete) {
-            mMediaCallType = mediaCallType;
-            mNeedToWaitForEventToComplete = needToWaitForEventToComplete;
-        }
-
-        abstract void process() throws IOException, NoDrmSchemeException;
-
-        @Override
-        public void run() {
-            int status = CALL_STATUS_NO_ERROR;
-            try {
-                if (mMediaCallType != CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED
-                        && getState() == PLAYER_STATE_ERROR) {
-                    status = CALL_STATUS_INVALID_OPERATION;
-                } else {
-                    if (mMediaCallType == CALL_COMPLETED_SEEK_TO) {
-                        synchronized (mTaskLock) {
-                            if (!mPendingTasks.isEmpty()) {
-                                Task nextTask = mPendingTasks.get(0);
-                                if (nextTask.mMediaCallType == mMediaCallType) {
-                                    throw new CommandSkippedException(
-                                            "consecutive seekTo is skipped except last one");
-                                }
-                            }
-                        }
-                    }
-                    process();
-                }
-            } catch (IllegalStateException e) {
-                status = CALL_STATUS_INVALID_OPERATION;
-            } catch (IllegalArgumentException e) {
-                status = CALL_STATUS_BAD_VALUE;
-            } catch (SecurityException e) {
-                status = CALL_STATUS_PERMISSION_DENIED;
-            } catch (IOException e) {
-                status = CALL_STATUS_ERROR_IO;
-            } catch (NoDrmSchemeException e) {
-                status = CALL_STATUS_NO_DRM_SCHEME;
-            } catch (CommandSkippedException e) {
-                status = CALL_STATUS_SKIPPED;
-            } catch (Exception e) {
-                status = CALL_STATUS_ERROR_UNKNOWN;
-            }
-            synchronized (mSrcLock) {
-                mDSD = mCurrentDSD;
-            }
-
-            // TODO: Make native implementations asynchronous and let them send notifications.
-            if (!mNeedToWaitForEventToComplete || status != CALL_STATUS_NO_ERROR) {
-
-                sendCompleteNotification(status);
-
-                synchronized (mTaskLock) {
-                    mCurrentTask = null;
-                    processPendingTask_l();
-                }
-            }
-        }
-
-        private void sendCompleteNotification(int status) {
-            // In {@link #notifyWhenCommandLabelReached} case, a separate callback
-            // {@link #onCommandLabelReached} is already called in {@code process()}.
-            // CALL_COMPLETED_PREPARE_DRM is sent via DrmEventCallback#onDrmPrepared
-            if (mMediaCallType == CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED
-                    || mMediaCallType == CALL_COMPLETED_PREPARE_DRM) {
-                return;
-            }
-            sendEvent(new EventNotifier() {
-                @Override
-                public void notify(EventCallback callback) {
-                    callback.onCallCompleted(
-                            MediaPlayer2Impl.this, mDSD, mMediaCallType, status);
-                }
-            });
-        }
-    };
-
-    private final class CommandSkippedException extends RuntimeException {
-        public CommandSkippedException(String detailMessage) {
-            super(detailMessage);
-        }
-    };
-}
diff --git a/media/java/android/media/MediaPlayer2Utils.java b/media/java/android/media/MediaPlayer2Utils.java
new file mode 100644
index 0000000..c6dee22
--- /dev/null
+++ b/media/java/android/media/MediaPlayer2Utils.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * Helper class used by native code to reduce JNI calls from native side.
+ * @hide
+ */
+public class MediaPlayer2Utils {
+    /**
+     * Returns whether audio offloading is supported for the given audio format.
+     *
+     * @param encoding the type of encoding defined in {@link AudioFormat}
+     * @param sampleRate the sampling rate of the stream
+     * @param channelMask the channel mask defined in {@link AudioFormat}
+     */
+    // @CalledByNative
+    public static boolean isOffloadedAudioPlaybackSupported(
+            int encoding, int sampleRate, int channelMask) {
+        final AudioFormat format = new AudioFormat.Builder()
+                .setEncoding(encoding)
+                .setSampleRate(sampleRate)
+                .setChannelMask(channelMask)
+                .build();
+        return AudioManager.isOffloadedPlaybackSupported(format);
+    }
+}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 0cde01e..3a64f43 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -1632,7 +1632,7 @@
             selectionArgs = new String[] { path };
             c = mMediaProvider.query(mFilesUriNoNotify, FILES_PRESCAN_PROJECTION,
                     where, selectionArgs, null, null);
-            if (c.moveToFirst()) {
+            if (c != null && c.moveToFirst()) {
                 long rowId = c.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
                 long lastModified = c.getLong(FILES_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);
                 int format = c.getInt(FILES_PRESCAN_FORMAT_COLUMN_INDEX);
diff --git a/media/java/android/media/RoutingDelegate.java b/media/java/android/media/RoutingDelegate.java
new file mode 100644
index 0000000..2359813
--- /dev/null
+++ b/media/java/android/media/RoutingDelegate.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.os.Handler;
+
+class RoutingDelegate implements AudioRouting.OnRoutingChangedListener {
+    private AudioRouting mAudioRouting;
+    private AudioRouting.OnRoutingChangedListener mOnRoutingChangedListener;
+    private Handler mHandler;
+
+    RoutingDelegate(final AudioRouting audioRouting,
+                    final AudioRouting.OnRoutingChangedListener listener,
+                    Handler handler) {
+        mAudioRouting = audioRouting;
+        mOnRoutingChangedListener = listener;
+        mHandler = handler;
+    }
+
+    public AudioRouting.OnRoutingChangedListener getListener() {
+        return mOnRoutingChangedListener;
+    }
+
+    public Handler getHandler() {
+        return mHandler;
+    }
+
+    @Override
+    public void onRoutingChanged(AudioRouting router) {
+        if (mOnRoutingChangedListener != null) {
+            mOnRoutingChangedListener.onRoutingChanged(mAudioRouting);
+        }
+    }
+}
diff --git a/media/java/android/media/VideoSize.java b/media/java/android/media/VideoSize.java
new file mode 100644
index 0000000..7e5cb1f
--- /dev/null
+++ b/media/java/android/media/VideoSize.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * Immutable class for describing width and height dimensions.
+ *
+ * @hide
+ */
+public final class VideoSize {
+    /**
+     * Create a new immutable VideoSize instance.
+     *
+     * @param width The width of the video size
+     * @param height The height of the video size
+     */
+    public VideoSize(int width, int height) {
+        mWidth = width;
+        mHeight = height;
+    }
+
+    /**
+     * Get the width of the video size
+     * @return width
+     */
+    public int getWidth() {
+        return mWidth;
+    }
+
+    /**
+     * Get the height of the video size
+     * @return height
+     */
+    public int getHeight() {
+        return mHeight;
+    }
+
+    /**
+     * Check if this video size is equal to another video size.
+     * <p>
+     * Two video sizes are equal if and only if both their widths and heights are
+     * equal.
+     * </p>
+     * <p>
+     * A video size object is never equal to any other type of object.
+     * </p>
+     *
+     * @return {@code true} if the objects were equal, {@code false} otherwise
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == null) {
+            return false;
+        }
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof VideoSize) {
+            VideoSize other = (VideoSize) obj;
+            return mWidth == other.mWidth && mHeight == other.mHeight;
+        }
+        return false;
+    }
+
+    /**
+     * Return the video size represented as a string with the format {@code "WxH"}
+     *
+     * @return string representation of the video size
+     */
+    @Override
+    public String toString() {
+        return mWidth + "x" + mHeight;
+    }
+
+    private final int mWidth;
+    private final int mHeight;
+}
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index cf7bf19..fa69062 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -24,7 +24,6 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.UnsupportedAppUsage;
-import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
 import android.hardware.soundtrigger.SoundTrigger;
@@ -367,15 +366,15 @@
     }
 
     /**
-     * Synchronously get state of the indicated model.  The model state is returned as
-     * a recognition event, or null if the model is not loaded, or if this method
-     * is not supported.
+     * Asynchronously get state of the indicated model.  The model state is returned as
+     * a recognition event in the callback that was registered in the startRecognition
+     * method.
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
-    public SoundTrigger.RecognitionEvent getModelState(UUID soundModelId) {
+    public int getModelState(UUID soundModelId) {
         if (soundModelId == null) {
-            return null;
+            return STATUS_ERROR;
         }
         try {
             return mSoundTriggerService.getModelState(new ParcelUuid(soundModelId));
diff --git a/media/java/android/media/update/MediaControlView2Provider.java b/media/java/android/media/update/MediaControlView2Provider.java
deleted file mode 100644
index 8e69653..0000000
--- a/media/java/android/media/update/MediaControlView2Provider.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.update;
-
-import android.media.SessionToken2;
-import android.media.session.MediaController;
-import android.util.AttributeSet;
-import android.widget.MediaControlView2;
-
-/**
- * Interface for connecting the public API to an updatable implementation.
- *
- * Each instance object is connected to one corresponding updatable object which implements the
- * runtime behavior of that class. There should a corresponding provider method for all public
- * methods.
- *
- * All methods behave as per their namesake in the public API.
- *
- * @see android.widget.MediaControlView2
- *
- * @hide
- */
-// TODO: @SystemApi
-public interface MediaControlView2Provider extends ViewGroupProvider {
-    void initialize(AttributeSet attrs, int defStyleAttr, int defStyleRes);
-
-    void setMediaSessionToken_impl(SessionToken2 token);
-    void setOnFullScreenListener_impl(MediaControlView2.OnFullScreenListener l);
-    /**
-     * @hide TODO: remove
-     */
-    void setController_impl(MediaController controller);
-    /**
-     * @hide
-     */
-    void setButtonVisibility_impl(int button, int visibility);
-    void requestPlayButtonFocus_impl();
-}
diff --git a/media/java/android/media/update/StaticProvider.java b/media/java/android/media/update/StaticProvider.java
index 8687b80..2bc17a9 100644
--- a/media/java/android/media/update/StaticProvider.java
+++ b/media/java/android/media/update/StaticProvider.java
@@ -16,7 +16,6 @@
 
 package android.media.update;
 
-import android.annotation.Nullable;
 import android.app.Notification;
 import android.content.Context;
 import android.media.MediaBrowser2;
@@ -48,9 +47,6 @@
 import android.media.update.MediaSessionService2Provider.MediaNotificationProvider;
 import android.os.Bundle;
 import android.os.IInterface;
-import android.util.AttributeSet;
-import android.widget.MediaControlView2;
-import android.widget.VideoView2;
 
 import java.util.concurrent.Executor;
 
@@ -62,13 +58,6 @@
  * @hide
  */
 public interface StaticProvider {
-    MediaControlView2Provider createMediaControlView2(MediaControlView2 instance,
-            ViewGroupProvider superProvider, ViewGroupProvider privateProvider,
-            @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes);
-    VideoView2Provider createVideoView2(VideoView2 instance,
-            ViewGroupProvider superProvider, ViewGroupProvider privateProvider,
-            @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes);
-
     CommandProvider createMediaSession2Command(SessionCommand2 instance,
             int commandCode, String action, Bundle extra);
     SessionCommand2 fromBundle_MediaSession2Command(Bundle bundle);
diff --git a/media/java/android/media/update/VideoView2Provider.java b/media/java/android/media/update/VideoView2Provider.java
deleted file mode 100644
index 27b436f..0000000
--- a/media/java/android/media/update/VideoView2Provider.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.update;
-
-import android.annotation.SystemApi;
-import android.media.AudioAttributes;
-import android.media.DataSourceDesc;
-import android.media.MediaItem2;
-import android.media.MediaMetadata2;
-import android.media.MediaPlayerBase;
-import android.media.SessionToken2;
-import android.media.session.MediaController;
-import android.media.session.PlaybackState;
-import android.media.session.MediaSession;
-import android.net.Uri;
-import android.util.AttributeSet;
-import android.widget.MediaControlView2;
-import android.widget.VideoView2;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executor;
-
-/**
- * Interface for connecting the public API to an updatable implementation.
- *
- * Each instance object is connected to one corresponding updatable object which implements the
- * runtime behavior of that class. There should a corresponding provider method for all public
- * methods.
- *
- * All methods behave as per their namesake in the public API.
- *
- * @see android.widget.VideoView2
- *
- * @hide
- */
-// TODO @SystemApi
-public interface VideoView2Provider extends ViewGroupProvider {
-    void initialize(AttributeSet attrs, int defStyleAttr, int defStyleRes);
-
-    void setMediaControlView2_impl(MediaControlView2 mediaControlView, long intervalMs);
-    void setMediaMetadata_impl(MediaMetadata2 metadata);
-    /**
-     * @hide TODO: remove
-     */
-    MediaController getMediaController_impl();
-    SessionToken2 getMediaSessionToken_impl();
-    MediaControlView2 getMediaControlView2_impl();
-    MediaMetadata2 getMediaMetadata_impl();
-    void setSubtitleEnabled_impl(boolean enable);
-    boolean isSubtitleEnabled_impl();
-    // TODO: remove setSpeed_impl once MediaController2 is ready.
-    void setSpeed_impl(float speed);
-    void setAudioFocusRequest_impl(int focusGain);
-    void setAudioAttributes_impl(AudioAttributes attributes);
-    void setVideoPath_impl(String path);
-    /**
-     * @hide TODO: remove
-     */
-    void setVideoUri_impl(Uri uri);
-    /**
-     * @hide TODO: remove
-     */
-    void setVideoUri_impl(Uri uri, Map<String, String> headers);
-    void setMediaItem_impl(MediaItem2 mediaItem);
-    void setDataSource_impl(DataSourceDesc dsd);
-    void setViewType_impl(int viewType);
-    int getViewType_impl();
-    /**
-     * @hide TODO: remove
-     */
-    void setCustomActions_impl(List<PlaybackState.CustomAction> actionList,
-            Executor executor, VideoView2.OnCustomActionListener listener);
-    /**
-     * @hide
-     */
-    @VisibleForTesting
-    void setOnViewTypeChangedListener_impl(VideoView2.OnViewTypeChangedListener l);
-    /**
-     * @hide TODO: remove
-     */
-    void setFullScreenRequestListener_impl(VideoView2.OnFullScreenRequestListener l);
-}
diff --git a/media/java/android/media/update/ViewGroupHelper.java b/media/java/android/media/update/ViewGroupHelper.java
deleted file mode 100644
index 6b4f15d..0000000
--- a/media/java/android/media/update/ViewGroupHelper.java
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.update;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * Helper class for connecting the public API to an updatable implementation.
- *
- * @see ViewGroupProvider
- *
- * @hide
- */
-public abstract class ViewGroupHelper<T extends ViewGroupProvider> extends ViewGroup {
-    /** @hide */
-    final public T mProvider;
-
-    /** @hide */
-    public ViewGroupHelper(ProviderCreator<T> creator,
-            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-
-        mProvider = creator.createProvider(this, new SuperProvider(),
-                new PrivateProvider());
-    }
-
-    /** @hide */
-    // TODO @SystemApi
-    public T getProvider() {
-        return mProvider;
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        mProvider.onAttachedToWindow_impl();
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        mProvider.onDetachedFromWindow_impl();
-    }
-
-    @Override
-    public CharSequence getAccessibilityClassName() {
-        return mProvider.getAccessibilityClassName_impl();
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        return mProvider.onTouchEvent_impl(ev);
-    }
-
-    @Override
-    public boolean onTrackballEvent(MotionEvent ev) {
-        return mProvider.onTrackballEvent_impl(ev);
-    }
-
-    @Override
-    public void onFinishInflate() {
-        mProvider.onFinishInflate_impl();
-    }
-
-    @Override
-    public void setEnabled(boolean enabled) {
-        mProvider.setEnabled_impl(enabled);
-    }
-
-    @Override
-    public void onVisibilityAggregated(boolean isVisible) {
-        mProvider.onVisibilityAggregated_impl(isVisible);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        mProvider.onLayout_impl(changed, left, top, right, bottom);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        mProvider.onMeasure_impl(widthMeasureSpec, heightMeasureSpec);
-    }
-
-    @Override
-    protected int getSuggestedMinimumWidth() {
-        return mProvider.getSuggestedMinimumWidth_impl();
-    }
-
-    @Override
-    protected int getSuggestedMinimumHeight() {
-        return mProvider.getSuggestedMinimumHeight_impl();
-    }
-
-    // setMeasuredDimension is final
-
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent ev) {
-        return mProvider.dispatchTouchEvent_impl(ev);
-    }
-
-    @Override
-    protected boolean checkLayoutParams(LayoutParams p) {
-        return mProvider.checkLayoutParams_impl(p);
-    }
-
-    @Override
-    protected LayoutParams generateDefaultLayoutParams() {
-        return mProvider.generateDefaultLayoutParams_impl();
-    }
-
-    @Override
-    public LayoutParams generateLayoutParams(AttributeSet attrs) {
-        return mProvider.generateLayoutParams_impl(attrs);
-    }
-
-    @Override
-    protected LayoutParams generateLayoutParams(LayoutParams lp) {
-        return mProvider.generateLayoutParams_impl(lp);
-    }
-
-    @Override
-    public boolean shouldDelayChildPressedState() {
-        return mProvider.shouldDelayChildPressedState_impl();
-    }
-
-    @Override
-    protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
-            int parentHeightMeasureSpec, int heightUsed) {
-        mProvider.measureChildWithMargins_impl(child,
-                parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
-    }
-
-    /** @hide */
-    public class SuperProvider implements ViewGroupProvider {
-        @Override
-        public CharSequence getAccessibilityClassName_impl() {
-            return ViewGroupHelper.super.getAccessibilityClassName();
-        }
-
-        @Override
-        public boolean onTouchEvent_impl(MotionEvent ev) {
-            return ViewGroupHelper.super.onTouchEvent(ev);
-        }
-
-        @Override
-        public boolean onTrackballEvent_impl(MotionEvent ev) {
-            return ViewGroupHelper.super.onTrackballEvent(ev);
-        }
-
-        @Override
-        public void onFinishInflate_impl() {
-            ViewGroupHelper.super.onFinishInflate();
-        }
-
-        @Override
-        public void setEnabled_impl(boolean enabled) {
-            ViewGroupHelper.super.setEnabled(enabled);
-        }
-
-        @Override
-        public void onAttachedToWindow_impl() {
-            ViewGroupHelper.super.onAttachedToWindow();
-        }
-
-        @Override
-        public void onDetachedFromWindow_impl() {
-            ViewGroupHelper.super.onDetachedFromWindow();
-        }
-
-        @Override
-        public void onVisibilityAggregated_impl(boolean isVisible) {
-            ViewGroupHelper.super.onVisibilityAggregated(isVisible);
-        }
-
-        @Override
-        public void onLayout_impl(boolean changed, int left, int top, int right, int bottom) {
-            // abstract method; no super
-        }
-
-        @Override
-        public void onMeasure_impl(int widthMeasureSpec, int heightMeasureSpec) {
-            ViewGroupHelper.super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        }
-
-        @Override
-        public int getSuggestedMinimumWidth_impl() {
-            return ViewGroupHelper.super.getSuggestedMinimumWidth();
-        }
-
-        @Override
-        public int getSuggestedMinimumHeight_impl() {
-            return ViewGroupHelper.super.getSuggestedMinimumHeight();
-        }
-
-        @Override
-        public void setMeasuredDimension_impl(int measuredWidth, int measuredHeight) {
-            ViewGroupHelper.super.setMeasuredDimension(measuredWidth, measuredHeight);
-        }
-
-        @Override
-        public boolean dispatchTouchEvent_impl(MotionEvent ev) {
-            return ViewGroupHelper.super.dispatchTouchEvent(ev);
-        }
-
-        @Override
-        public boolean checkLayoutParams_impl(LayoutParams p) {
-            return ViewGroupHelper.super.checkLayoutParams(p);
-        }
-
-        @Override
-        public LayoutParams generateDefaultLayoutParams_impl() {
-            return ViewGroupHelper.super.generateDefaultLayoutParams();
-        }
-
-        @Override
-        public LayoutParams generateLayoutParams_impl(AttributeSet attrs) {
-            return ViewGroupHelper.super.generateLayoutParams(attrs);
-        }
-
-        @Override
-        public LayoutParams generateLayoutParams_impl(LayoutParams lp) {
-            return ViewGroupHelper.super.generateLayoutParams(lp);
-        }
-
-        @Override
-        public boolean shouldDelayChildPressedState_impl() {
-            return ViewGroupHelper.super.shouldDelayChildPressedState();
-        }
-
-        @Override
-        public void measureChildWithMargins_impl(View child,
-                int parentWidthMeasureSpec, int widthUsed,
-                int parentHeightMeasureSpec, int heightUsed) {
-            ViewGroupHelper.super.measureChildWithMargins(child,
-                    parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
-        }
-    }
-
-    /** @hide */
-    public class PrivateProvider implements ViewGroupProvider {
-        @Override
-        public CharSequence getAccessibilityClassName_impl() {
-            return ViewGroupHelper.this.getAccessibilityClassName();
-        }
-
-        @Override
-        public boolean onTouchEvent_impl(MotionEvent ev) {
-            return ViewGroupHelper.this.onTouchEvent(ev);
-        }
-
-        @Override
-        public boolean onTrackballEvent_impl(MotionEvent ev) {
-            return ViewGroupHelper.this.onTrackballEvent(ev);
-        }
-
-        @Override
-        public void onFinishInflate_impl() {
-            ViewGroupHelper.this.onFinishInflate();
-        }
-
-        @Override
-        public void setEnabled_impl(boolean enabled) {
-            ViewGroupHelper.this.setEnabled(enabled);
-        }
-
-        @Override
-        public void onAttachedToWindow_impl() {
-            ViewGroupHelper.this.onAttachedToWindow();
-        }
-
-        @Override
-        public void onDetachedFromWindow_impl() {
-            ViewGroupHelper.this.onDetachedFromWindow();
-        }
-
-        @Override
-        public void onVisibilityAggregated_impl(boolean isVisible) {
-            ViewGroupHelper.this.onVisibilityAggregated(isVisible);
-        }
-
-        @Override
-        public void onLayout_impl(boolean changed, int left, int top, int right, int bottom) {
-            ViewGroupHelper.this.onLayout(changed, left, top, right, bottom);
-        }
-
-        @Override
-        public void onMeasure_impl(int widthMeasureSpec, int heightMeasureSpec) {
-            ViewGroupHelper.this.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        }
-
-        @Override
-        public int getSuggestedMinimumWidth_impl() {
-            return ViewGroupHelper.this.getSuggestedMinimumWidth();
-        }
-
-        @Override
-        public int getSuggestedMinimumHeight_impl() {
-            return ViewGroupHelper.this.getSuggestedMinimumHeight();
-        }
-
-        @Override
-        public void setMeasuredDimension_impl(int measuredWidth, int measuredHeight) {
-            ViewGroupHelper.this.setMeasuredDimension(measuredWidth, measuredHeight);
-        }
-
-        @Override
-        public boolean dispatchTouchEvent_impl(MotionEvent ev) {
-            return ViewGroupHelper.this.dispatchTouchEvent(ev);
-        }
-
-        @Override
-        public boolean checkLayoutParams_impl(LayoutParams p) {
-            return ViewGroupHelper.this.checkLayoutParams(p);
-        }
-
-        @Override
-        public LayoutParams generateDefaultLayoutParams_impl() {
-            return ViewGroupHelper.this.generateDefaultLayoutParams();
-        }
-
-        @Override
-        public LayoutParams generateLayoutParams_impl(AttributeSet attrs) {
-            return ViewGroupHelper.this.generateLayoutParams(attrs);
-        }
-
-        @Override
-        public LayoutParams generateLayoutParams_impl(LayoutParams lp) {
-            return ViewGroupHelper.this.generateLayoutParams(lp);
-        }
-
-        @Override
-        public boolean shouldDelayChildPressedState_impl() {
-            return ViewGroupHelper.this.shouldDelayChildPressedState();
-        }
-
-        @Override
-        public void measureChildWithMargins_impl(View child,
-                int parentWidthMeasureSpec, int widthUsed,
-                int parentHeightMeasureSpec, int heightUsed) {
-            ViewGroupHelper.this.measureChildWithMargins(child,
-                    parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
-        }
-    }
-
-        /** @hide */
-    @FunctionalInterface
-    public interface ProviderCreator<T extends ViewGroupProvider> {
-        T createProvider(ViewGroupHelper<T> instance, ViewGroupProvider superProvider,
-                ViewGroupProvider privateProvider);
-    }
-}
diff --git a/media/java/android/media/update/ViewGroupProvider.java b/media/java/android/media/update/ViewGroupProvider.java
deleted file mode 100644
index 67e8cea..0000000
--- a/media/java/android/media/update/ViewGroupProvider.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media.update;
-
-import android.annotation.SystemApi;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-
-/**
- * Interface for connecting the public API to an updatable implementation.
- *
- * Each instance object is connected to one corresponding updatable object which implements the
- * runtime behavior of that class. There should a corresponding provider method for all public
- * methods.
- *
- * All methods behave as per their namesake in the public API.
- *
- * @see android.view.View
- *
- * @hide
- */
-// TODO @SystemApi
-public interface ViewGroupProvider {
-    // View methods
-    void onAttachedToWindow_impl();
-    void onDetachedFromWindow_impl();
-    CharSequence getAccessibilityClassName_impl();
-    boolean onTouchEvent_impl(MotionEvent ev);
-    boolean onTrackballEvent_impl(MotionEvent ev);
-    void onFinishInflate_impl();
-    void setEnabled_impl(boolean enabled);
-    void onVisibilityAggregated_impl(boolean isVisible);
-    void onLayout_impl(boolean changed, int left, int top, int right, int bottom);
-    void onMeasure_impl(int widthMeasureSpec, int heightMeasureSpec);
-    int getSuggestedMinimumWidth_impl();
-    int getSuggestedMinimumHeight_impl();
-    void setMeasuredDimension_impl(int measuredWidth, int measuredHeight);
-    boolean dispatchTouchEvent_impl(MotionEvent ev);
-
-    // ViewGroup methods
-    boolean checkLayoutParams_impl(LayoutParams p);
-    LayoutParams generateDefaultLayoutParams_impl();
-    LayoutParams generateLayoutParams_impl(AttributeSet attrs);
-    LayoutParams generateLayoutParams_impl(LayoutParams lp);
-    boolean shouldDelayChildPressedState_impl();
-    void measureChildWithMargins_impl(View child, int parentWidthMeasureSpec, int widthUsed,
-        int parentHeightMeasureSpec, int heightUsed);
-
-    // ViewManager methods
-    // ViewParent methods
-}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 0f531c9..faf4301 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -97,7 +97,6 @@
     shared_libs: [
         "android.hardware.cas@1.0",  // for CasManager. VNDK???
         "android.hardware.cas.native@1.0",  // CasManager. VNDK???
-        "libaudioclient",  // for use of AudioTrack, AudioSystem. to be removed
         "libbinder",
         "libgui",  // for VideoFrameScheduler
         "libhidlallocatorutils",
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 7cf8828..be71dad5 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -161,6 +161,12 @@
     jint kSecurityLevelHwSecureAll;
 } gSecurityLevels;
 
+struct OfflineLicenseState {
+    jint kOfflineLicenseStateUsable;
+    jint kOfflineLicenseStateInactive;
+    jint kOfflineLicenseStateUnknown;
+} gOfflineLicenseStates;
+
 
 struct fields_t {
     jfieldID context;
@@ -543,7 +549,7 @@
     import jav.util.Iterator;
 
     HashMap<k, v> hm;
-    Set<Entry<k, v> > s = hm.entrySet();
+    Set<Entry<k, v>> s = hm.entrySet();
     Iterator i = s.iterator();
     Entry e = s.next();
 */
@@ -613,10 +619,10 @@
 }
 
 static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
-                                                   List<Vector<uint8_t> > list) {
+                                                   List<Vector<uint8_t>> list) {
     jclass clazz = gFields.arraylistClassId;
     jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
-    List<Vector<uint8_t> >::iterator iter = list.begin();
+    List<Vector<uint8_t>>::iterator iter = list.begin();
     while (iter != list.end()) {
         jbyteArray byteArray = VectorToJByteArray(env, *iter);
         env->CallBooleanMethod(arrayList, gFields.arraylist.add, byteArray);
@@ -740,6 +746,15 @@
     GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_ALL", "I");
     gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
 
+    GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_USABLE", "I");
+    gOfflineLicenseStates.kOfflineLicenseStateUsable = env->GetStaticIntField(clazz, field);
+    GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_INACTIVE", "I");
+    gOfflineLicenseStates.kOfflineLicenseStateInactive = env->GetStaticIntField(clazz, field);
+    GET_STATIC_FIELD_ID(field, clazz, "OFFLINE_LICENSE_STATE_UNKNOWN", "I");
+    gOfflineLicenseStates.kOfflineLicenseStateUnknown = env->GetStaticIntField(clazz, field);
+
+    GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_HW_SECURE_CRYPTO", "I");
+
     jmethodID getMaxSecurityLevel;
     GET_STATIC_METHOD_ID(getMaxSecurityLevel, clazz, "getMaxSecurityLevel", "()I");
     gSecurityLevels.kSecurityLevelMax = env->CallStaticIntMethod(clazz, getMaxSecurityLevel);
@@ -890,9 +905,7 @@
         JNIEnv *env, jobject thiz, jint jlevel) {
     sp<IDrm> drm = GetDrm(env, thiz);
 
-    if (drm == NULL) {
-        jniThrowException(env, "java/lang/IllegalStateException",
-                          "MediaDrm obj is null");
+    if (!CheckDrm(env, drm)) {
         return NULL;
     }
 
@@ -1070,6 +1083,10 @@
     JNIEnv *env, jobject thiz, jbyteArray jkeysetId) {
     sp<IDrm> drm = GetDrm(env, thiz);
 
+    if (!CheckDrm(env, drm)) {
+        return;
+    }
+
     if (jkeysetId == NULL) {
         jniThrowException(env, "java/lang/IllegalArgumentException",
                           "keySetId is null");
@@ -1216,7 +1233,7 @@
         return NULL;
     }
 
-    List<Vector<uint8_t> > secureStops;
+    List<Vector<uint8_t>> secureStops;
 
     status_t err = drm->getSecureStops(secureStops);
 
@@ -1231,13 +1248,11 @@
     JNIEnv *env, jobject thiz) {
     sp<IDrm> drm = GetDrm(env, thiz);
 
-    if (drm == NULL) {
-        jniThrowException(env, "java/lang/IllegalStateException",
-                          "MediaDrm obj is null");
+    if (!CheckDrm(env, drm)) {
         return NULL;
     }
 
-    List<Vector<uint8_t> > secureStopIds;
+    List<Vector<uint8_t>> secureStopIds;
 
     status_t err = drm->getSecureStopIds(secureStopIds);
 
@@ -1286,9 +1301,7 @@
         JNIEnv *env, jobject thiz, jbyteArray ssid) {
     sp<IDrm> drm = GetDrm(env, thiz);
 
-    if (drm == NULL) {
-        jniThrowException(env, "java/lang/IllegalStateException",
-                          "MediaDrm obj is null");
+    if (!CheckDrm(env, drm)) {
         return;
     }
 
@@ -1437,6 +1450,65 @@
     }
 }
 
+static jobject android_media_MediaDrm_getOfflineLicenseKeySetIds(
+    JNIEnv *env, jobject thiz) {
+    sp<IDrm> drm = GetDrm(env, thiz);
+
+    if (!CheckDrm(env, drm)) {
+        return NULL;
+    }
+
+    List<Vector<uint8_t> > keySetIds;
+
+    status_t err = drm->getOfflineLicenseKeySetIds(keySetIds);
+
+    if (throwExceptionAsNecessary(env, err, "Failed to get offline key set Ids")) {
+        return NULL;
+    }
+
+    return ListOfVectorsToArrayListOfByteArray(env, keySetIds);
+}
+
+static void android_media_MediaDrm_removeOfflineLicense(
+        JNIEnv *env, jobject thiz, jbyteArray keySetId) {
+    sp<IDrm> drm = GetDrm(env, thiz);
+
+    if (!CheckDrm(env, drm)) {
+        return;
+    }
+
+    status_t err = drm->removeOfflineLicense(JByteArrayToVector(env, keySetId));
+
+    throwExceptionAsNecessary(env, err, "Failed to remove offline license");
+}
+
+static jint android_media_MediaDrm_getOfflineLicenseState(JNIEnv *env,
+        jobject thiz, jbyteArray jkeySetId) {
+    sp<IDrm> drm = GetDrm(env, thiz);
+
+    if (!CheckDrm(env, drm)) {
+        return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
+    }
+
+    Vector<uint8_t> keySetId(JByteArrayToVector(env, jkeySetId));
+
+    DrmPlugin::OfflineLicenseState state = DrmPlugin::kOfflineLicenseStateUnknown;
+
+    status_t err = drm->getOfflineLicenseState(keySetId, &state);
+
+    if (throwExceptionAsNecessary(env, err, "Failed to get offline license state")) {
+        return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
+    }
+
+    switch(state) {
+    case DrmPlugin::kOfflineLicenseStateUsable:
+        return gOfflineLicenseStates.kOfflineLicenseStateUsable;
+    case DrmPlugin::kOfflineLicenseStateInactive:
+        return gOfflineLicenseStates.kOfflineLicenseStateInactive;
+    default:
+        return gOfflineLicenseStates.kOfflineLicenseStateUnknown;
+    }
+}
 
 static jstring android_media_MediaDrm_getPropertyString(
     JNIEnv *env, jobject thiz, jstring jname) {
@@ -1718,9 +1790,8 @@
 android_media_MediaDrm_native_getMetrics(JNIEnv *env, jobject thiz)
 {
     sp<IDrm> drm = GetDrm(env, thiz);
-    if (drm == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException",
-                          "MediaDrm obj is null");
+
+    if (!CheckDrm(env, drm)) {
         return NULL;
     }
 
@@ -1839,6 +1910,15 @@
     { "getSecurityLevel", "([B)I",
       (void *)android_media_MediaDrm_getSecurityLevel },
 
+    { "removeOfflineLicense", "([B)V",
+      (void *)android_media_MediaDrm_removeOfflineLicense },
+
+    { "getOfflineLicenseKeySetIds", "()Ljava/util/List;",
+      (void *)android_media_MediaDrm_getOfflineLicenseKeySetIds },
+
+    { "getOfflineLicenseState", "([B)I",
+      (void *)android_media_MediaDrm_getOfflineLicenseState },
+
     { "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
       (void *)android_media_MediaDrm_getPropertyString },
 
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index 61c28ed..f7de2e7 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -175,7 +175,7 @@
     // that posts events to the application thread.
     jclass clazz = env->GetObjectClass(thiz);
     if (clazz == NULL) {
-        ALOGE("Can't find android/media/MediaPlayer2Impl");
+        ALOGE("Can't find android/media/MediaPlayer2");
         jniThrowException(env, "java/lang/Exception", NULL);
         return;
     }
@@ -488,7 +488,7 @@
     env->SetLongField(thiz, fields.surface_texture, (jlong)anw);
 
     // This will fail if the media player has not been initialized yet. This
-    // can be the case if setDisplay() on MediaPlayer2Impl.java has been called
+    // can be the case if setDisplay() on MediaPlayer2.java has been called
     // before setDataSource(). The redundant call to setVideoSurfaceTexture()
     // in prepare/prepare covers for this case.
     mp->setVideoSurfaceTexture(new ANativeWindowWrapper(anw));
@@ -598,20 +598,6 @@
     process_media_player_call( env, thiz, mp->pause(), NULL, NULL );
 }
 
-static jboolean
-android_media_MediaPlayer2_isPlaying(JNIEnv *env, jobject thiz)
-{
-    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return JNI_FALSE;
-    }
-    const jboolean is_playing = mp->isPlaying();
-
-    ALOGV("isPlaying: %d", is_playing);
-    return is_playing;
-}
-
 static void
 android_media_MediaPlayer2_setPlaybackParams(JNIEnv *env, jobject thiz, jobject params)
 {
@@ -790,40 +776,6 @@
     return (jint)mp->getState();
 }
 
-static jint
-android_media_MediaPlayer2_getVideoWidth(JNIEnv *env, jobject thiz)
-{
-    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return 0;
-    }
-    int w;
-    if (0 != mp->getVideoWidth(&w)) {
-        ALOGE("getVideoWidth failed");
-        w = 0;
-    }
-    ALOGV("getVideoWidth: %d", w);
-    return (jint) w;
-}
-
-static jint
-android_media_MediaPlayer2_getVideoHeight(JNIEnv *env, jobject thiz)
-{
-    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return 0;
-    }
-    int h;
-    if (0 != mp->getVideoHeight(&h)) {
-        ALOGE("getVideoHeight failed");
-        h = 0;
-    }
-    ALOGV("getVideoHeight: %d", h);
-    return (jint) h;
-}
-
 static jobject
 android_media_MediaPlayer2_native_getMetrics(JNIEnv *env, jobject thiz)
 {
@@ -893,71 +845,30 @@
     process_media_player_call( env, thiz, mp->reset(), NULL, NULL );
 }
 
-static jint
-android_media_MediaPlayer2_getAudioStreamType(JNIEnv *env, jobject thiz)
-{
-    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return 0;
-    }
-    audio_stream_type_t streamtype;
-    process_media_player_call( env, thiz, mp->getAudioStreamType(&streamtype), NULL, NULL );
-    ALOGV("getAudioStreamType: %d (streamtype)", streamtype);
-    return (jint) streamtype;
-}
-
 static jboolean
-android_media_MediaPlayer2_setParameter(JNIEnv *env, jobject thiz, jint key, jobject)
+android_media_MediaPlayer2_setAudioAttributes(JNIEnv *env, jobject thiz, jobject attributes)
 {
-    ALOGV("setParameter: key %d", key);
+    ALOGV("setAudioAttributes");
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         return false;
     }
-
-    return false;
-    // TODO: set/getParameter is temporarily disabled to remove android_runtime.so dependency.
-    //       Once JAudioTrack migration is done, the AudioAttribute jobject
-    //       should be directly passed to AudioTrack without native parcel conversion.
-    /*
-    Parcel *request = parcelForJavaObject(env, java_request);
-    status_t err = mp->setParameter(key, *request);
-    if (err == OK) {
-        return true;
-    } else {
-        return false;
-    }
-    */
+    status_t err = mp->setAudioAttributes(attributes);
+    return err == OK;
 }
 
 static jobject
-android_media_MediaPlayer2_getParameter(JNIEnv *env, jobject thiz, jint key)
+android_media_MediaPlayer2_getAudioAttributes(JNIEnv *env, jobject thiz)
 {
-    ALOGV("getParameter: key %d", key);
+    ALOGV("getAudioAttributes");
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         return NULL;
     }
 
-    return NULL;
-    // TODO: set/getParameter is temporarily disabled to remove android_runtime.so dependency.
-    //       Once JAudioTrack migration is done, the AudioAttribute jobject
-    //       should be directly passed to AudioTrack without native parcel conversion.
-    /*
-    jobject jParcel = createJavaParcelObject(env);
-    if (jParcel != NULL) {
-        Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
-        status_t err = mp->getParameter(key, nativeParcel);
-        if (err != OK) {
-            env->DeleteLocalRef(jParcel);
-            return NULL;
-        }
-    }
-    return jParcel;
-    */
+    return mp->getAudioAttributes();
 }
 
 static void
@@ -1039,7 +950,7 @@
 {
     jclass clazz;
 
-    clazz = env->FindClass("android/media/MediaPlayer2Impl");
+    clazz = env->FindClass("android/media/MediaPlayer2");
     if (clazz == NULL) {
         return;
     }
@@ -1098,10 +1009,11 @@
 }
 
 static void
-android_media_MediaPlayer2_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
+android_media_MediaPlayer2_native_setup(JNIEnv *env, jobject thiz,
+        jint sessionId, jobject weak_this)
 {
     ALOGV("native_setup");
-    sp<MediaPlayer2> mp = MediaPlayer2::Create();
+    sp<MediaPlayer2> mp = MediaPlayer2::Create(sessionId);
     if (mp == NULL) {
         jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
         return;
@@ -1139,9 +1051,9 @@
     android_media_MediaPlayer2_release(env, thiz);
 }
 
-static void android_media_MediaPlayer2_set_audio_session_id(JNIEnv *env,  jobject thiz,
+static void android_media_MediaPlayer2_setAudioSessionId(JNIEnv *env,  jobject thiz,
         jint sessionId) {
-    ALOGV("set_session_id(): %d", sessionId);
+    ALOGV("setAudioSessionId(): %d", sessionId);
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -1151,8 +1063,8 @@
             NULL);
 }
 
-static jint android_media_MediaPlayer2_get_audio_session_id(JNIEnv *env,  jobject thiz) {
-    ALOGV("get_session_id()");
+static jint android_media_MediaPlayer2_getAudioSessionId(JNIEnv *env,  jobject thiz) {
+    ALOGV("getAudioSessionId()");
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL ) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -1354,33 +1266,48 @@
 
 /////////////////////////////////////////////////////////////////////////////////////
 // AudioRouting begin
-static jboolean android_media_MediaPlayer2_setOutputDevice(JNIEnv *env, jobject thiz, jint device_id)
+static jboolean android_media_MediaPlayer2_setPreferredDevice(JNIEnv *env, jobject thiz, jobject device)
 {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL) {
         return false;
     }
-    return mp->setOutputDevice(device_id) == NO_ERROR;
+    return mp->setPreferredDevice(device) == NO_ERROR;
 }
 
-static jint android_media_MediaPlayer2_getRoutedDeviceId(JNIEnv *env, jobject thiz)
+static jobject android_media_MediaPlayer2_getRoutedDevice(JNIEnv *env, jobject thiz)
 {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL) {
-        return AUDIO_PORT_HANDLE_NONE;
+        return nullptr;
     }
-    return mp->getRoutedDeviceId();
+    return mp->getRoutedDevice();
 }
 
-static void android_media_MediaPlayer2_enableDeviceCallback(
-        JNIEnv* env, jobject thiz, jboolean enabled)
+static void android_media_MediaPlayer2_addDeviceCallback(
+        JNIEnv* env, jobject thiz, jobject routingDelegate)
 {
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
     if (mp == NULL) {
         return;
     }
 
-    status_t status = mp->enableAudioDeviceCallback(enabled);
+    status_t status = mp->addAudioDeviceCallback(routingDelegate);
+    if (status != NO_ERROR) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        ALOGE("enable device callback failed: %d", status);
+    }
+}
+
+static void android_media_MediaPlayer2_removeDeviceCallback(
+        JNIEnv* env, jobject thiz, jobject listener)
+{
+    sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        return;
+    }
+
+    status_t status = mp->removeAudioDeviceCallback(listener);
     if (status != NO_ERROR) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
         ALOGE("enable device callback failed: %d", status);
@@ -1467,48 +1394,46 @@
         (void *)android_media_MediaPlayer2_handleDataSourceCallback
     },
     {"nativePlayNextDataSource", "(J)V",                        (void *)android_media_MediaPlayer2_playNextDataSource},
-    {"_setVideoSurface",    "(Landroid/view/Surface;)V",        (void *)android_media_MediaPlayer2_setVideoSurface},
+    {"native_setVideoSurface", "(Landroid/view/Surface;)V",     (void *)android_media_MediaPlayer2_setVideoSurface},
     {"getBufferingParams", "()Landroid/media/BufferingParams;", (void *)android_media_MediaPlayer2_getBufferingParams},
-    {"_setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer2_setBufferingParams},
-    {"_prepare",            "()V",                              (void *)android_media_MediaPlayer2_prepare},
-    {"_start",              "()V",                              (void *)android_media_MediaPlayer2_start},
+    {"native_setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer2_setBufferingParams},
+    {"native_prepare",      "()V",                              (void *)android_media_MediaPlayer2_prepare},
+    {"native_start",        "()V",                              (void *)android_media_MediaPlayer2_start},
     {"native_getState",     "()I",                              (void *)android_media_MediaPlayer2_getState},
-    {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer2_getVideoWidth},
-    {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer2_getVideoHeight},
     {"native_getMetrics",   "()Landroid/os/PersistableBundle;", (void *)android_media_MediaPlayer2_native_getMetrics},
-    {"_setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer2_setPlaybackParams},
-    {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer2_getPlaybackParams},
-    {"_setSyncParams",     "(Landroid/media/SyncParams;)V",  (void *)android_media_MediaPlayer2_setSyncParams},
-    {"getSyncParams",     "()Landroid/media/SyncParams;",   (void *)android_media_MediaPlayer2_getSyncParams},
-    {"_seekTo",             "(JI)V",                            (void *)android_media_MediaPlayer2_seekTo},
-    {"_pause",              "()V",                              (void *)android_media_MediaPlayer2_pause},
-    {"isPlaying",           "()Z",                              (void *)android_media_MediaPlayer2_isPlaying},
+    {"native_setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer2_setPlaybackParams},
+    {"getPlaybackParams", "()Landroid/media/PlaybackParams;",   (void *)android_media_MediaPlayer2_getPlaybackParams},
+    {"native_setSyncParams",     "(Landroid/media/SyncParams;)V",     (void *)android_media_MediaPlayer2_setSyncParams},
+    {"getSyncParams",     "()Landroid/media/SyncParams;",       (void *)android_media_MediaPlayer2_getSyncParams},
+    {"native_seekTo",       "(JI)V",                            (void *)android_media_MediaPlayer2_seekTo},
+    {"native_pause",        "()V",                              (void *)android_media_MediaPlayer2_pause},
     {"getCurrentPosition",  "()J",                              (void *)android_media_MediaPlayer2_getCurrentPosition},
     {"getDuration",         "()J",                              (void *)android_media_MediaPlayer2_getDuration},
-    {"_release",            "()V",                              (void *)android_media_MediaPlayer2_release},
-    {"_reset",              "()V",                              (void *)android_media_MediaPlayer2_reset},
-    {"_getAudioStreamType", "()I",                              (void *)android_media_MediaPlayer2_getAudioStreamType},
-    {"setParameter",        "(ILjava/lang/Object;)Z",          (void *)android_media_MediaPlayer2_setParameter},
-    {"getParameter",        "(I)Ljava/lang/Object;",           (void *)android_media_MediaPlayer2_getParameter},
+    {"native_release",      "()V",                              (void *)android_media_MediaPlayer2_release},
+    {"native_reset",        "()V",                              (void *)android_media_MediaPlayer2_reset},
+    {"native_setAudioAttributes", "(Landroid/media/AudioAttributes;)Z", (void *)android_media_MediaPlayer2_setAudioAttributes},
+    {"native_getAudioAttributes", "()Landroid/media/AudioAttributes;", (void *)android_media_MediaPlayer2_getAudioAttributes},
     {"setLooping",          "(Z)V",                             (void *)android_media_MediaPlayer2_setLooping},
     {"isLooping",           "()Z",                              (void *)android_media_MediaPlayer2_isLooping},
-    {"_setVolume",          "(F)V",                             (void *)android_media_MediaPlayer2_setVolume},
-    {"_invoke",             "([B)[B",                           (void *)android_media_MediaPlayer2_invoke},
+    {"native_setVolume",    "(F)V",                             (void *)android_media_MediaPlayer2_setVolume},
+    {"native_invoke",       "([B)[B",                           (void *)android_media_MediaPlayer2_invoke},
     {"native_init",         "()V",                              (void *)android_media_MediaPlayer2_native_init},
-    {"native_setup",        "(Ljava/lang/Object;)V",            (void *)android_media_MediaPlayer2_native_setup},
+    {"native_setup",        "(ILjava/lang/Object;)V",           (void *)android_media_MediaPlayer2_native_setup},
     {"native_finalize",     "()V",                              (void *)android_media_MediaPlayer2_native_finalize},
-    {"getAudioSessionId",   "()I",                              (void *)android_media_MediaPlayer2_get_audio_session_id},
-    {"_setAudioSessionId",   "(I)V",                             (void *)android_media_MediaPlayer2_set_audio_session_id},
-    {"_setAuxEffectSendLevel", "(F)V",                          (void *)android_media_MediaPlayer2_setAuxEffectSendLevel},
-    {"_attachAuxEffect",     "(I)V",                             (void *)android_media_MediaPlayer2_attachAuxEffect},
+    {"getAudioSessionId",   "()I",                              (void *)android_media_MediaPlayer2_getAudioSessionId},
+    {"native_setAudioSessionId", "(I)V",                        (void *)android_media_MediaPlayer2_setAudioSessionId},
+    {"native_setAuxEffectSendLevel", "(F)V",                    (void *)android_media_MediaPlayer2_setAuxEffectSendLevel},
+    {"native_attachAuxEffect", "(I)V",                          (void *)android_media_MediaPlayer2_attachAuxEffect},
     // Modular DRM
-    { "_prepareDrm", "([B[B)V",                                 (void *)android_media_MediaPlayer2_prepareDrm },
-    { "_releaseDrm", "()V",                                     (void *)android_media_MediaPlayer2_releaseDrm },
+    { "native_prepareDrm", "([B[B)V",                           (void *)android_media_MediaPlayer2_prepareDrm },
+    { "native_releaseDrm", "()V",                               (void *)android_media_MediaPlayer2_releaseDrm },
 
     // AudioRouting
-    {"native_setOutputDevice", "(I)Z",                          (void *)android_media_MediaPlayer2_setOutputDevice},
-    {"native_getRoutedDeviceId", "()I",                         (void *)android_media_MediaPlayer2_getRoutedDeviceId},
-    {"native_enableDeviceCallback", "(Z)V",                     (void *)android_media_MediaPlayer2_enableDeviceCallback},
+    {"native_setPreferredDevice", "(Landroid/media/AudioDeviceInfo;)Z", (void *)android_media_MediaPlayer2_setPreferredDevice},
+    {"getRoutedDevice", "()Landroid/media/AudioDeviceInfo;", (void *)android_media_MediaPlayer2_getRoutedDevice},
+    {"native_addDeviceCallback", "(Landroid/media/RoutingDelegate;)V", (void *)android_media_MediaPlayer2_addDeviceCallback},
+    {"native_removeDeviceCallback", "(Landroid/media/AudioRouting$OnRoutingChangedListener;)V",
+            (void *)android_media_MediaPlayer2_removeDeviceCallback},
 
     // StreamEventCallback for JAudioTrack
     {"native_stream_event_onTearDown",                "(JJ)V",  (void *)android_media_MediaPlayer2_native_on_tear_down},
@@ -1517,9 +1442,9 @@
 };
 
 // This function only registers the native methods
-static int register_android_media_MediaPlayer2Impl(JNIEnv *env)
+static int register_android_media_MediaPlayer2(JNIEnv *env)
 {
-    return jniRegisterNativeMethods(env, "android/media/MediaPlayer2Impl", gMethods, NELEM(gMethods));
+    return jniRegisterNativeMethods(env, "android/media/MediaPlayer2", gMethods, NELEM(gMethods));
 }
 
 jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
@@ -1533,7 +1458,7 @@
     }
     assert(env != NULL);
 
-    if (register_android_media_MediaPlayer2Impl(env) < 0) {
+    if (register_android_media_MediaPlayer2(env) < 0) {
         ALOGE("ERROR: MediaPlayer2 native registration failed\n");
         goto bail;
     }
diff --git a/media/native/midi/midi.cpp b/media/native/midi/midi.cpp
index 78ca0ab..a5bdba8 100644
--- a/media/native/midi/midi.cpp
+++ b/media/native/midi/midi.cpp
@@ -338,7 +338,8 @@
             numMessageBytes = std::min(maxBytes, numMessageBytes);
             memcpy(buffer, readBuffer + 1, numMessageBytes);
             if (timestampPtr != nullptr) {
-                *timestampPtr = *(uint64_t*)(readBuffer + readCount - sizeof(uint64_t));
+                memcpy(timestampPtr, readBuffer + readCount - sizeof(uint64_t),
+                        sizeof(*timestampPtr));
             }
         }
         *numBytesReceivedPtr = numMessageBytes;
diff --git a/native/android/Android.bp b/native/android/Android.bp
index a4306fe..5cfb09b 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -81,6 +81,8 @@
     export_static_lib_headers: ["libarect"],
 
     include_dirs: ["bionic/libc/dns/include"],
+
+    version_script: "libandroid.map.txt",
 }
 
 // Network library.
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 9426148..942eafd 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -37,6 +37,7 @@
             ldflags: ["-Wl,--hash-style=both"],
         },
     },
+    version_script: "libjnigraphics.map.txt",
 }
 
 // The headers module is in frameworks/native/Android.bp.
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index 9ecaa03..5ab6632 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -26,7 +26,8 @@
     <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
 
     <application android:label="@string/app_name"
-                 android:usesCleartextTraffic="true">
+                 android:usesCleartextTraffic="true"
+                 android:supportsRtl="true" >
         <activity
             android:name="com.android.captiveportallogin.CaptivePortalLoginActivity"
             android:label="@string/action_bar_label"
diff --git a/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml b/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml
new file mode 100644
index 0000000..d460041
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/ssl_error_msg"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:textAppearance="?android:attr/textAppearanceSmall"
+    android:layout_marginStart="20dip"
+    android:layout_marginEnd="20dip"
+    android:gravity="center_vertical"
+    android:layout_marginBottom="4dip"
+    android:layout_marginTop="4dip" />
+
diff --git a/packages/CaptivePortalLogin/res/layout/ssl_warning.xml b/packages/CaptivePortalLogin/res/layout/ssl_warning.xml
new file mode 100644
index 0000000..ffd57a4
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/layout/ssl_warning.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical" >
+
+    <!-- ssl error type -->
+    <TextView
+        android:id="@+id/ssl_error_type"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="start"
+        android:text="SSL_UNKNOWN"
+        android:layout_marginStart="24dip"
+        android:layout_marginEnd="24dip"
+        android:layout_marginBottom="0dip"
+        android:layout_marginTop="24dip" />
+
+    <!-- Page info: -->
+    <TextView
+        android:id="@+id/page_info"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/page_info"
+        android:textStyle="bold"
+        android:layout_marginStart="24dip"
+        android:layout_marginEnd="24dip" />
+
+    <!-- Title: -->
+    <TextView
+        android:id="@+id/title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textStyle="bold"
+        android:layout_marginStart="24dip"
+        android:layout_marginEnd="24dip" />
+
+    <!-- Address: -->
+    <TextView
+        android:id="@+id/address_header"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/page_info_address"
+        android:layout_marginStart="24dip"
+        android:layout_marginEnd="24dip" />
+
+    <TextView
+        android:id="@+id/address"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="24dip"
+        android:layout_marginEnd="24dip" />
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="4dip"
+        android:paddingEnd="4dip" >
+
+        <!-- certificate view: -->
+        <LinearLayout
+            android:id="@+id/certificate_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="16dip" >
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
diff --git a/packages/CaptivePortalLogin/res/values-af/strings.xml b/packages/CaptivePortalLogin/res/values-af/strings.xml
index fa6f3fa..cf4dc82 100644
--- a/packages/CaptivePortalLogin/res/values-af/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-af/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Die netwerk waarby jy probeer aansluit, het sekuriteitkwessies."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Byvoorbeeld, die aanmeldbladsy behoort dalk nie aan die organisasie wat gewys word nie."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Gaan in elk geval deur blaaier voort"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Bladsy-inligting"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sekuriteitswaarskuwing"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Bekyk sertifikaat"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Hierdie sertifikaat is nie van \'n betroubare owerheid nie."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Die naam van die werf kom nie ooreen met die naam op die sertifikaat nie."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Hierdie sertifikaat het verval."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Hierdie sertifikaat is nog nie geldig nie."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Hierdie sertifikaat het \'n ongeldige datum."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Hierdie sertifikaat is ongeldig."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Onbekende sertifikaatfout."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-am/strings.xml b/packages/CaptivePortalLogin/res/values-am/strings.xml
index 36d5e19..cdcb5a5 100644
--- a/packages/CaptivePortalLogin/res/values-am/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-am/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"ለመቀላቀል እየሞከሩ ያሉት አውታረ መረብ የደህንነት ችግሮች አሉበት።"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ለምሳሌ፣ የመግቢያ ገጹ የሚታየው ድርጅት ላይሆን ይችላል።"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ለማንኛውም በአሳሽ በኩል ይቀጥሉ"</string>
+    <string name="ok" msgid="1509280796718850364">"እሺ"</string>
+    <string name="page_info" msgid="4048529256302257195">"የገፅ መረጃ"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"አድራሻ:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"የደህንነት ቅንብሮች"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"ምስክሮች ይመልከቱ"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"ይህ ምስክር ከታማኝ ቦታ አይደለም።"</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"የጣቢያው ስም ከምስክር ወረቀቱ ስም ጋር አይዛመድም።"</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"ይህ ምስክር ጊዜው አልፏል"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"ይህ ምስክር ገና ትክክል አይደለም።"</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"ይህ ምስክር ትክክለኛ ቀን አለው።"</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"ይህ ምስክር ትክክል ያልሆነ ነው።"</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"ያልታወቀ የምስክር ስህተት።"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ar/strings.xml b/packages/CaptivePortalLogin/res/values-ar/strings.xml
index 8eb259b..7773eeb 100644
--- a/packages/CaptivePortalLogin/res/values-ar/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ar/strings.xml
@@ -11,4 +11,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"الشبكة التي تحاول الانضمام إليها بها مشاكل أمنية."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"على سبيل المثال، قد لا تنتمي صفحة تسجيل الدخول إلى المنظمة المعروضة."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"المتابعة على أي حال عبر المتصفح"</string>
+    <string name="ok" msgid="1509280796718850364">"موافق"</string>
+    <string name="page_info" msgid="4048529256302257195">"معلومات الصفحة"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"العنوان:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"تحذير أمان"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"عرض الشهادة"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"هذه الشهادة ليست من جهة موثوق بها."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"لا يتطابق اسم الموقع مع الاسم على الشهادة."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"انتهت صلاحية هذه الشهادة."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"هذه الشهادة ليست صالحة بعد."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"تشتمل هذه الشهادة على تاريخ غير صالح."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"هذه الشهادة غير صالحة."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"حدث خطأ غير معروف بالشهادة."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-bg/strings.xml b/packages/CaptivePortalLogin/res/values-bg/strings.xml
index 8ce9deb..4dd8aa0 100644
--- a/packages/CaptivePortalLogin/res/values-bg/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-bg/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Мрежата, към която опитвате да се присъедините, има проблеми със сигурността."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Например страницата за вход може да не принадлежи на показаната организация."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Продължаване през браузър въпреки това"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Данни за страницата"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Адрес:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Предупреждение относно защитата"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Преглед на сертификата"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Сертификатът не е от надежден орган."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Името на сайта не съответства на името в сертификата."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Сертификатът е изтекъл."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Сертификатът още не е валиден."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Този сертификат е с невалидна дата."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Този сертификат е невалиден."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Неизвестна грешка в сертификата."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-bn/strings.xml b/packages/CaptivePortalLogin/res/values-bn/strings.xml
index b75d76e..fb703cf 100644
--- a/packages/CaptivePortalLogin/res/values-bn/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-bn/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"আপনি যে নেটওয়ার্কে যোগ দেওয়ার চেষ্টা করছেন তাতে নিরাপত্তার সমস্যা আছে।"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"উদাহরণস্বরূপ, লগ-ইন পৃষ্ঠাটি প্রদর্শিত প্রতিষ্ঠানের অন্তর্গত নাও হতে পারে৷"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"যাই হোক না কেন ব্রাউজারের মাধ্যমে অবিরত রাখুন"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Sideinfo"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sikkerhetsadvarsel"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vis sertifikat"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sertifikatet er ikke fra en pålitelig myndighet."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Navnet på nettstedet samsvarer ikke med navnet på sertifikatet."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Sertifikatet er utløpt."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sertifikatet er ikke gyldig ennå."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dette sertifikatet har en ugyldig dato."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Dette sertifikatet er ugyldig."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Ukjent sertifikatfeil."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ca/strings.xml b/packages/CaptivePortalLogin/res/values-ca/strings.xml
index fe189ed..a2c9ed8 100644
--- a/packages/CaptivePortalLogin/res/values-ca/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ca/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"La xarxa a què et vols connectar té problemes de seguretat."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Per exemple, la pàgina d\'inici de sessió podria no pertànyer a l\'organització que es mostra."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continua igualment mitjançant el navegador"</string>
+    <string name="ok" msgid="1509280796718850364">"D\'acord"</string>
+    <string name="page_info" msgid="4048529256302257195">"Informació de la pàgina"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adreça:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Advertiment de seguretat"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visualitza el certificat"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Aquest certificat no és d\'una autoritat de confiança."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"El nom del lloc no coincideix amb el del certificat."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Aquest certificat ha caducat."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Aquest certificat encara no és vàlid."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Aquest certificat té una data no vàlida."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Aquest certificat no és vàlid."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Error de certificat desconegut."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-cs/strings.xml b/packages/CaptivePortalLogin/res/values-cs/strings.xml
index 09dcc5f..be649a5 100644
--- a/packages/CaptivePortalLogin/res/values-cs/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-cs/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Síť, ke které se pokoušíte připojit, má bezpečnostní problémy."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Například přihlašovací stránka nemusí patřit do zobrazované organizace."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Přesto pokračovat prostřednictvím prohlížeče"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Informace o stránce"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adresa:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Upozornění zabezpečení"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Zobrazit certifikát"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Tento certifikát nepochází od důvěryhodné autority."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Název webu se neshoduje s názvem uvedeným v certifikátu."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Platnost certifikátu vypršela."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Tento certifikát ještě není platný."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Datum tohoto certifikátu není platné."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Tento certifikát je neplatný."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Neznámá chyba certifikátu."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-da/strings.xml b/packages/CaptivePortalLogin/res/values-da/strings.xml
index dc0dd17..8183105 100644
--- a/packages/CaptivePortalLogin/res/values-da/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-da/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Der er sikkerhedsproblemer på det netværk, du forsøger at logge ind på."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Det er f.eks. ikke sikkert, at loginsiden tilhører den anførte organisation."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Fortsæt alligevel via browseren"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Sideoplysninger"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sikkerhedsadvarsel"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vis certifikat"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Dette certifikat stammer ikke fra en troværdig autoritet."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Navnet på websitet stemmer ikke overens med navnet på certifikatet."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Dette certifikat er udløbet."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Dette certifikat er endnu ikke gyldigt."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dette certifikat har en ugyldig dato."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Dette certifikat er ugyldigt."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Ukendt fejl i certifikatet."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-de/strings.xml b/packages/CaptivePortalLogin/res/values-de/strings.xml
index d8f7be9..a9b7415 100644
--- a/packages/CaptivePortalLogin/res/values-de/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-de/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Im Netzwerk, zu dem du eine Verbindung herstellen möchtest, liegen Sicherheitsprobleme vor."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Beispiel: Die Log-in-Seite gehört eventuell nicht zur angezeigten Organisation."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Trotzdem in einem Browser fortfahren"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Seiteninfo"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sicherheitswarnung"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Zertifikat ansehen"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Dieses Zertifikat wurde nicht von einer vertrauenswürdigen Stelle ausgegeben."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Name der Website stimmt nicht mit dem Namen auf dem Zertifikat überein."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Dieses Zertifikat ist abgelaufen."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Dieses Zertifikat ist noch nicht gültig."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dieses Zertifikat weist ein ungültiges Datum auf."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Dieses Zertifikat ist ungültig."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Unbekannter Zertifikatfehler"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-el/strings.xml b/packages/CaptivePortalLogin/res/values-el/strings.xml
index cb61710..16bf6e2 100644
--- a/packages/CaptivePortalLogin/res/values-el/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-el/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Παρουσιάζονται προβλήματα ασφάλειας στο δίκτυο στο οποίο προσπαθείτε να συνδεθείτε."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Για παράδειγμα, η σελίδα σύνδεσης ενδέχεται να μην ανήκει στον οργανισμό που εμφανίζεται."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Συνέχεια ούτως ή άλλως μέσω του προγράμματος περιήγησης"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Πληροφορίες σελίδας"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Διεύθυνση:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Προειδοποίηση ασφαλείας"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Προβολή πιστοποιητικού"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Αυτό το πιστοποιητικό δεν προέρχεται από αξιόπιστη αρχή."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Το όνομα του ιστότοπου δεν αντιστοιχεί με το όνομα στο πιστοποιητικό."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Αυτό το πιστοποιητικό έχει λήξει."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Αυτό το πιστοποιητικό δεν είναι έγκυρο ακόμα."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Αυτό το πιστοποιητικό δεν έχει έγκυρη ημερομηνία."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Αυτό το πιστοποιητικό δεν είναι έγκυρο."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Άγνωστο σφάλμα πιστοποιητικού."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml b/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
index 2e8d1f0..f940299 100644
--- a/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"The network that you’re trying to join has security issues."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"For example, the login page might not belong to the organisation shown."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continue anyway via browser"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Page info"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Address:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Security warning"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"View certificate"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"This certificate isn\'t from a trusted authority."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"The name of the site doesn\'t match the name on the certificate."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"This certificate has expired."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"This certificate isn\'t valid yet."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"This certificate has an invalid date."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"This certificate is invalid."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Unknown certificate error."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml b/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
index 2e8d1f0..f940299 100644
--- a/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"The network that you’re trying to join has security issues."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"For example, the login page might not belong to the organisation shown."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continue anyway via browser"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Page info"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Address:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Security warning"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"View certificate"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"This certificate isn\'t from a trusted authority."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"The name of the site doesn\'t match the name on the certificate."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"This certificate has expired."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"This certificate isn\'t valid yet."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"This certificate has an invalid date."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"This certificate is invalid."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Unknown certificate error."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml b/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml
index 5d7ba91..c011664 100644
--- a/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"La red a la que intentas conectarte tiene problemas de seguridad."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Por ejemplo, es posible que la página de acceso no pertenezca a la organización que aparece."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuar de todos modos desde el navegador"</string>
+    <string name="ok" msgid="1509280796718850364">"Aceptar"</string>
+    <string name="page_info" msgid="4048529256302257195">"Información de la página"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Dirección:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Advertencia de seguridad"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Ver certificado"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado no proviene de una autoridad confiable."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"El nombre del sitio no coincide con el nombre del certificado."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado ha expirado."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado aún no es válido."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"La fecha de este certificado no es válida."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado no es válido."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Error de certificado desconocido"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-es/strings.xml b/packages/CaptivePortalLogin/res/values-es/strings.xml
index da2eae9..65244e7 100644
--- a/packages/CaptivePortalLogin/res/values-es/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-es/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"La red a la que intentas unirte tiene problemas de seguridad."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Por ejemplo, es posible que la página de inicio de sesión no pertenezca a la organización mostrada."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuar de todos modos a través del navegador"</string>
+    <string name="ok" msgid="1509280796718850364">"Aceptar"</string>
+    <string name="page_info" msgid="4048529256302257195">"Información de la página"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Dirección:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Advertencia de seguridad"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Ver certificado"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado no procede de una entidad de certificación de confianza."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"El nombre del sitio no coincide con el del certificado."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado ha caducado."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado aún no es válido."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"La fecha de este certificado no es válida."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado no es válido."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Error de certificado desconocido"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-et/strings.xml b/packages/CaptivePortalLogin/res/values-et/strings.xml
index 41fcb9a..e4c4c98 100644
--- a/packages/CaptivePortalLogin/res/values-et/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-et/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Võrgul, millega üritate ühenduse luua, on turvaprobleeme."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Näiteks ei pruugi sisselogimisleht kuuluda kuvatavale organisatsioonile."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Jätka siiski brauseris"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Lehe teave"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Aadress:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Turvahoiatus"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Kuva sertifikaat"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"See sertifikaat ei pärine usaldusväärselt asutuselt."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Saidi nimi ei vasta sertifikaadil olevale nimele."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"See sertifikaat on aegunud."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"See sertifikaat pole veel kehtiv."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Sellel sertifikaadil on kehtetu kuupäev."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"See sertifikaat on kehtetu."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Tundmatu sertifikaadiviga."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-fa/strings.xml b/packages/CaptivePortalLogin/res/values-fa/strings.xml
index 2e4cc51..27b9b7f 100644
--- a/packages/CaptivePortalLogin/res/values-fa/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fa/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"شبکه‌ای که می‌خواهید به آن بپیوندید مشکلات امنیتی دارد."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"به عنوان مثال، صفحه ورود به سیستم ممکن است متعلق به سازمان نشان داده شده نباشد."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"در هر صورت از طریق مرورگر ادامه یابد"</string>
+    <string name="ok" msgid="1509280796718850364">"تأیید"</string>
+    <string name="page_info" msgid="4048529256302257195">"اطلاعات صفحه"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"آدرس:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"اخطار امنیتی"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"مشاهده گواهی"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"این گواهی از یک منبع مورد اطمینان صادر نشده است."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"نام سایت با نام موجود در گواهی مطابقت ندارد."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"این گواهی منقضی شده است."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"این گواهی هنوز معتبر نیست."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"تاریخ این گواهی نامعتبر است."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"این گواهی نامعتبر است."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"خطای ناشناخته در گواهی."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-fi/strings.xml b/packages/CaptivePortalLogin/res/values-fi/strings.xml
index 1976f7d..8086fbf 100644
--- a/packages/CaptivePortalLogin/res/values-fi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fi/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Verkossa, johon yrität muodostaa yhteyttä, on turvallisuusongelmia."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Kirjautumissivu ei välttämättä kuulu näytetylle organisaatiolle."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Jatka silti selaimen kautta."</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Sivun tiedot"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Osoite:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Suojausvaroitus"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Näytä varmenne"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Varmenteen myöntäjä ei ole luotettava taho."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Sivuston nimi ei vastaa varmenteessa olevaa nimeä."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Varmenne ei ole enää voimassa."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Varmenne ei ole vielä voimassa."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Varmenteen päiväys ei kelpaa."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Varmenne on virheellinen."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Tuntematon varmennevirhe."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-fr/strings.xml b/packages/CaptivePortalLogin/res/values-fr/strings.xml
index 8f98bb5..39fc569 100644
--- a/packages/CaptivePortalLogin/res/values-fr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fr/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Le réseau que vous essayez de rejoindre présente des problèmes de sécurité."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Par exemple, la page de connexion peut ne pas appartenir à l\'organisation représentée."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuer quand même dans le navigateur"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Infos sur la page"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adresse :"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Avertissement de sécurité"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Afficher le certificat"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ce certificat provient d\'une autorité non approuvée."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Le nom du site ne correspond pas au nom indiqué dans le certificat."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Le certificat a expiré."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Ce certificat n\'est pas encore valide."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"La date de ce certificat n\'est pas valide."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Ce certificat n\'est pas valide."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Erreur : Certificat inconnu."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-hi/strings.xml b/packages/CaptivePortalLogin/res/values-hi/strings.xml
index 1bacc46..d924fff 100644
--- a/packages/CaptivePortalLogin/res/values-hi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hi/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"आप जिस नेटवर्क में शामिल होने का प्रयास कर रहे हैं उसमें सुरक्षा समस्‍याएं हैं."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"उदाहरण के लिए, हो सकता है कि लॉगिन पृष्‍ठ दिखाए गए संगठन से संबद्ध ना हो."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ब्राउज़र के द्वारा फिर जारी रखें"</string>
+    <string name="ok" msgid="1509280796718850364">"ठीक"</string>
+    <string name="page_info" msgid="4048529256302257195">"पृष्ठ जानकारी"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"पता:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"सुरक्षा चेतावनी"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"प्रमाणपत्र देखें"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"यह प्रमाणपत्र किसी विश्वस्त प्राधिकारी का नहीं है."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"साइट का नाम, प्रमाणपत्र के नाम से मिलान नहीं करता."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"इस प्रमाणपत्र की समय सीमा समाप्त हो गई है."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"यह प्रमाणपत्र अभी तक मान्य नहीं है."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"इस प्रमाणपत्र में एक अमान्‍य दिनांक है."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"यह प्रमाणपत्र अमान्य है."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"अज्ञात प्रमाणपत्र त्रुटि."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-hr/strings.xml b/packages/CaptivePortalLogin/res/values-hr/strings.xml
index e44cd3b..11b1dd3 100644
--- a/packages/CaptivePortalLogin/res/values-hr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hr/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Mreža kojoj se pokušavate pridružiti ima sigurnosne poteškoće."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Na primjer, stranica za prijavu možda ne pripada prikazanoj organizaciji."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Ipak nastavi putem preglednika"</string>
+    <string name="ok" msgid="1509280796718850364">"U redu"</string>
+    <string name="page_info" msgid="4048529256302257195">"Informacije o stranici"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adresa:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Upozorenje o sigurnosti"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Prikaži certifikat"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ovaj certifikat ne potječe iz pouzdanog izvora."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Naziv web-lokacije ne podudara se s nazivom na certifikatu."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Ovaj je certifikat istekao."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Ovaj certifikat još nije važeći."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Ovaj certifikat ima nevažeći datum."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Ovaj certifikat nije valjan."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Nepoznata pogreška certifikata."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-hu/strings.xml b/packages/CaptivePortalLogin/res/values-hu/strings.xml
index f15fb49..145e2ab 100644
--- a/packages/CaptivePortalLogin/res/values-hu/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hu/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Biztonsági problémák vannak azzal a hálózattal, amelyhez csatlakozni szeretne."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Például lehet, hogy a bejelentkezési oldal nem a megjelenített szervezethez tartozik."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Folytatás ennek ellenére böngészőn keresztül"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Oldaladatok"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Cím:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Biztonsági figyelmeztetés"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Tanúsítvány megtekintése"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ez a tanúsítvány nem hiteles tanúsítványkibocsátótól származik."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"A webhely neve nem egyezik a tanúsítványon lévő névvel."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"A tanúsítvány lejárt."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"A tanúsítvány még nem érvényes."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"A tanúsítvány dátuma érvénytelen."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Ez a tanúsítvány érvénytelen."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Ismeretlen tanúsítványhiba."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-in/strings.xml b/packages/CaptivePortalLogin/res/values-in/strings.xml
index 10e3de6..4a335dd 100644
--- a/packages/CaptivePortalLogin/res/values-in/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-in/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Jaringan yang ingin Anda masuki mengalami masalah keamanan."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Misalnya, halaman masuk mungkin bukan milik organisasi yang ditampilkan."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Tetap lanjutkan melalui browser"</string>
+    <string name="ok" msgid="1509280796718850364">"Oke"</string>
+    <string name="page_info" msgid="4048529256302257195">"Info laman"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Alamat:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Peringatan sertifikat"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Lihat sertifikat"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sertifikat ini tidak berasal dari otoritas tepercaya."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Nama situs tidak cocok dengan nama pada sertifikat."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Sertifikat ini telah kedaluwarsa."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sertifikat ini belum valid."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Tanggal sertifikat ini tidak valid."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Sertifikat ini tidak valid."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Kesalahan sertifikat tak dikenal."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-it/strings.xml b/packages/CaptivePortalLogin/res/values-it/strings.xml
index a01a553..2cc4038 100644
--- a/packages/CaptivePortalLogin/res/values-it/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-it/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"La rete a cui stai tentando di accedere presenta problemi di sicurezza."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Ad esempio, la pagina di accesso potrebbe non appartenere all\'organizzazione indicata."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continua comunque dal browser"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Info pagina"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Indirizzo:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Avviso di sicurezza"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visualizza certificato"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Questo certificato non proviene da un\'autorità attendibile."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Il nome del sito non corrisponde al nome nel certificato."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Il certificato è scaduto."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Questo certificato non è ancora valido."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Questo certificato presenta una data non valida."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Questo certificato non è valido."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Errore certificato sconosciuto."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-iw/strings.xml b/packages/CaptivePortalLogin/res/values-iw/strings.xml
index 8e7915d..527e692 100644
--- a/packages/CaptivePortalLogin/res/values-iw/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-iw/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"יש בעיות אבטחה ברשת שאליה אתה מנסה להתחבר."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"לדוגמה, ייתכן שדף ההתחברות אינו שייך לארגון המוצג."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"המשך בכל זאת באמצעות דפדפן"</string>
+    <string name="ok" msgid="1509280796718850364">"אישור"</string>
+    <string name="page_info" msgid="4048529256302257195">"פרטי דף"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"כתובת:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"אזהרת אבטחה"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"הצג אישור"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"אישור זה אינו מגיע מרשות אמינה."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"שם האתר לא תואם לשם באישור."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"פג תוקפו של אישור זה."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"אישור זה אינו חוקי עדיין."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"לאישור זה יש תאריך בלתי חוקי."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"אישור זה אינו חוקי."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"שגיאת אישור לא ידועה."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ja/strings.xml b/packages/CaptivePortalLogin/res/values-ja/strings.xml
index e275b95..bcc8686 100644
--- a/packages/CaptivePortalLogin/res/values-ja/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ja/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"接続しようとしているネットワークにセキュリティの問題があります。"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"たとえば、ログインページが表示されている組織に属していない可能性があります。"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ブラウザから続行"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"ページ情報"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"アドレス:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"セキュリティ警告"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"証明書を表示"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"この証明書は信頼できる認証機関のものではありません。"</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"サイト名と証明書上の名前が一致しません。"</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"この証明書は有効期限切れです。"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"この証明書はまだ有効ではありません。"</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"この証明書の日付は無効です。"</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"この証明書は無効です。"</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"不明な証明書エラーです。"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ko/strings.xml b/packages/CaptivePortalLogin/res/values-ko/strings.xml
index 75f2b48..7a7f7e0 100644
--- a/packages/CaptivePortalLogin/res/values-ko/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ko/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"가입하려는 네트워크에 보안 문제가 있습니다."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"예를 들어 로그인 페이지가 표시된 조직에 속하지 않을 수 있습니다."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"브라우저를 통해 계속하기"</string>
+    <string name="ok" msgid="1509280796718850364">"확인"</string>
+    <string name="page_info" msgid="4048529256302257195">"페이지 정보"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"주소:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"보안 경고"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"인증서 보기"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"신뢰할 수 있는 인증 기관에서 발급한 인증서가 아닙니다."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"사이트 이름이 인증서에 있는 것과 일치하지 않습니다."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"인증서가 만료되었습니다."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"인증서가 아직 유효하지 않습니다."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"인증서 날짜가 유효하지 않습니다."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"인증서가 잘못되었습니다."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"알 수 없는 인증서 오류입니다."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-lt/strings.xml b/packages/CaptivePortalLogin/res/values-lt/strings.xml
index 17da83f..158f7ce 100644
--- a/packages/CaptivePortalLogin/res/values-lt/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-lt/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Kilo tinklo, prie kurio bandote prisijungti, problemų."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Pavyzdžiui, prisijungimo puslapis gali nepriklausyti rodomai organizacijai."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Vis tiek tęsti naudojant naršyklę"</string>
+    <string name="ok" msgid="1509280796718850364">"Gerai"</string>
+    <string name="page_info" msgid="4048529256302257195">"Puslapio informacija"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adresas:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Saugos įspėjimas"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Žiūrėti sertifikatą"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Šį sertifikatą išdavė nepatikima įstaiga."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Svetainės pavadinimas neatitinka sertifikate nurodyto pavadinimo."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Šio sertifikato galiojimo laikas baigėsi."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Šis sertifikatas dar negalioja."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Šio sertifikato data netinkama."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Šis sertifikatas netinkamas."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Nežinoma sertifikato klaida."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-lv/strings.xml b/packages/CaptivePortalLogin/res/values-lv/strings.xml
index 95b8558..a42cb22 100644
--- a/packages/CaptivePortalLogin/res/values-lv/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-lv/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Tīklam, kuram mēģināt pievienoties, ir drošības problēmas."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Piemēram, pieteikšanās lapa, iespējams, nepieder norādītajai organizācijai."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Tik un tā turpināt, izmantojot pārlūkprogrammu"</string>
+    <string name="ok" msgid="1509280796718850364">"Labi"</string>
+    <string name="page_info" msgid="4048529256302257195">"Lapas informācija"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adrese:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Drošības brīdinājums"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Skatīt sertifikātu"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Šo sertifikātu nav izsniegusi uzticama iestāde."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Vietnes nosaukums neatbilst nosaukumam sertifikātā."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Šī sertifikāta derīguma termiņš ir beidzies."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Šis sertifikāts vēl nav derīgs."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Šī sertifikāta datums nav derīgs."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Šis sertifikāts nav derīgs."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Nezināma sertifikāta kļūda."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ms/strings.xml b/packages/CaptivePortalLogin/res/values-ms/strings.xml
index 933721a..aaa51c8 100644
--- a/packages/CaptivePortalLogin/res/values-ms/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ms/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Rangkaian yang anda cuba sertai mempunyai isu keselamatan."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Contohnya, halaman log masuk mungkin bukan milik organisasi yang ditunjukkan."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Teruskan juga melalui penyemak imbas"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Maklumat halaman"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Alamat:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Amaran keselamatan"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Lihat sijil"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sijil ini bukan daripada pihak berkuasa yang dipercayai."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Nama tapak tidak sepadan dengan nama pada sijil."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Sijil ini telah tamat tempoh."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sijil ini belum lagi sah."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Sijil ini mempunyai tarikh yang tidak sah."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Sijil ini tidak sah."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Ralat sijil tidak diketahui."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-nb/strings.xml b/packages/CaptivePortalLogin/res/values-nb/strings.xml
index 0dd5b6c..29c23ed 100644
--- a/packages/CaptivePortalLogin/res/values-nb/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-nb/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Nettverket du prøver å logge på, har sikkerhetsproblemer."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Det er for eksempel mulig at påloggingssiden kanskje ikke tilhører organisasjonen som vises."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Fortsett likevel via nettleseren"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Sideinfo"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sikkerhetsadvarsel"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vis sertifikat"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sertifikatet er ikke fra en pålitelig myndighet."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Navnet på nettstedet samsvarer ikke med navnet på sertifikatet."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Sertifikatet er utløpt."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sertifikatet er ikke gyldig ennå."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dette sertifikatet har en ugyldig dato."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Dette sertifikatet er ugyldig."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Ukjent sertifikatfeil."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-nl/strings.xml b/packages/CaptivePortalLogin/res/values-nl/strings.xml
index 1c59601..2cbca06 100644
--- a/packages/CaptivePortalLogin/res/values-nl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-nl/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Het netwerk waarmee u verbinding probeert te maken, heeft beveiligingsproblemen."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Zo hoort de weergegeven inlogpagina misschien niet bij de weergegeven organisatie."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Toch doorgaan via browser"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Pagina-informatie"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Beveiligingsmelding"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Certificaat weergeven"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Dit is geen certificaat van een vertrouwde autoriteit."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"De naam van deze site komt niet overeen met de naam op het certificaat."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Dit certificaat is verlopen."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Dit certificaat is nog niet geldig."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dit certificaat heeft een ongeldige datum."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Dit certificaat is ongeldig."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Onbekende certificaatfout."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-pl/strings.xml b/packages/CaptivePortalLogin/res/values-pl/strings.xml
index 17f20df..9ba066e 100644
--- a/packages/CaptivePortalLogin/res/values-pl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pl/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"W sieci, z którą próbujesz się połączyć, występują problemy z zabezpieczeniami."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Na przykład strona logowania może nie należeć do wyświetlanej organizacji."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Kontynuuj mimo to w przeglądarce"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Informacje o stronie"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Ostrzeżenie zabezpieczeń"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Wyświetl certyfikat"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Certyfikat nie pochodzi od zaufanego urzędu."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Nazwa witryny nie pasuje do nazwy na certyfikacie."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Ten certyfikat wygasł."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Certyfikat nie jest jeszcze ważny."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Certyfikat ma nieprawidłową datę."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Certyfikat jest nieprawidłowy."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Nieznany błąd certyfikatu"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml b/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml
index 94b9d60..5bef235 100644
--- a/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"A rede à qual está a tentar aceder tem problemas de segurança."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Por exemplo, a página de início de sessão pode não pertencer à entidade apresentada."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuar mesmo assim através do navegador"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Informações da página"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Endereço:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Aviso de segurança"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Ver certificado"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado não pertence a uma autoridade fidedigna."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"O nome do Web site não corresponde ao nome constante no certificado."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado expirou."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado ainda não é válido."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Este certificado tem uma data inválida."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado é inválido."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Erro: certificado desconhecido."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-pt/strings.xml b/packages/CaptivePortalLogin/res/values-pt/strings.xml
index 3d1064c..ebe4148 100644
--- a/packages/CaptivePortalLogin/res/values-pt/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pt/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"A rede à qual você está tentando se conectar tem problemas de segurança."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuar mesmo assim pelo navegador"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Informações da página"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Endereço:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Aviso de segurança"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visualizar certificado"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado não é de uma autoridade confiável."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"O nome do site não corresponde ao nome no certificado."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado expirou."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado ainda não é válido."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Este certificado tem uma data inválida."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado é inválido."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Erro de certificado desconhecido."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ro/strings.xml b/packages/CaptivePortalLogin/res/values-ro/strings.xml
index cf1b6b5..e2e4eac 100644
--- a/packages/CaptivePortalLogin/res/values-ro/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ro/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Rețeaua la care încercați să vă conectați are probleme de securitate."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"De exemplu, este posibil ca pagina de conectare să nu aparțină organizației afișate."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Continuați oricum prin browser"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Informaţii pagină"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adresă:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Avertisment de securitate"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vizualizaţi certificatul"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Acest certificat nu provine de la o autoritate de încredere."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Numele acestui site nu se potriveşte cu numele de pe certificat."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Acest certificat a expirat."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Acest certificat nu este încă valid."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Acest certificat are o dată nevalidă."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Acest certificat este nevalid."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Eroare de certificat necunoscută."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-ru/strings.xml b/packages/CaptivePortalLogin/res/values-ru/strings.xml
index 6966bcd..c0153e6 100644
--- a/packages/CaptivePortalLogin/res/values-ru/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ru/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Сеть, к которой вы хотите подключиться, небезопасна."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Например, страница входа в аккаунт может быть фиктивной."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Игнорировать и открыть браузер"</string>
+    <string name="ok" msgid="1509280796718850364">"ОК"</string>
+    <string name="page_info" msgid="4048529256302257195">"Информация о странице"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Адрес:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Угроза безопасности"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Просмотреть сертификат"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Этот сертификат получен из ненадежных источников."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Название сайта не соответствует названию в сертификате."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Срок действия сертификата истек."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Сертификат еще не действителен."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Дата этого сертификата недействительна."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Этот сертификат недействителен."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Неизвестная ошибка сертификата."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-sk/strings.xml b/packages/CaptivePortalLogin/res/values-sk/strings.xml
index 54763be..8ba24b1 100644
--- a/packages/CaptivePortalLogin/res/values-sk/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sk/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Sieť, ku ktorej sa pokúšate pripojiť, má problémy so zabezpečením"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Napríklad prihlasovacia stránka nemusí patriť uvedenej organizácii."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Pokračovať pomocou prehliadača"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Informácie o stránke"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adresa:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Upozornenie zabezpečenia"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Zobraziť certifikát"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Tento certifikát nepochádza od dôveryhodnej autority."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Názov stránky sa nezhoduje s názvom uvedeným v certifikáte."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Platnosť certifikátu skončila."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Tento certifikát zatiaľ nie je platný."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Tento certifikát má neplatný dátum."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Tento certifikát je neplatný."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Neznáma chyba certifikátu."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-sl/strings.xml b/packages/CaptivePortalLogin/res/values-sl/strings.xml
index 7dd0b37..b7d9a8a 100644
--- a/packages/CaptivePortalLogin/res/values-sl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sl/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Omrežje, ki se mu poskušate pridružiti, ima varnostne težave."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Stran za prijavo na primer morda ne pripada prikazani organizaciji."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Vseeno nadaljuj v brskalniku"</string>
+    <string name="ok" msgid="1509280796718850364">"V redu"</string>
+    <string name="page_info" msgid="4048529256302257195">"Podatki o strani"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Naslov:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Varnostno opozorilo"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Prikaži potrdilo"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Potrdila ni izdal zaupanja vreden overitelj."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Ime spletnega mesta se ne ujema z imenom na potrdilu."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Potrdilo je poteklo."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"To potrdilo še ni veljavno."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Potrdilo ima neveljaven datum."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"To potrdilo ni veljavno."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Neznana napaka potrdila."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-sr/strings.xml b/packages/CaptivePortalLogin/res/values-sr/strings.xml
index f604289..967c8ba 100644
--- a/packages/CaptivePortalLogin/res/values-sr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sr/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Мрежа којој покушавате да се придружите има безбедносних проблема."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"На пример, страница за пријављивање можда не припада приказаној организацији."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Ипак настави преко прегледача"</string>
+    <string name="ok" msgid="1509280796718850364">"Потврди"</string>
+    <string name="page_info" msgid="4048529256302257195">"Информације о страници"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Адреса:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Безбедносно упозорење"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Прикажи сертификат"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Овај сертификат не потиче од поузданог ауторитета."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Назив сајта се не подудара са називом на сертификату."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Овај сертификат је истекао."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Овај сертификат још увек није важећи."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Датум овог сертификата је неважећи."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Овај сертификат је неважећи."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Непозната грешка сертификата."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-sv/strings.xml b/packages/CaptivePortalLogin/res/values-sv/strings.xml
index 8cf7041..75356f0 100644
--- a/packages/CaptivePortalLogin/res/values-sv/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sv/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Nätverket du försöker ansluta till har säkerhetsproblem."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Det kan t.ex. hända att inloggningssidan inte tillhör den organisation som visas."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Fortsätt ändå via webbläsaren"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Sidinformation"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adress:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Säkerhetsvarning"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visa certifikat"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Certifikatet kommer inte från en betrodd utfärdare."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Webbplatsens namn stämmer inte med namnet på certifikatet."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Certifikatet har upphört att gälla."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Certifikatet är inte giltigt än."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Det här certifikatet har ett ogiltigt datum."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Certifikatet är ogiltigt."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Okänt certifikatfel."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-sw/strings.xml b/packages/CaptivePortalLogin/res/values-sw/strings.xml
index 1c8b6e1..feb2dde 100644
--- a/packages/CaptivePortalLogin/res/values-sw/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sw/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Mtandao unaojaribu kujiunga nao una matatizo ya usalama."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Kwa mfano, ukurasa wa kuingia katika akaunti unaweza usiwe unamilikiwa na shirika lililoonyeshwa."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Endelea hata hivyo kupitia kivinjari"</string>
+    <string name="ok" msgid="1509280796718850364">"Sawa"</string>
+    <string name="page_info" msgid="4048529256302257195">"Maelezo ya ukurasa"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Anwani:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Ilani ya usalama"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Tazama cheti"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Cheti hiki hakijatoka kwa mamlaka inayoaminika."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Jina la tovuti halilingani na jina lililo katika cheti."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Cheti hiki kimepitwa na muda"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Cheti bado si halali."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Cheti hiki kina tarehe batili."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Hati hii ni batili."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Hitilafu isiyojulikana ya cheti."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-th/strings.xml b/packages/CaptivePortalLogin/res/values-th/strings.xml
index 9a3a626..11a2131 100644
--- a/packages/CaptivePortalLogin/res/values-th/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-th/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"เครือข่ายที่คุณพยายามเข้าร่วมมีปัญหาด้านความปลอดภัย"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"ตัวอย่างเช่น หน้าเข้าสู่ระบบอาจไม่ใช่ขององค์กรที่แสดงไว้"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ดำเนินการต่อผ่านเบราว์เซอร์"</string>
+    <string name="ok" msgid="1509280796718850364">"ตกลง"</string>
+    <string name="page_info" msgid="4048529256302257195">"ข้อมูลหน้าเว็บ"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"ที่อยู่:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"คำเตือนเกี่ยวกับความปลอดภัย"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"ดูใบรับรอง"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"ใบรับรองนี้ไม่ได้มาจากผู้ออกที่เชื่อถือได้"</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"ชื่อไซต์ไม่ตรงกับในใบรับรอง"</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"ใบรับรองนี้หมดอายุแล้ว"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"ใบรับรองนี้ยังใช้งานไม่ได้"</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"ใบรับรองนี้มีวันที่ไม่ถูกต้อง"</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"ใบรับรองนี้ไม่ถูกต้อง"</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"ข้อผิดพลาดใบรับรองที่ไม่รู้จัก"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-tl/strings.xml b/packages/CaptivePortalLogin/res/values-tl/strings.xml
index 565ef8f..07a2479 100644
--- a/packages/CaptivePortalLogin/res/values-tl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-tl/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"May mga isyu sa seguridad ang network kung saan mo sinusubukang sumali."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Halimbawa, maaaring hindi sa organisasyong ipinapakita ang page sa pag-log in."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Magpatuloy pa rin sa pamamagitan ng browser"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Impormasyon ng pahina"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Address:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Babala sa seguridad"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Tingnan ang certificate"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ang certificate ay hindi mula sa isang pinagkakatiwalaang kinauukulan."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Ang pangalan ng site ay hindi tumutugma sa pangalan sa certificate."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Nag-expire na ang certificate na ito."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Wala pang bisa ang certificate na ito."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Ang certificate ay mayroong di-wastong petsa."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Di-wasto ang certificate na ito."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Hindi kilalang error ng certificate."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-tr/strings.xml b/packages/CaptivePortalLogin/res/values-tr/strings.xml
index 73d2455..cdedd33 100644
--- a/packages/CaptivePortalLogin/res/values-tr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-tr/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Katılmaya çalıştığınız ağda güvenlik sorunları var."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Örneğin, giriş sayfası, gösterilen kuruluşa ait olmayabilir."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Yine de tarayıcıyla devam et"</string>
+    <string name="ok" msgid="1509280796718850364">"Tamam"</string>
+    <string name="page_info" msgid="4048529256302257195">"Sayfa bilgileri"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Güvenlik uyarısı"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Sertifikayı görüntüle"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Bu sertifika güvenilir bir yetkiliden değil."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Sitenin adı sertifika üzerindeki adla eşleşmiyor."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Bu sertifikanın süresi dolmuş."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Bu sertifika henüz geçerli değil."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Bu sertifikanın tarihi geçersiz."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Bu sertifika geçersiz."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Bilinmeyen sertifika hatası."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-uk/strings.xml b/packages/CaptivePortalLogin/res/values-uk/strings.xml
index 0e818d3..0f4cd16 100644
--- a/packages/CaptivePortalLogin/res/values-uk/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-uk/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"У мережі, до якої ви намагаєтеся під’єднатись, є проблеми з безпекою."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Наприклад, сторінка входу може не належати вказаній організації."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Усе одно продовжити у веб-переглядачі"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Інфо про стор."</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Адреса:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Застереж. про небезп."</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Переглянути сертиф."</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Сертифікат видано ненадійним центром сертифікації."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Назва сайту не збігається з назвою в сертифікаті."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Термін дії сертиф. завершився."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Цей сертифікат ще не дійсний."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Цей сертифікат має недійсну дату."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Цей сертифікат недійсний."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Помилка невідомого сертифіката."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-vi/strings.xml b/packages/CaptivePortalLogin/res/values-vi/strings.xml
index e51d2aa..9c702b9 100644
--- a/packages/CaptivePortalLogin/res/values-vi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-vi/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Mạng mà bạn đang cố gắng tham gia có vấn đề về bảo mật."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Ví dụ, trang đăng nhập có thể không thuộc về tổ chức được hiển thị."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Vẫn tiếp tục qua trình duyệt"</string>
+    <string name="ok" msgid="1509280796718850364">"OK"</string>
+    <string name="page_info" msgid="4048529256302257195">"Thông tin trang"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Địa chỉ:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Cảnh báo bảo mật"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Xem chứng chỉ"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Chứng chỉ này không xuất phát từ tổ chức phát hành đáng tin cậy."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Tên của trang web không khớp với tên trên chứng chỉ."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Chứng chỉ này đã hết hạn."</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Chứng chỉ này chưa hợp lệ."</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Chứng chỉ này có ngày không hợp lệ."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Chứng chỉ này không hợp lệ."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Lỗi chứng chỉ không xác định."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml b/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml
index ce822e7..70c2a08 100644
--- a/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"您尝试加入的网络存在安全问题。"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"例如,登录页面可能并不属于页面上显示的单位。"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"仍然通过浏览器继续操作"</string>
+    <string name="ok" msgid="1509280796718850364">"确定"</string>
+    <string name="page_info" msgid="4048529256302257195">"网页信息"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"网址:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"安全警告"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"查看证书"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"该证书并非来自可信的授权中心。"</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"网站的名称与证书上的名称不一致。"</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"该证书已过期。"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"该证书尚未生效。"</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"该证书的日期无效。"</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"该证书无效。"</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"未知证书错误。"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml b/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml
index 9010e1e..df1c700 100644
--- a/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"您正在嘗試加入的網絡有安全性問題。"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"例如,登入頁面並不屬於所顯示的機構。"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"透過瀏覽器繼續"</string>
+    <string name="ok" msgid="1509280796718850364">"確定"</string>
+    <string name="page_info" msgid="4048529256302257195">"網頁資訊"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"地址:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"安全性警告"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"查看憑證"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"這個憑證並非由受信任的權威機構發出。"</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"網站名稱與憑證上的名稱不相符。"</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"這個憑證已過期。"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"這個憑證尚未生效。"</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"此憑證的日期無效。"</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"此憑證是無效的。"</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"不明的憑證錯誤。"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml b/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml
index 5b535e2..2a2e397 100644
--- a/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"你嘗試加入的網路有安全問題。"</string>
     <string name="ssl_error_example" msgid="647898534624078900">"例如,登入網頁中顯示的機構可能並非該網頁實際隸屬的機構。"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"透過瀏覽器繼續"</string>
+    <string name="ok" msgid="1509280796718850364">"確定"</string>
+    <string name="page_info" msgid="4048529256302257195">"頁面資訊"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"位址:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"安全性警告"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"檢視憑證"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"這個憑證並非來自信任的授權單位。"</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"網站名稱與憑證上的名稱不相符。"</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"此憑證已過期"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"這個憑證尚未生效。"</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"這個憑證的日期無效。"</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"這個憑證無效。"</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"不明的憑證錯誤。"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-zu/strings.xml b/packages/CaptivePortalLogin/res/values-zu/strings.xml
index 866ba18..7943645 100644
--- a/packages/CaptivePortalLogin/res/values-zu/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zu/strings.xml
@@ -9,4 +9,16 @@
     <string name="ssl_error_warning" msgid="6653188881418638872">"Inethiwekhi ozama ukuyijoyina inezinkinga zokuvikela."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"Isibonelo, ikhasi lokungena ngemvume kungenzeka lingelenhlangano ebonisiwe."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"Qhubeka noma kunjalo ngesiphequluli"</string>
+    <string name="ok" msgid="1509280796718850364">"KULUNGILE"</string>
+    <string name="page_info" msgid="4048529256302257195">"Ulwazi lekhasi"</string>
+    <string name="page_info_address" msgid="2222306609532903254">"Ikheli:"</string>
+    <string name="ssl_security_warning_title" msgid="6607795404322797541">"Isexwayiso sokuvikeleka"</string>
+    <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Buka isitifiketi"</string>
+    <string name="ssl_error_untrusted" msgid="7754507359360636447">"Lesi sitifiketi asiphumi embusweni othembekile."</string>
+    <string name="ssl_error_mismatch" msgid="3809794439740523641">"Igama lale ngosi alifani negama elikusitifiketi."</string>
+    <string name="ssl_error_expired" msgid="5739349389499575559">"Lesi sitifiketi siphelelwe yisikhathi"</string>
+    <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Lesi sitifiketi asilungile okwamanje"</string>
+    <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Lesi sitifiketi sinosuku olungalungile."</string>
+    <string name="ssl_error_invalid" msgid="9041704741505449967">"Lesi sitifiketi asilungile."</string>
+    <string name="ssl_error_unknown" msgid="5679243486524754571">"Iphutha lesitifiketi elingaziwa."</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values/strings.xml b/packages/CaptivePortalLogin/res/values/strings.xml
index f486fe4..e9698db 100644
--- a/packages/CaptivePortalLogin/res/values/strings.xml
+++ b/packages/CaptivePortalLogin/res/values/strings.xml
@@ -9,5 +9,17 @@
     <string name="ssl_error_warning">The network you&#8217;re trying to join has security issues.</string>
     <string name="ssl_error_example">For example, the login page may not belong to the organization shown.</string>
     <string name="ssl_error_continue">Continue anyway via browser</string>
+    <string name="ssl_error_untrusted">This certificate isn\'t from a trusted authority.</string>
+    <string name="ssl_error_mismatch">The name of the site doesn\'t match the name on the certificate.</string>
+    <string name="ssl_error_expired">This certificate has expired.</string>
+    <string name="ssl_error_not_yet_valid">This certificate isn\'t valid yet.</string>
+    <string name="ssl_error_date_invalid">This certificate has an invalid date.</string>
+    <string name="ssl_error_invalid">This certificate is invalid.</string>
+    <string name="ssl_error_unknown">Unknown certificate error.</string>
+    <string name="ssl_security_warning_title">Security warning</string>
+    <string name="ssl_error_view_certificate">View certificate</string>
+    <string name="ok">OK</string>
+    <string name="page_info_address">Address:</string>
+    <string name="page_info">Page info</string>
 
 </resources>
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 0ba37ae..83084c5 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -20,8 +20,10 @@
 import static android.net.captiveportal.CaptivePortalProbeSpec.HTTP_LOCATION_HEADER_NAME;
 
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.app.LoadedApk;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.net.CaptivePortal;
@@ -33,6 +35,7 @@
 import android.net.Proxy;
 import android.net.Uri;
 import android.net.captiveportal.CaptivePortalProbeSpec;
+import android.net.http.SslCertificate;
 import android.net.http.SslError;
 import android.net.wifi.WifiInfo;
 import android.os.Build;
@@ -42,8 +45,9 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
-import android.util.TypedValue;
 import android.util.SparseArray;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -52,8 +56,8 @@
 import android.webkit.WebChromeClient;
 import android.webkit.WebSettings;
 import android.webkit.WebView;
-import android.webkit.WebView;
 import android.webkit.WebViewClient;
+import android.widget.LinearLayout;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
@@ -276,6 +280,13 @@
     @Override
     public void onDestroy() {
         super.onDestroy();
+        final WebView webview = (WebView) findViewById(R.id.webview);
+        if (webview != null) {
+            webview.stopLoading();
+            webview.setWebViewClient(null);
+            webview.setWebChromeClient(null);
+            webview.destroy();
+        }
         if (mNetworkCallback != null) {
             // mNetworkCallback is not null if mUrl is not null.
             mCm.unregisterNetworkCallback(mNetworkCallback);
@@ -382,6 +393,7 @@
         private static final String INTERNAL_ASSETS = "file:///android_asset/";
 
         private final String mBrowserBailOutToken = Long.toString(new Random().nextLong());
+        private final String mCertificateOutToken = Long.toString(new Random().nextLong());
         // How many Android device-independent-pixels per scaled-pixel
         // dp/sp = (px/sp) / (px/dp) = (1/sp) / (1/dp)
         private final float mDpPerSp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 1,
@@ -397,6 +409,10 @@
             return mPagesLoaded > 1;
         }
 
+        private String mSslErrorTitle = null;
+        private SslErrorHandler mSslErrorHandler = null;
+        private SslError mSslError = null;
+
         @Override
         public void onPageStarted(WebView view, String urlString, Bitmap favicon) {
             if (urlString.contains(mBrowserBailOutToken)) {
@@ -473,12 +489,16 @@
             logMetricsEvent(MetricsEvent.CAPTIVE_PORTAL_LOGIN_ACTIVITY_SSL_ERROR);
             final String sslErrorPage = makeSslErrorPage();
             view.loadDataWithBaseURL(INTERNAL_ASSETS, sslErrorPage, "text/HTML", "UTF-8", null);
+            mSslErrorTitle = view.getTitle() == null ? "" : view.getTitle();
+            mSslErrorHandler = handler;
+            mSslError = error;
         }
 
         private String makeSslErrorPage() {
             final String warningMsg = getString(R.string.ssl_error_warning);
             final String exampleMsg = getString(R.string.ssl_error_example);
             final String continueMsg = getString(R.string.ssl_error_continue);
+            final String certificateMsg = getString(R.string.ssl_error_view_certificate);
             return String.join("\n",
                     "<html>",
                     "<head>",
@@ -516,13 +536,18 @@
                     "      text-decoration:none;",
                     "      text-transform:uppercase;",
                     "    }",
+                    "    a.certificate {",
+                    "      margin-top:0px;",
+                    "    }",
                     "  </style>",
                     "</head>",
                     "<body>",
                     "  <p><img src=quantum_ic_warning_amber_96.png><br>",
                     "  <div class=warn>" + warningMsg + "</div>",
                     "  <div class=example>" + exampleMsg + "</div>",
-                    "  <a href=" + mBrowserBailOutToken + ">" + continueMsg + "</a>",
+                    "  <a href=" + mBrowserBailOutToken + ">" + continueMsg + "</a><br>",
+                    "  <a class=certificate href=" + mCertificateOutToken + ">" + certificateMsg +
+                            "</a>",
                     "</body>",
                     "</html>");
         }
@@ -533,8 +558,50 @@
                 startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
                 return true;
             }
+            if (url.contains(mCertificateOutToken) && mSslError != null) {
+                showSslAlertDialog(mSslErrorHandler, mSslError, mSslErrorTitle);
+                return true;
+            }
             return false;
         }
+        private void showSslAlertDialog(SslErrorHandler handler, SslError error, String title) {
+            final LayoutInflater factory = LayoutInflater.from(CaptivePortalLoginActivity.this);
+            final View sslWarningView = factory.inflate(R.layout.ssl_warning, null);
+
+            // Set Security certificate
+            setViewSecurityCertificate(sslWarningView.findViewById(R.id.certificate_layout), error);
+            ((TextView) sslWarningView.findViewById(R.id.ssl_error_type))
+                    .setText(sslErrorName(error));
+            ((TextView) sslWarningView.findViewById(R.id.title)).setText(mSslErrorTitle);
+            ((TextView) sslWarningView.findViewById(R.id.address)).setText(error.getUrl());
+
+            AlertDialog sslAlertDialog = new AlertDialog.Builder(CaptivePortalLoginActivity.this)
+                    .setTitle(R.string.ssl_security_warning_title)
+                    .setView(sslWarningView)
+                    .setPositiveButton(R.string.ok, (DialogInterface dialog, int whichButton) -> {
+                        // handler.cancel is called via OnCancelListener.
+                        dialog.cancel();
+                    })
+                    .setOnCancelListener((DialogInterface dialogInterface) -> handler.cancel())
+                    .create();
+            sslAlertDialog.show();
+        }
+
+        private void setViewSecurityCertificate(LinearLayout certificateLayout, SslError error) {
+            SslCertificate cert = error.getCertificate();
+
+            View certificateView = cert.inflateCertificateView(CaptivePortalLoginActivity.this);
+            final LinearLayout placeholder = (LinearLayout) certificateView
+                    .findViewById(com.android.internal.R.id.placeholder);
+            LayoutInflater factory = LayoutInflater.from(CaptivePortalLoginActivity.this);
+
+            TextView textView = (TextView) factory.inflate(
+                    R.layout.ssl_error_msg, placeholder, false);
+            textView.setText(sslErrorMessage(error));
+            placeholder.addView(textView);
+
+            certificateLayout.addView(certificateView);
+        }
     }
 
     private class MyWebChromeClient extends WebChromeClient {
@@ -587,4 +654,18 @@
     private static String sslErrorName(SslError error) {
         return SSL_ERRORS.get(error.getPrimaryError(), "UNKNOWN");
     }
+
+    private static final SparseArray<Integer> SSL_ERROR_MSGS = new SparseArray<>();
+    static {
+        SSL_ERROR_MSGS.put(SslError.SSL_NOTYETVALID,  R.string.ssl_error_not_yet_valid);
+        SSL_ERROR_MSGS.put(SslError.SSL_EXPIRED,      R.string.ssl_error_expired);
+        SSL_ERROR_MSGS.put(SslError.SSL_IDMISMATCH,   R.string.ssl_error_mismatch);
+        SSL_ERROR_MSGS.put(SslError.SSL_UNTRUSTED,    R.string.ssl_error_untrusted);
+        SSL_ERROR_MSGS.put(SslError.SSL_DATE_INVALID, R.string.ssl_error_date_invalid);
+        SSL_ERROR_MSGS.put(SslError.SSL_INVALID,      R.string.ssl_error_invalid);
+    }
+
+    private static Integer sslErrorMessage(SslError error) {
+        return SSL_ERROR_MSGS.get(error.getPrimaryError(), R.string.ssl_error_unknown);
+    }
 }
diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp
index 1b1bf8d..8f13497 100644
--- a/packages/CarSystemUI/Android.bp
+++ b/packages/CarSystemUI/Android.bp
@@ -30,7 +30,7 @@
         "SystemUIPluginLib",
         "SystemUISharedLib",
         "SettingsLib",
-        "android.car.user",
+        "android.car.userlib",
         "androidx.car_car",
         "androidx.legacy_legacy-support-v4",
         "androidx.recyclerview_recyclerview",
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index ddc00e3..60153fc 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -78,8 +78,6 @@
 public class Assistant extends NotificationAssistantService {
     private static final String TAG = "ExtAssistant";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    public static final boolean AUTO_DEMOTE_NOTIFICATIONS = SystemProperties.getBoolean(
-            "debug.demote_notifs", false);
     public static final boolean AGE_NOTIFICATIONS = SystemProperties.getBoolean(
             "debug.age_notifs", false);
 
@@ -236,13 +234,14 @@
             @NonNull ArrayList<CharSequence> smartReplies) {
         Bundle signals = new Bundle();
 
-        if (AUTO_DEMOTE_NOTIFICATIONS) {
-            if (!smartActions.isEmpty()) {
-                signals.putParcelableArrayList(Adjustment.KEY_SMART_ACTIONS, smartActions);
-            }
-            if (!smartReplies.isEmpty()) {
-                signals.putCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES, smartReplies);
-            }
+        if (!smartActions.isEmpty()) {
+            signals.putParcelableArrayList(Adjustment.KEY_SMART_ACTIONS, smartActions);
+        }
+        if (!smartReplies.isEmpty()) {
+            signals.putCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES, smartReplies);
+        }
+        if (Settings.Secure.getInt(getContentResolver(),
+                Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL, 0) == 1) {
             if (mNotificationCategorizer.shouldSilence(entry)) {
                 final int importance = entry.getImportance() < IMPORTANCE_LOW
                         ? entry.getImportance() : IMPORTANCE_LOW;
diff --git a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
index 8fee822..6f437bd5 100644
--- a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
+++ b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
@@ -15,6 +15,7 @@
  */
 package android.ext.services.notification;
 
+import static android.app.Notification.CATEGORY_MESSAGE;
 import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
@@ -148,6 +149,18 @@
         return Objects.equals(getNotification().category, category);
     }
 
+    /**
+     * Similar to {@link #isCategory(String)}, but checking the public version of the notification,
+     * if available.
+     */
+    public boolean isPublicVersionCategory(String category) {
+        Notification publicVersion = getNotification().publicVersion;
+        if (publicVersion == null) {
+            return false;
+        }
+        return Objects.equals(publicVersion.category, category);
+    }
+
     public boolean isAudioAttributesUsage(int usage) {
         return mAttributes != null && mAttributes.getUsage() == usage;
     }
@@ -175,9 +188,9 @@
     }
 
     protected boolean isMessaging() {
-        return isCategory(Notification.CATEGORY_MESSAGE)
-                || hasStyle(Notification.MessagingStyle.class)
-                || hasInlineReply();
+        return isCategory(CATEGORY_MESSAGE)
+                || isPublicVersionCategory(CATEGORY_MESSAGE)
+                || hasStyle(Notification.MessagingStyle.class);
     }
 
     public boolean hasInlineReply() {
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index 37a98fd..b2fc417 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -19,23 +19,22 @@
 import android.annotation.Nullable;
 import android.app.Notification;
 import android.app.RemoteAction;
-import android.app.RemoteInput;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.Process;
-import android.os.SystemProperties;
-import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.view.textclassifier.ConversationActions;
 import android.view.textclassifier.TextClassification;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textclassifier.TextClassifier;
 import android.view.textclassifier.TextLinks;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
 
 public class SmartActionsHelper {
     private static final ArrayList<Notification.Action> EMPTY_ACTION_LIST = new ArrayList<>();
@@ -50,12 +49,18 @@
     private static final int MAX_ACTION_EXTRACTION_TEXT_LENGTH = 400;
     private static final int MAX_ACTIONS_PER_LINK = 1;
     private static final int MAX_SMART_ACTIONS = Notification.MAX_ACTION_BUTTONS;
-    // Allow us to test out smart reply with dumb suggestions, it is disabled by default.
-    // TODO: Removed this once we have the model.
-    private static final String SYS_PROP_SMART_REPLIES_EXPERIMENT =
-            "persist.sys.smart_replies_experiment";
+    private static final int MAX_SUGGESTED_REPLIES = 3;
 
-    SmartActionsHelper() {}
+    private static final ConversationActions.TypeConfig TYPE_CONFIG =
+            new ConversationActions.TypeConfig.Builder().setIncludedTypes(
+                    Collections.singletonList(ConversationActions.TYPE_TEXT_REPLY))
+                    .includeTypesFromTextClassifier(false)
+                    .build();
+    private static final List<String> HINTS =
+            Collections.singletonList(ConversationActions.HINT_FOR_NOTIFICATION);
+
+    SmartActionsHelper() {
+    }
 
     /**
      * Adds action adjustments based on the notification contents.
@@ -92,8 +97,31 @@
         if (context == null) {
             return EMPTY_REPLY_LIST;
         }
-        // TODO: replaced this with our model when it is ready.
-        return new ArrayList<>(Arrays.asList("Yes, please", "No, thanks"));
+        TextClassificationManager tcm = context.getSystemService(TextClassificationManager.class);
+        if (tcm == null) {
+            return EMPTY_REPLY_LIST;
+        }
+        CharSequence text = getMostSalientActionText(entry.getNotification());
+        ConversationActions.Message message =
+                new ConversationActions.Message.Builder()
+                        .setText(text)
+                        .build();
+
+        ConversationActions.Request request =
+                new ConversationActions.Request.Builder(Collections.singletonList(message))
+                        .setMaxSuggestions(MAX_SUGGESTED_REPLIES)
+                        .setHints(HINTS)
+                        .setTypeConfig(TYPE_CONFIG)
+                        .build();
+
+        TextClassifier textClassifier = tcm.getTextClassifier();
+        List<ConversationActions.ConversationAction> conversationActions =
+                textClassifier.suggestConversationActions(request).getConversationActions();
+
+        return conversationActions.stream()
+                .map(conversationAction -> conversationAction.getTextReply())
+                .filter(textReply -> !TextUtils.isEmpty(textReply))
+                .collect(Collectors.toCollection(ArrayList::new));
     }
 
     /**
@@ -124,20 +152,30 @@
     }
 
     private boolean isEligibleForReplyAdjustment(@NonNull NotificationEntry entry) {
-        if (!SystemProperties.getBoolean(SYS_PROP_SMART_REPLIES_EXPERIMENT, false)) {
+        if (!Process.myUserHandle().equals(entry.getSbn().getUser())) {
             return false;
         }
-        Notification notification = entry.getNotification();
-        if (notification.actions == null) {
+        String pkg = entry.getSbn().getPackageName();
+        if (TextUtils.isEmpty(pkg) || pkg.equals("android")) {
             return false;
         }
-        return entry.hasInlineReply();
+        // For now, we are only interested in messages.
+        if (!entry.isMessaging()) {
+            return false;
+        }
+        // Does not make sense to provide suggested replies if it is not something that can be
+        // replied.
+        if (!entry.hasInlineReply()) {
+            return false;
+        }
+        return true;
     }
 
     /** Returns the text most salient for action extraction in a notification. */
     @Nullable
     private CharSequence getMostSalientActionText(@NonNull Notification notification) {
         /* If it's messaging style, use the most recent message. */
+        // TODO: Use the last few X messages instead and take the Person object into consideration.
         Parcelable[] messages = notification.extras.getParcelableArray(Notification.EXTRA_MESSAGES);
         if (messages != null && messages.length != 0) {
             Bundle lastMessage = (Bundle) messages[messages.length - 1];
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 4e52ff6d..c9ee5c8 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -186,7 +186,8 @@
                     title = mStorageManager.getBestVolumeDescription(privateVol);
                     storageUuid = StorageManager.convert(privateVol.fsUuid);
                 }
-            } else if (volume.getType() == VolumeInfo.TYPE_PUBLIC
+            } else if ((volume.getType() == VolumeInfo.TYPE_PUBLIC
+                            || volume.getType() == VolumeInfo.TYPE_STUB)
                     && volume.getMountUserId() == userId) {
                 rootId = volume.getFsUuid();
                 title = mStorageManager.getBestVolumeDescription(volume);
@@ -540,14 +541,14 @@
     }
 
     @Override
-    public Cursor querySearchDocuments(String rootId, String query, String[] projection)
+    public Cursor querySearchDocuments(String rootId, String[] projection, Bundle queryArgs)
             throws FileNotFoundException {
         final File parent;
         synchronized (mRootsLock) {
             parent = mRoots.get(rootId).path;
         }
 
-        return querySearchDocuments(parent, query, projection, Collections.emptySet());
+        return querySearchDocuments(parent, projection, Collections.emptySet(), queryArgs);
     }
 
     @Override
diff --git a/packages/PackageInstaller/res/values-pt-rPT/strings.xml b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
index d45dc1c..e27fed5 100644
--- a/packages/PackageInstaller/res/values-pt-rPT/strings.xml
+++ b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
@@ -41,7 +41,7 @@
     <string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Este utilizador não pode instalar aplicações desconhecidas."</string>
     <string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Este utilizador não tem autorização para instalar aplicações."</string>
     <string name="ok" msgid="7871959885003339302">"OK"</string>
-    <string name="manage_applications" msgid="5400164782453975580">"Gerir aplic."</string>
+    <string name="manage_applications" msgid="5400164782453975580">"Gerir app"</string>
     <string name="out_of_space_dlg_title" msgid="4156690013884649502">"Sem espaço"</string>
     <string name="out_of_space_dlg_text" msgid="8727714096031856231">"Não foi possível instalar a aplicação <xliff:g id="APP_NAME">%1$s</xliff:g>. Liberte algum espaço e tente novamente."</string>
     <string name="app_not_found_dlg_title" msgid="5107924008597470285">"Aplicação não encontrada"</string>
@@ -70,7 +70,7 @@
     <string name="uninstall_failed_device_policy_manager_of_user" msgid="4813104025494168064">"Não é possível desinstalar a aplicação de administração de dispositivos ativa para <xliff:g id="USERNAME">%1$s</xliff:g>."</string>
     <string name="uninstall_all_blocked_profile_owner" msgid="2009393666026751501">"Esta aplicação é necessária para alguns utilizadores ou perfis e foi desinstalada para outros."</string>
     <string name="uninstall_blocked_profile_owner" msgid="6373897407002404848">"O perfil necessita desta aplicação e não é possível desinstalá-la."</string>
-    <string name="uninstall_blocked_device_owner" msgid="6724602931761073901">"Esta aplic. é exigida pelo administrador do disp. e não pode ser desinstalada."</string>
+    <string name="uninstall_blocked_device_owner" msgid="6724602931761073901">"Esta app é exigida pelo administrador do disp. e não pode ser desinstalada."</string>
     <string name="manage_device_administrators" msgid="3092696419363842816">"Gerir aplicações de administração de dispositivos"</string>
     <string name="manage_users" msgid="1243995386982560813">"Gerir utilizadores"</string>
     <string name="uninstall_failed_msg" msgid="2176744834786696012">"Não foi possível desinstalar a aplicação <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java
index 1eb423e..74c7b58 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
+import android.provider.Settings;
 import android.util.Log;
 
 /**
@@ -29,11 +30,11 @@
     private static final String TAG = PackageInstalledReceiver.class.getSimpleName();
 
     private static final boolean DEBUG = false;
-    private static final boolean APP_INSTALLED_NOTIFICATION_ENABLED = false;
 
     @Override
     public void onReceive(Context context, Intent intent) {
-        if (!APP_INSTALLED_NOTIFICATION_ENABLED) {
+        if (Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED, 0) == 0) {
             return;
         }
 
diff --git a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
index 9c29ff2..5f0322f 100644
--- a/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
+++ b/packages/PrintSpooler/res/values-b+sr+Latn/strings.xml
@@ -86,7 +86,7 @@
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Greška štampača <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="blocked_notification_title_template" msgid="1175435827331588646">"Štampač je blokirao <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancel" msgid="4373674107267141885">"Otkaži"</string>
-    <string name="restart" msgid="2472034227037808749">"Ponovo pokreni"</string>
+    <string name="restart" msgid="2472034227037808749">"Restartuj"</string>
     <string name="no_connection_to_printer" msgid="2159246915977282728">"Nema veze sa štampačem"</string>
     <string name="reason_unknown" msgid="5507940196503246139">"nepoznato"</string>
     <string name="print_service_security_warning_title" msgid="2160752291246775320">"Želite li da koristite <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index cb23c3c..c2f99d9 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -86,7 +86,7 @@
     <string name="failed_notification_title_template" msgid="2256217208186530973">"Грешка штампача <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="blocked_notification_title_template" msgid="1175435827331588646">"Штампач је блокирао <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancel" msgid="4373674107267141885">"Откажи"</string>
-    <string name="restart" msgid="2472034227037808749">"Поново покрени"</string>
+    <string name="restart" msgid="2472034227037808749">"Рестартуј"</string>
     <string name="no_connection_to_printer" msgid="2159246915977282728">"Нема везе са штампачем"</string>
     <string name="reason_unknown" msgid="5507940196503246139">"непознато"</string>
     <string name="print_service_security_warning_title" msgid="2160752291246775320">"Желите ли да користите <xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index 5161344..d1f140f 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -9,6 +9,7 @@
         "androidx.preference_preference",
         "androidx.appcompat_appcompat",
         "androidx.lifecycle_lifecycle-runtime",
+        "androidx.mediarouter_mediarouter-nodeps",
 
         "SettingsLibHelpUtils",
         "SettingsLibRestrictedLockUtils",
diff --git a/packages/SettingsLib/SettingsSpinner/res/values/styles.xml b/packages/SettingsLib/SettingsSpinner/res/values/styles.xml
index 8447b08..8af20e2 100644
--- a/packages/SettingsLib/SettingsSpinner/res/values/styles.xml
+++ b/packages/SettingsLib/SettingsSpinner/res/values/styles.xml
@@ -17,7 +17,7 @@
 
 <resources>
     <style name="SettingsSpinnerTitleBar">
-        <item name="android:textAppearance">?android:attr/textAppearance</item>
+        <item name="android:textAppearance">?android:attr/textAppearanceButton</item>
         <item name="android:paddingStart">16dp</item>
         <item name="android:paddingEnd">36dp</item>
         <item name="android:paddingTop">8dp</item>
diff --git a/packages/SettingsLib/res/drawable/list_divider_dark.xml b/packages/SettingsLib/res/drawable/list_divider_dark.xml
deleted file mode 100644
index 5773d9e..0000000
--- a/packages/SettingsLib/res/drawable/list_divider_dark.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2017 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.
-  -->
-
-<shape
-    xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#64000000" />
-    <size
-        android:height="1dp"
-        android:width="1dp" />
-</shape>
diff --git a/packages/SettingsLib/res/layout/preference_two_target_divider.xml b/packages/SettingsLib/res/layout/preference_two_target_divider.xml
index 60efed4..b81dd83 100644
--- a/packages/SettingsLib/res/layout/preference_two_target_divider.xml
+++ b/packages/SettingsLib/res/layout/preference_two_target_divider.xml
@@ -27,5 +27,5 @@
     <View
         android:layout_width="1dp"
         android:layout_height="match_parent"
-        android:background="@drawable/list_divider_dark" />
+        android:background="?android:attr/listDivider" />
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index b77d4e5..d34820c 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Kan nie skandeer vir netwerke nie"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Geen"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Gestoor"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Gedeaktiveer"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-opstelling het misluk"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 836ec80..b595e2b 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ለአውታረመረቦች መቃኘት አይቻልም"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"የለም"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ተቀምጧል"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ተሰናክሏል"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"የአይ.ፒ. ውቅረት መሰናከል"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 83c4b8e..f8c2ba2 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"لا يمكن فحص الشبكات"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"بدون"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"تم الحفظ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"غير مفعّلة"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‏تعذّرت تهيئة عنوان IP"</string>
@@ -227,11 +226,11 @@
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"‏اختيار برنامج ترميز LDAC\nلصوت مشغّل البلوتوث: جودة التشغيل"</string>
     <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"البث: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"نظام أسماء النطاقات الخاص"</string>
-    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"اختر وضع نظام أسماء النطاقات الخاص"</string>
+    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"تحديد وضع \"نظام أسماء النطاقات الخاص\""</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"غير مفعّل"</string>
     <string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"تلقائي"</string>
-    <string name="private_dns_mode_provider" msgid="8354935160639360804">"اسم مضيف مزوّد نظام أسماء النطاقات الخاص"</string>
-    <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"أدخل اسم مضيف مزوّد نظام أسماء النطاقات"</string>
+    <string name="private_dns_mode_provider" msgid="8354935160639360804">"اسم مضيف مزوّد \"نظام أسماء النطاقات الخاص\""</string>
+    <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"يُرجى إدخال اسم مضيف \"مزوّد نظام أسماء النطاقات\""</string>
     <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"تعذّر الاتصال"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"عرض خيارات شهادة عرض شاشة لاسلكي"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"‏زيادة مستوى تسجيل Wi-Fi، وعرض لكل SSID RSSI في منتقي Wi-Fi"</string>
@@ -371,10 +370,10 @@
     <string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا، بناءً على استخدامك"</string>
     <string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"يتبقى <xliff:g id="TIME_REMAINING">%1$s</xliff:g> تقريبًا، بناءً على استخدامك (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"الوقت المتبقي: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"من المفترض أن يستمر شحن البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
-    <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"من المفترض أن يستمر شحن البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك."</string>
-    <string name="power_discharge_by" msgid="6453537733650125582">"من المفترض أن يستمر شحن البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
-    <string name="power_discharge_by_only" msgid="107616694963545745">"من المفترض أن يستمر شحن البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g>."</string>
+    <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
+    <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> حسب استخدامك."</string>
+    <string name="power_discharge_by" msgid="6453537733650125582">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
+    <string name="power_discharge_by_only" msgid="107616694963545745">"قد تكفي طاقة البطارية حتى حوالي الساعة <xliff:g id="TIME">%1$s</xliff:g>."</string>
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"يتبقى أقل من <xliff:g id="THRESHOLD">%1$s</xliff:g>."</string>
     <string name="power_remaining_less_than_duration" msgid="5751885147712659423">"يتبقى أقل من <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
     <string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"يتبقى أكثر من <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index ddd17daf..72122c2 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"নেটৱৰ্ক বিচাৰি স্কেন কৰিব পৰা নাই"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"নাই"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ছেভ কৰি থোৱা নেটৱৰ্কসমূহ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"নিষ্ক্ৰিয় হৈ আছে"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP কনফিগাৰেশ্বন বিফল হৈছে"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index a6e484f..23008e2 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Şəbəkə axtarmaq olmur"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Heç biri"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Yadda saxlanılan"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiv"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Konfiqurasiya Uğursuzluğu"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index a446845..3ee8589 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -21,13 +21,12 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nije moguće skenirati mreže"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Sačuvano"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfiguracija je otkazala"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Nije povezano zbog lošeg kvaliteta mreže"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi veza je otkazala"</string>
-    <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem sa potvrdom autentičnosti"</string>
+    <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem sa potvrdom identiteta"</string>
     <string name="wifi_cant_connect" msgid="5410016875644565884">"Povezivanje nije uspelo"</string>
     <string name="wifi_cant_connect_to_ap" msgid="1222553274052685331">"Povezivanje sa „<xliff:g id="AP_NAME">%1$s</xliff:g>“ nije uspelo"</string>
     <string name="wifi_check_password_try_again" msgid="516958988102584767">"Proverite lozinku i probajte ponovo"</string>
@@ -448,5 +447,5 @@
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Trajanje"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Uvek pitaj"</string>
     <string name="zen_mode_forever" msgid="2704305038191592967">"Dok ne isključite"</string>
-    <string name="time_unit_just_now" msgid="6363336622778342422">"Upravo sada"</string>
+    <string name="time_unit_just_now" msgid="6363336622778342422">"Upravo"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index d56db13..64253bf 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не атрымлiваецца выканаць сканаванне для сетак"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Няма"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Захавана"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Адключана"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Збой канфігурацыі IP"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index c1bc31c..668aa2d 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не може да се сканира за мрежи"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Няма"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Запазено"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Деактивирани"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Неуспешно конфигуриране на IP адреса"</string>
@@ -374,7 +373,7 @@
     <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> въз основа на използването (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> въз основа на използването"</string>
     <string name="power_discharge_by" msgid="6453537733650125582">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
-    <string name="power_discharge_by_only" msgid="107616694963545745">"Следва да издържи приблизително до <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_only" msgid="107616694963545745">"Следва да издържи до около <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Остава/т по-малко от <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Остава/т по-малко от <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Остава/т повече от <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 1550c00..c6eed2c 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"নেটওয়ার্কগুলির জন্য স্ক্যান করা যাবে না"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"কোনো কিছুই নয়"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"সংরক্ষিত"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"অক্ষম হয়েছে"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP কনফিগারেশনের ব্যর্থতা"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 460e7cf..16179fb 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ne može skenirati mreže"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Sačuvano"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Greška u konfiguraciji IP-a"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 5638947..f906ea4 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"No es poden cercar xarxes"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Cap"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Desat"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desactivat"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuració d\'IP"</string>
@@ -70,7 +69,7 @@
     <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Actiu"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Àudio multimèdia"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Trucades telefòniques"</string>
-    <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferència del fitxer"</string>
+    <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transferència de fitxers"</string>
     <string name="bluetooth_profile_hid" msgid="3680729023366986480">"Dispositiu d\'entrada"</string>
     <string name="bluetooth_profile_pan" msgid="3391606497945147673">"Accés a Internet"</string>
     <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Compartir contactes"</string>
@@ -393,7 +392,7 @@
     <string name="battery_info_status_charging_lower" msgid="8689770213898117994">"s\'està carregant"</string>
     <string name="battery_info_status_discharging" msgid="310932812698268588">"No s\'està carregant"</string>
     <string name="battery_info_status_not_charging" msgid="8523453668342598579">"El dispositiu està endollat però en aquests moments no es pot carregar"</string>
-    <string name="battery_info_status_full" msgid="2824614753861462808">"Plena"</string>
+    <string name="battery_info_status_full" msgid="2824614753861462808">"Completa"</string>
     <string name="disabled_by_admin_summary_text" msgid="6750513964908334617">"Controlat per l\'administrador"</string>
     <string name="disabled" msgid="9206776641295849915">"Desactivat"</string>
     <string name="external_source_trusted" msgid="2707996266575928037">"Amb permís"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index de02245..f9c8669 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nelze hledat sítě"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Žádné"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Uloženo"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Vypnuto"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Selhání konfigurace protokolu IP"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 34608d3..6b2bd98 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Der kan ikke søges efter netværk"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ingen"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Gemt"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiveret"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurationsfejl"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 79965d2..ad6f5f2 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Netzwerkscan nicht möglich"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Keine"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Gespeichert"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Deaktiviert"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-Konfigurationsfehler"</string>
@@ -231,7 +230,7 @@
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Aus"</string>
     <string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatisch"</string>
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Hostname des privaten DNS-Anbieters"</string>
-    <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostnamen des DNS-Anbieters eingeben"</string>
+    <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostname des DNS-Anbieters eingeben"</string>
     <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Verbindung nicht möglich"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Optionen zur Zertifizierung für kabellose Übertragung anzeigen"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Level für WLAN-Protokollierung erhöhen, in WiFi Picker pro SSID-RSSI anzeigen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index b9ea843..5bfbf2c 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Δεν είναι δυνατή η σάρωση για δίκτυα"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Καμία"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Αποθηκευμένο"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Απενεργοποιημένο"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Αποτυχία διαμόρφωσης διεύθυνσης IP"</string>
@@ -231,7 +230,7 @@
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Ανενεργή"</string>
     <string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Αυτόματα"</string>
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Όνομα κεντρικού υπολογιστή παρόχου DNS"</string>
-    <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Εισαγάγετε το όνομα κεντρικού υπολογιστή του παρόχου DNS"</string>
+    <string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Όνομα κεντρικού υπολογιστή του παρόχου DNS"</string>
     <string name="private_dns_mode_provider_failure" msgid="231837290365031223">"Δεν ήταν δυνατή η σύνδεση"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Εμφάνιση επιλογών για πιστοποίηση ασύρματης οθόνης"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Αύξηση επιπέδου καταγ. Wi-Fi, εμφάνιση ανά SSID RSSI στο εργαλείο επιλογής Wi-Fi"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 1a7d7c5..f0eaeed 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 1a7d7c5..f0eaeed 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 1a7d7c5..f0eaeed 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 1a7d7c5..f0eaeed 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Can\'t scan for networks"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"None"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Saved"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disabled"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Configuration Failure"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 2bfd5b1..6927fda 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎Can\'t scan for networks‎‏‎‎‏‎"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‏‎‎‎‎‎‎None‎‏‎‎‏‎"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‎‎Saved‎‏‎‎‏‎"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‏‎‎Disabled‎‏‎‎‏‎"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‏‎‏‎‎‎IP Configuration Failure‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 790c0d3..675084f 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"No se pueden buscar las redes."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ninguna"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Guardada"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Inhabilitada"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuración IP"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 1dec85d..b51b847 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"No se puede buscar redes."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ninguna"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Guardado"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Inhabilitado"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Error de configuración de IP"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 406e15d..fb077be 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Võrke ei saa kontrollida"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Puudub"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Salvestatud"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Keelatud"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP seadistamise ebaõnnestumine"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index bd4724e..3d3b8c3 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ezin dira sareak bilatu"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Bat ere ez"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Gordeta"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desgaituta"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ezin izan da konfiguratu IP helbidea"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 45b8ac7..0af118e 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"اسکن شبکه‌ها امکان‌پذیر نیست"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"هیچ‌کدام"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ذخیره‌شده"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"غیرفعال شد"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‏پیکربندی IP انجام نشد"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 23c63b1..dde10d0d 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Verkkoja ei voi etsiä."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ei mitään"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Tallennettu"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Pois käytöstä"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-kokoonpanovirhe"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index ad99000..1257ea5 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Impossible de rechercher des réseaux."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Aucune"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Enregistré"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Désactivés"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Échec de configuration de l\'adresse IP"</string>
@@ -227,7 +226,7 @@
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Déclencher le codec audio Bluetooth LDAC\nSélection : qualité de lecture"</string>
     <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Diffusion : <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS privé"</string>
-    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Sélectionnez le mode DNS privé"</string>
+    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Sélectionner le mode DNS privé"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Désactivé"</string>
     <string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automatique"</string>
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nom d\'hôte du fournisseur DNS privé"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index c23db25..444a52e 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Impossible de rechercher des réseaux."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Aucune"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Enregistré"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Désactivé"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Échec de configuration de l\'adresse IP"</string>
@@ -70,7 +69,7 @@
     <string name="bluetooth_active_no_battery_level" msgid="8380223546730241956">"Actif"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"Multimédia"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"Appels téléphoniques"</string>
-    <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfert de fichier"</string>
+    <string name="bluetooth_profile_opp" msgid="9168139293654233697">"Transfert de fichiers"</string>
     <string name="bluetooth_profile_hid" msgid="3680729023366986480">"Périphérique d\'entrée"</string>
     <string name="bluetooth_profile_pan" msgid="3391606497945147673">"Accès Internet"</string>
     <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"Partage de contacts"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 46532e9..8df2697 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Non se poden explorar redes"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ningunha"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Gardada"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desactivadas"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Erro na configuración de IP"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 6a74490..4a92f2a 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"નેટવર્ક્સ માટે સ્કૅન કરી શકતા નથી"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"કોઈ નહીં"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"સાચવેલા"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"અક્ષમ કર્યો"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP કન્ફિગરેશન નિષ્ફળ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index bd9a6ec..6d88c35 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"नेटवर्क के लिए स्‍कैन नहीं कर सकता"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"कोई नहीं"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"सेव किया गया"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"अक्षम"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP कॉन्‍फ़िगरेशन की विफलता"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 5270531..32c9a62 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Skeniranje mreža nije moguće"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nema"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Spremljeno"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogućeno"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Konfiguracija IP-a nije uspjela"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index ad897f8..ed19267 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nem lehet beolvasni a hálózatokat"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nincs"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Mentve"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Letiltva"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurációs hiba"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 82755f9..6d516ea 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Հնարավոր չէ սկանավորել ցանցերը"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ոչ մեկը"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Պահված է"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Անջատված"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP կարգավորման ձախողում"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 961f892..a5f2317 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Tidak dapat memindai jaringan"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Tidak ada"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Disimpan"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Nonaktif"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Kegagalan Konfigurasi IP"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 759b7ba..6cf09a6 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ekki er hægt að leita að netum"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ekkert"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Vistað"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Óvirkt"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-stillingarvilla"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index bd41e28..a1b9b82 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Impossibile cercare reti"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nessuna"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Salvata"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Disattivata"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Errore configurazione IP"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 5da253c..1a50622 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"לא ניתן לסרוק לאיתור רשתות"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ללא"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"נשמר"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"מושבת"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‏כשל בתצורת IP"</string>
@@ -316,7 +315,7 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"מגבלה של תהליכים ברקע"</string>
     <string name="show_all_anrs" msgid="4924885492787069007">"‏הצגת מקרי ANR ברקע"</string>
     <string name="show_all_anrs_summary" msgid="6636514318275139826">"הצגת תיבת דו-שיח של \'אפליקציה לא מגיבה\' עבור אפליקציות שפועלות ברקע"</string>
-    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"אזהרות לגבי ערוץ הודעות"</string>
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"אזהרות לגבי ערוץ התראות"</string>
     <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"הצגת אזהרה כשאפליקציה שולחת התראה ללא ערוץ חוקי"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"אילוץ הרשאת אפליקציות באחסון חיצוני"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index f6b81ed..4c544af 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ネットワークをスキャンできません"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"なし"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"保存済み"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"無効"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP設定エラー"</string>
@@ -436,7 +435,7 @@
     <string name="cancel" msgid="6859253417269739139">"キャンセル"</string>
     <string name="okay" msgid="1997666393121016642">"OK"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"ON にする"</string>
-    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"マナーモードを ON にする"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"サイレント モードを ON にする"</string>
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"なし"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"優先的な通知のみ"</string>
     <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>。<xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index d5f5408..92f3049 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ქსელების სკანირება არა არის შესაძლებელი"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"არცერთი"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"დამახსოვრებულია"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"გამორთულია"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP კონფიგურაციის შეფერხება"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index c3fbfcd..b56c6fd 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Желілерді шолу мүмкін емес"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ешқандай"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Сақталды"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Өшірілген"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурациясының қатесі"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 8e73f81..5860473 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"មិន​អាច​វិភាគ​រក​បណ្ដាញ"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"គ្មាន"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"បាន​រក្សាទុក"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"បាន​បិទ"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"ការ​កំណត់​រចនាសម្ព័ន្ធ IP បរាជ័យ"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index ce225ea..87e18e6 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ನೆಟ್‌ವರ್ಕ್‌ಗಳಿಗಾಗಿ ಸ್ಕ್ಯಾನ್‌ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ಯಾವುದೂ ಇಲ್ಲ"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ಉಳಿಸಲಾಗಿದೆ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ಕಾನ್ಫಿಗರೇಶನ್ ವಿಫಲತೆ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index b47471b..3333c0d 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"네트워크를 검색할 수 없습니다."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"없음"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"저장됨"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"사용 중지됨"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 설정 실패"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 9853dac..cbbc47c 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Түйүндөрдү издөө мүмкүн эмес"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Жок"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Сакталды"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Өчүрүлгөн"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурациясы бузулду"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 1816515..21e4679 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ບໍ່ສາມາດກວດຫາເຄືອຂ່າຍໄດ້"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ບໍ່ໃຊ້"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ບັນ​ທຶກແລ້ວ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ປິດການນຳໃຊ້"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"ການ​ຕັ້ງ​ຄ່າ IP ລົ້ມ​ເຫຼວ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index e6a8e1c..cbff9e7 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nepavyksta nuskaityti tinklų"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nėra"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Išsaugotas"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Neleidžiama"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfigūracijos triktis"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index b55afc0..d200828 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nevar skenēt tīklus"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nav"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Saglabāts"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Atspējots"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP konfigurācijas kļūme"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index e28c8ee..db16847 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не може да скенира за мрежи"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ниедна"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Зачувано"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Оневозможено"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Конфигурирањето ИП не успеа"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 6860398..c3af968 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"നെ‌റ്റ്‌വർക്കുകൾക്കായി സ്കാൻ ചെയ്യാനായില്ല"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ഒന്നുമില്ല"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"സംരക്ഷിച്ചു"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"പ്രവർത്തനരഹിതമാക്കി"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP കോൺഫിഗറേഷൻ പരാജയം"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index ba6d601..8627e1b 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Сүлжээнүүдийг скан хийх боломжгүй"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Байхгүй"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Хадгалагдсан"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Идэвхгүйжүүлсэн"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP тохируулга амжилтгүй"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index a5d230a..cd7f175 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"नेटवर्कसाठी स्कॅन करू शकत नाही"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"काहीही नाही"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"सेव्ह केले"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"अक्षम"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP कॉन्फिगरेशन अयशस्वी"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index a7ac3ef..d0b2e12 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Tidak boleh mengimbas untuk rangkaian"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Tiada"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Disimpan"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Dinyahdayakan"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Kegagalan Konfigurasi IP"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 6cdab67..5f5957c 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ကွန်ယက်များကို စကင်မလုပ်နိုင်ပါ"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"တစ်ခုမျှ မဟုတ်ပါ"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"သိမ်းဆည်းပြီး"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ပိတ်ထားသည်"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ပြုပြင်ခြင်း မအောင်မြင်ပါ"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index cf18477..3c240f8 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Kan ikke søke etter nettverk"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ingen"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Lagret"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Slått av"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurasjonsfeil"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 8aba0f8..1699870 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"सञ्जालका लागि स्क्यान गर्न सक्दैन"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"कुनै पनि होइन"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"सुरक्षित गरियो"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"असक्षम पारियो"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP विन्यास असफल"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index e3f1aea..738df94 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Kan niet zoeken naar netwerken"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Geen"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Opgeslagen"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Uitgeschakeld"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-configuratie mislukt"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 8ecac4d..2d39cc6 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ନେଟ୍‌ୱର୍କଗୁଡ଼ିକୁ ଖୋଜିପାରୁନାହିଁ"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"କିଛି ନାହିଁ"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ସେଭ୍‌ ହୋଇଗଲା"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ଅକ୍ଷମ ହୋଇଛି"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP କନଫିଗରେଶନ ବିଫଳ ହୋଇଛି"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 6f17e13..61f0447 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ਨੈਟਵਰਕਾਂ ਲਈ ਸਕੈਨ ਨਹੀਂ ਕਰ ਸਕਦਾ"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ਕੋਈ ਨਹੀਂ"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"ਰੱਖਿਅਤ ਕੀਤਾ"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ਅਯੋਗ ਬਣਾਇਆ"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP ਕੌਂਫਿਗਰੇਸ਼ਨ ਅਸਫਲਤਾ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 3c208e3..519f82c 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nie można wyszukać sieci."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Brak"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Zapisana"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Wyłączona"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Błąd konfiguracji IP"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 5c363a4..16844a2 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Não é possível verificar a existência de redes"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nenhuma"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Salva"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
@@ -227,7 +226,7 @@
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Acionar seleção de codec de áudio\nBluetooth LDAC: qualidade de reprodução"</string>
     <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS particular"</string>
-    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo DNS particular"</string>
+    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo de DNS particular"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Desativado"</string>
     <string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automático"</string>
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome do host do provedor de DNS particular"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 66c59ac..f01ddfa 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Não é possível verificar redes"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nenhuma"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Guardada"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
@@ -278,7 +277,7 @@
     <string name="media_category" msgid="4388305075496848353">"Multimédia"</string>
     <string name="debug_monitoring_category" msgid="7640508148375798343">"Monitorização"</string>
     <string name="strict_mode" msgid="1938795874357830695">"Modo rigoroso ativado"</string>
-    <string name="strict_mode_summary" msgid="142834318897332338">"Piscar ecrã se aplic. fazem oper. prolong. no tópico princ."</string>
+    <string name="strict_mode_summary" msgid="142834318897332338">"Piscar ecrã se app fazem oper. prolong. no tópico princ."</string>
     <string name="pointer_location" msgid="6084434787496938001">"Localização do ponteiro"</string>
     <string name="pointer_location_summary" msgid="840819275172753713">"Apresentar dados atuais de toque"</string>
     <string name="show_touches" msgid="2642976305235070316">"Mostrar toques"</string>
@@ -305,7 +304,7 @@
     <string name="show_non_rect_clip" msgid="505954950474595172">"Depurar operações de clipe não retangulares"</string>
     <string name="track_frame_time" msgid="6094365083096851167">"Renderiz. HWUI do perfil"</string>
     <string name="enable_gpu_debug_layers" msgid="3848838293793255097">"Ativar cam. depuração GPU"</string>
-    <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Permitir carreg. cam. depuração GPU p/ dep. aplic."</string>
+    <string name="enable_gpu_debug_layers_summary" msgid="8009136940671194940">"Permitir carreg. cam. depuração GPU p/ dep. app"</string>
     <string name="window_animation_scale_title" msgid="6162587588166114700">"Escala de anim. da janela"</string>
     <string name="transition_animation_scale_title" msgid="387527540523595875">"Escala de anim. de trans."</string>
     <string name="animator_duration_scale_title" msgid="3406722410819934083">"Esc. de duração do anim."</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 5c363a4..16844a2 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Não é possível verificar a existência de redes"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Nenhuma"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Salva"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Desativado"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Falha de configuração de IP"</string>
@@ -227,7 +226,7 @@
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="6893955536658137179">"Acionar seleção de codec de áudio\nBluetooth LDAC: qualidade de reprodução"</string>
     <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="select_private_dns_configuration_title" msgid="3700456559305263922">"DNS particular"</string>
-    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo DNS particular"</string>
+    <string name="select_private_dns_configuration_dialog_title" msgid="9221994415765826811">"Selecione o modo de DNS particular"</string>
     <string name="private_dns_mode_off" msgid="8236575187318721684">"Desativado"</string>
     <string name="private_dns_mode_opportunistic" msgid="8314986739896927399">"Automático"</string>
     <string name="private_dns_mode_provider" msgid="8354935160639360804">"Nome do host do provedor de DNS particular"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 703add6..8a7b440 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nu se poate scana pentru rețele"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Niciuna"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Salvată"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Dezactivată"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Eroare de configurație IP"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 4eb3ca4..31274d1 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Не удалось начать поиск сетей."</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Нет"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Сохранено"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Отключено"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ошибка IP-конфигурации"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 1ab5b79..b22e068 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ජාල සඳහා පරිලෝකනය කළ නොහැක"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"කිසිවක් නැත"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"සුරකින ලදි"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"අබලයි"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP වින්‍යාස කිරීම අසාර්ථකයි"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 5c3920f..43923b8 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Siete sa nedajú vyhľadávať"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Žiadne"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Uložené"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Vypnuté"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Zlyhanie konfigurácie adresy IP"</string>
@@ -438,7 +437,7 @@
     <string name="cancel" msgid="6859253417269739139">"Zrušiť"</string>
     <string name="okay" msgid="1997666393121016642">"OK"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="8287824809739581837">"Zapnúť"</string>
-    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Zapnite režim Nerušiť"</string>
+    <string name="zen_mode_settings_turn_on_dialog_title" msgid="2297134204747331078">"Zapnite režim bez vyrušení"</string>
     <string name="zen_mode_settings_summary_off" msgid="6119891445378113334">"Nikdy"</string>
     <string name="zen_interruption_level_priority" msgid="2078370238113347720">"Iba prioritné"</string>
     <string name="zen_mode_and_condition" msgid="4927230238450354412">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index f479405..6d392fe 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ni mogoče iskati omrežij"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Brez"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Shranjeno"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Onemogočeno"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Konfiguracija IP-ja ni uspela"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 2741985..e05a019 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Nuk mund të skanojë për rrjete"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Asnjë"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"U ruajt"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Të çaktivizuara"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Dështim në konfigurimin e IP-së"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 241d9cb..371b909 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -21,13 +21,12 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Није могуће скенирати мреже"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Нема"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Сачувано"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Онемогућено"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP конфигурација је отказала"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Није повезано због лошег квалитета мреже"</string>
     <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Wi-Fi веза је отказала"</string>
-    <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблем са потврдом аутентичности"</string>
+    <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Проблем са потврдом идентитета"</string>
     <string name="wifi_cant_connect" msgid="5410016875644565884">"Повезивање није успело"</string>
     <string name="wifi_cant_connect_to_ap" msgid="1222553274052685331">"Повезивање са „<xliff:g id="AP_NAME">%1$s</xliff:g>“ није успело"</string>
     <string name="wifi_check_password_try_again" msgid="516958988102584767">"Проверите лозинку и пробајте поново"</string>
@@ -448,5 +447,5 @@
     <string name="zen_mode_duration_settings_title" msgid="229547412251222757">"Трајање"</string>
     <string name="zen_mode_duration_always_prompt_title" msgid="6478923750878945501">"Увек питај"</string>
     <string name="zen_mode_forever" msgid="2704305038191592967">"Док не искључите"</string>
-    <string name="time_unit_just_now" msgid="6363336622778342422">"Управо сада"</string>
+    <string name="time_unit_just_now" msgid="6363336622778342422">"Управо"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index d338e96..e6872bb 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Det går inte att söka efter nätverk"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Ingen"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Sparat"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Inaktiverad"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP-konfigurationsfel"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index d693077..23efb91 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Haiwezi kutambaza mitandao"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Hamna"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Imehifadhiwa"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Imezimwa"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Haikuweza Kusanidi IP"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 8f5c7d8..53ba738 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"நெட்வொர்க்குகளுக்கு ஸ்கேன் செய்யப்படவில்லை"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ஏதுமில்லை"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"சேமிக்கப்பட்டது"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"முடக்கப்பட்டது"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP உள்ளமைவில் தோல்வி"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 5f7ab996..c8c6b4c 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"నెట్‌వర్క్‌ల కోసం స్కాన్ చేయడం సాధ్యపడదు"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ఏదీ లేదు"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"సేవ్ చేయబడింది"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"నిలిపివేయబడింది"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP కాన్ఫిగరేషన్ వైఫల్యం"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 020baf0..d293d59 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"ไม่สามารถสแกนหาเครือข่าย"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"ไม่มี"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"บันทึกแล้ว"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"ปิดอยู่"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"การกำหนดค่า IP ล้มเหลว"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 2164ade..9da4561 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Hindi makapag-scan ng mga network"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Wala"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Na-save"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Naka-disable"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Pagkabigo ng Configuration ng IP"</string>
@@ -374,7 +373,7 @@
     <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> batay sa iyong paggamit (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> batay sa iyong paggamit"</string>
     <string name="power_discharge_by" msgid="6453537733650125582">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
-    <string name="power_discharge_by_only" msgid="107616694963545745">"Tatagal dapat nang hanggang humigit-kumulang <xliff:g id="TIME">%1$s</xliff:g>"</string>
+    <string name="power_discharge_by_only" msgid="107616694963545745">"Tatagal hanggang mga <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira"</string>
     <string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="3176771815132876675">"Mahigit <xliff:g id="TIME_REMAINING">%1$s</xliff:g> pa ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 532927c..2d5cd7f 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ağlar taranamıyor"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Yok"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Kaydedildi"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Devre dışı"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP Yapılandırması Hatası"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index cf26d20..512ea86 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Неможливо здійснити сканування мереж"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Немає"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Збережено"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Вимкнено"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Помилка конфігурації IP-адреси"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index c158179..84ad3ed 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"نیٹ ورکس کیلئے اسکین نہيں کر سکتے ہیں"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"کوئی نہیں"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"محفوظ کردیا گیا"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"غیر فعال"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"‏IP کنفیگریشن کی ناکامی"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index ac8bffe..af2ada5 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Tarmoqlarni tekshirib chiqishni iloji bo‘lmadi"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Hech qanday"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Saqlandi"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"O‘chiq"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP manzilini sozlab bo‘lmadi"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 78306da..f454127 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Không thể dò tìm mạng"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Không"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Đã lưu"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Đã tắt"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Lỗi cấu hình IP"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 4fb26100..10a20be 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"无法扫描网络"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"无"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"已保存"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 配置失败"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index c5a8f92..1510545 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"無法掃瞄網絡"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"無"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"已儲存"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 設定失敗"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 0947ccec..90c0d80 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"無法掃描網路"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"無"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"已儲存"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"已停用"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"IP 設定失敗"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index cd90d74..e4f9f4d 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -21,7 +21,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="wifi_fail_to_scan" msgid="1265540342578081461">"Ayikwazi ukuhlola amanethiwekhi"</string>
-    <string name="wifi_security_none" msgid="7985461072596594400">"Lutho"</string>
     <string name="wifi_remembered" msgid="4955746899347821096">"Kulondoloziwe"</string>
     <string name="wifi_disabled_generic" msgid="4259794910584943386">"Akusebenzi"</string>
     <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Ukwehluleka kokulungiswa kwe-IP"</string>
diff --git a/packages/SettingsLib/res/values/colors.xml b/packages/SettingsLib/res/values/colors.xml
index 02b7ea6..66bbb3a 100644
--- a/packages/SettingsLib/res/values/colors.xml
+++ b/packages/SettingsLib/res/values/colors.xml
@@ -18,4 +18,5 @@
     <color name="disabled_text_color">#66000000</color> <!-- 38% black -->
 
     <color name="usage_graph_dots">@*android:color/tertiary_device_default_settings</color>
+    <color name="list_divider_color">#64000000</color>
 </resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 508adbd..2823149 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -21,35 +21,47 @@
     <!-- Toast message when Wi-Fi cannot scan for networks -->
     <string name="wifi_fail_to_scan">Can\'t scan for networks</string>
     <!-- Do not translate.  Concise terminology for wifi with WEP security -->
-    <string name="wifi_security_short_wep">WEP</string>
+    <string name="wifi_security_short_wep" translatable="false">WEP</string>
     <!-- Do not translate.  Concise terminology for wifi with WPA security -->
-    <string name="wifi_security_short_wpa">WPA</string>
+    <string name="wifi_security_short_wpa" translatable="false">WPA</string>
     <!-- Do not translate.  Concise terminology for wifi with WPA2 security -->
-    <string name="wifi_security_short_wpa2">WPA2</string>
+    <string name="wifi_security_short_wpa2" translatable="false">WPA2</string>
     <!-- Do not translate.  Concise terminology for wifi with both WPA/WPA2 security -->
-    <string name="wifi_security_short_wpa_wpa2">WPA/WPA2</string>
+    <string name="wifi_security_short_wpa_wpa2" translatable="false">WPA/WPA2</string>
     <!-- Do not translate.  Concise terminology for wifi with unknown PSK type -->
-    <string name="wifi_security_short_psk_generic">@string/wifi_security_short_wpa_wpa2</string>
+    <string name="wifi_security_short_psk_generic" translatable="false">@string/wifi_security_short_wpa_wpa2</string>
     <!-- Do not translate.  Concise terminology for wifi with 802.1x EAP security -->
-    <string name="wifi_security_short_eap">802.1x</string>
+    <string name="wifi_security_short_eap" translatable="false">802.1x</string>
+    <!-- Do not translate.  Concise terminology for wifi with WPA3 security -->
+    <string name="wifi_security_short_sae" translatable="false">WPA3</string>
+    <!-- Do not translate.  Concise terminology for wifi with OWE security -->
+    <string name="wifi_security_short_owe" translatable="false">OWE</string>
+    <!-- Do not translate.  Concise terminology for wifi with 802.1x EAP Suite-B security -->
+    <string name="wifi_security_short_eap_suiteb" translatable="false">Suite-B</string>
 
-    <!-- Used in Wi-Fi settings dialogs when Wi-Fi does not have any security. -->
+    <!-- Used in Wi-Fi settings dialogs when Wi-Fi does not have any security. [CHAR LIMIT=40] -->
     <string name="wifi_security_none">None</string>
 
     <!-- Do not translate.  Terminology for wifi with WEP security -->
-    <string name="wifi_security_wep">WEP</string>
+    <string name="wifi_security_wep" translatable="false">WEP</string>
     <!-- Do not translate.  Terminology for wifi with WPA security -->
-    <string name="wifi_security_wpa">WPA PSK</string>
+    <string name="wifi_security_wpa" translatable="false">WPA-Personal</string>
     <!-- Do not translate.  Terminology for wifi with WPA2 security -->
-    <string name="wifi_security_wpa2">WPA2 PSK</string>
+    <string name="wifi_security_wpa2" translatable="false">WPA2-Personal</string>
     <!-- Do not translate.  Terminology for wifi with both WPA/WPA2 security, or unknown -->
-    <string name="wifi_security_wpa_wpa2">WPA/WPA2 PSK</string>
+    <string name="wifi_security_wpa_wpa2" translatable="false">WPA/WPA2-Personal</string>
     <!-- Do not translate.  Terminology for wifi with unknown PSK type -->
-    <string name="wifi_security_psk_generic">@string/wifi_security_wpa_wpa2</string>
+    <string name="wifi_security_psk_generic" translatable="false">@string/wifi_security_wpa_wpa2</string>
     <!-- Do not translate.  Concise terminology for wifi with 802.1x EAP security -->
-    <string name="wifi_security_eap">802.1x EAP</string>
+    <string name="wifi_security_eap" translatable="false">WPA/WPA2-Enterprise</string>
     <!-- Do not translate.  Concise terminology for Passpoint network -->
-    <string name="wifi_security_passpoint">Passpoint</string>
+    <string name="wifi_security_passpoint" translatable="false">Passpoint</string>
+    <!-- Do not translate.  Terminology for wifi with WPA3 security -->
+    <string name="wifi_security_sae" translatable="false">WPA3-Personal</string>
+    <!-- Do not translate.  Terminology for wifi with OWE security -->
+    <string name="wifi_security_owe" translatable="false">Enhanced Open</string>
+    <!-- Do not translate.  Concise terminology for wifi with 802.1x EAP Suite-B security -->
+    <string name="wifi_security_eap_suiteb" translatable="false">WPA3-Enterprise</string>
 
     <!-- Summary for the remembered network. -->
     <string name="wifi_remembered">Saved</string>
@@ -918,6 +930,8 @@
     <string name="power_discharge_by">Should last until about <xliff:g id="time">%1$s</xliff:g> (<xliff:g id="level">%2$s</xliff:g>)</string>
     <!-- [CHAR_LIMIT=100] Label for estimated time that phone will run out of battery -->
     <string name="power_discharge_by_only">Should last until about <xliff:g id="time">%1$s</xliff:g></string>
+    <!-- [CHAR_LIMIT=100] Label for estimated time that phone will run out of battery -->
+    <string name="power_discharge_by_only_short">Until <xliff:g id="time" example="12 PM">%1$s</xliff:g></string>
 
     <!-- [CHAR_LIMIT=60] label for estimated remaining duration of battery when under a certain amount -->
     <string name="power_remaining_less_than_duration_only">Less than <xliff:g id="threshold">%1$s</xliff:g> remaining</string>
@@ -1118,4 +1132,10 @@
 
     <!-- The notice header of Third-party licenses. not translatable -->
     <string name="notice_header" translatable="false"></string>
+
+    <!-- UI debug setting: opt in to use updated graphics driver? [CHAR LIMIT=100] -->
+    <string name="updated_gfx_driver_dev_opt_in_app_summary">Opt in app to use updated graphcis driver in developement</string>
+
+    <!-- Name of the phone device [CHAR LIMIT=NONE] -->
+    <string name="media_transfer_phone_device_name">Phone speaker</string>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index b4e82e9..d6c6491 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -892,7 +892,7 @@
                 if (batteryLevelPercentageString != null) {
                     //device is in phone call
                     if (com.android.settingslib.Utils.isAudioModeOngoingCall(mContext)) {
-                        if (mIsActiveDeviceHeadset) {
+                        if (mIsActiveDeviceHearingAid || mIsActiveDeviceHeadset) {
                             stringRes = R.string.bluetooth_active_battery_level;
                         } else {
                             stringRes = R.string.bluetooth_battery_level;
@@ -908,7 +908,7 @@
                 } else {
                     //no battery information
                     if (com.android.settingslib.Utils.isAudioModeOngoingCall(mContext)) {
-                        if (mIsActiveDeviceHeadset) {
+                        if (mIsActiveDeviceHearingAid || mIsActiveDeviceHeadset) {
                             stringRes = R.string.bluetooth_active_no_battery_level;
                         }
                     } else {
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
index 027ca09..e824508 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.metrics.LogMaker;
+import android.text.TextUtils;
 import android.util.Pair;
 
 import com.android.internal.logging.MetricsLogger;
@@ -28,8 +29,7 @@
  */
 public class EventLogWriter implements LogWriter {
 
-    private final MetricsLogger mMetricsLogger = new MetricsLogger();
-
+    @Override
     public void visible(Context context, int source, int category) {
         final LogMaker logMaker = new LogMaker(category)
                 .setType(MetricsProto.MetricsEvent.TYPE_OPEN)
@@ -37,69 +37,56 @@
         MetricsLogger.action(logMaker);
     }
 
+    @Override
     public void hidden(Context context, int category) {
         MetricsLogger.hidden(context, category);
     }
 
-    public void action(int category, int value, Pair<Integer, Object>... taggedData) {
-        if (taggedData == null || taggedData.length == 0) {
-            mMetricsLogger.action(category, value);
-        } else {
-            final LogMaker logMaker = new LogMaker(category)
-                    .setType(MetricsProto.MetricsEvent.TYPE_ACTION)
-                    .setSubtype(value);
+    @Override
+    public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
+        final LogMaker logMaker = new LogMaker(category)
+                .setType(MetricsProto.MetricsEvent.TYPE_ACTION);
+        if (taggedData != null) {
             for (Pair<Integer, Object> pair : taggedData) {
                 logMaker.addTaggedData(pair.first, pair.second);
             }
-            mMetricsLogger.write(logMaker);
-        }
-    }
-
-    public void action(int category, boolean value, Pair<Integer, Object>... taggedData) {
-        action(category, value ? 1 : 0, taggedData);
-    }
-
-    public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
-        action(context, category, "", taggedData);
-    }
-
-    public void actionWithSource(Context context, int source, int category) {
-        final LogMaker logMaker = new LogMaker(category)
-                .setType(MetricsProto.MetricsEvent.TYPE_ACTION);
-        if (source != MetricsProto.MetricsEvent.VIEW_UNKNOWN) {
-            logMaker.addTaggedData(MetricsProto.MetricsEvent.FIELD_CONTEXT, source);
         }
         MetricsLogger.action(logMaker);
     }
 
-    /** @deprecated use {@link #action(int, int, Pair[])} */
-    @Deprecated
+    @Override
     public void action(Context context, int category, int value) {
         MetricsLogger.action(context, category, value);
     }
 
-    /** @deprecated use {@link #action(int, boolean, Pair[])} */
-    @Deprecated
+    @Override
     public void action(Context context, int category, boolean value) {
         MetricsLogger.action(context, category, value);
     }
 
-    public void action(Context context, int category, String pkg,
-            Pair<Integer, Object>... taggedData) {
-        if (taggedData == null || taggedData.length == 0) {
-            MetricsLogger.action(context, category, pkg);
-        } else {
-            final LogMaker logMaker = new LogMaker(category)
-                    .setType(MetricsProto.MetricsEvent.TYPE_ACTION)
-                    .setPackageName(pkg);
-            for (Pair<Integer, Object> pair : taggedData) {
-                logMaker.addTaggedData(pair.first, pair.second);
-            }
-            MetricsLogger.action(logMaker);
-        }
+    @Override
+    public void action(Context context, int category, String pkg) {
+        final LogMaker logMaker = new LogMaker(category)
+                .setType(MetricsProto.MetricsEvent.TYPE_ACTION)
+                .setPackageName(pkg);
+
+        MetricsLogger.action(logMaker);
     }
 
-    public void count(Context context, String name, int value) {
-        MetricsLogger.count(context, name, value);
+    @Override
+    public void action(int attribution, int action, int pageId, String key, int value) {
+        final LogMaker logMaker = new LogMaker(action)
+                .setType(MetricsProto.MetricsEvent.TYPE_ACTION);
+        if (attribution != MetricsProto.MetricsEvent.VIEW_UNKNOWN) {
+            logMaker.addTaggedData(MetricsProto.MetricsEvent.FIELD_CONTEXT, pageId);
+        }
+        if (!TextUtils.isEmpty(key)) {
+            logMaker.addTaggedData(MetricsProto.MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME,
+                    key);
+            logMaker.addTaggedData(
+                    MetricsProto.MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
+                    value);
+        }
+        MetricsLogger.action(logMaker);
     }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
index a16838c..f187688 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
@@ -34,16 +34,6 @@
     void hidden(Context context, int category);
 
     /**
-     * Logs a user action.
-     */
-    void action(int category, int value, Pair<Integer, Object>... taggedData);
-
-    /**
-     * Logs a user action.
-     */
-    void action(int category, boolean value, Pair<Integer, Object>... taggedData);
-
-    /**
      * Logs an user action.
      */
     void action(Context context, int category, Pair<Integer, Object>... taggedData);
@@ -51,37 +41,20 @@
     /**
      * Logs an user action.
      */
-    void actionWithSource(Context context, int source, int category);
-
-    /**
-     * Logs an user action.
-     *
-     * @deprecated use {@link #action(int, int, Pair[])}
-     */
-    @Deprecated
     void action(Context context, int category, int value);
 
     /**
      * Logs an user action.
-     *
-     * @deprecated use {@link #action(int, boolean, Pair[])}
      */
-    @Deprecated
     void action(Context context, int category, boolean value);
 
     /**
      * Logs an user action.
      */
-    void action(Context context, int category, String pkg, Pair<Integer, Object>... taggedData);
+    void action(Context context, int category, String pkg);
 
     /**
-     * Logs a count.
+     * Generically log action.
      */
-    void count(Context context, String name, int value);
-
-    /**
-     * Generically log action into statsd.
-     */
-    default void action(int attribution, int action, int pageId, String key, int value) {
-    }
+    void action(int attribution, int action, int pageId, String key, int value);
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
index e1f9111..8cc3b5a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
@@ -15,6 +15,8 @@
  */
 package com.android.settingslib.core.instrumentation;
 
+import android.app.Activity;
+import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -30,6 +32,11 @@
  * FeatureProvider for metrics.
  */
 public class MetricsFeatureProvider {
+    /**
+     * The metrics category constant for logging source when a setting fragment is opened.
+     */
+    public static final String EXTRA_SOURCE_METRICS_CATEGORY = ":settings:source_metrics";
+
     protected List<LogWriter> mLoggerWriters;
 
     public MetricsFeatureProvider() {
@@ -41,6 +48,25 @@
         mLoggerWriters.add(new EventLogWriter());
     }
 
+    /**
+     * Returns the attribution id for specified activity. If no attribution is set, returns {@link
+     * SettingsEnums#PAGE_UNKNOWN}.
+     *
+     * <p/> Attribution is a {@link SettingsEnums} page id that indicates where the specified
+     * activity is launched from.
+     */
+    public int getAttribution(Activity activity) {
+        if (activity == null) {
+            return SettingsEnums.PAGE_UNKNOWN;
+        }
+        final Intent intent = activity.getIntent();
+        if (intent == null) {
+            return SettingsEnums.PAGE_UNKNOWN;
+        }
+        return intent.getIntExtra(EXTRA_SOURCE_METRICS_CATEGORY,
+                SettingsEnums.PAGE_UNKNOWN);
+    }
+
     public void visible(Context context, int source, int category) {
         for (LogWriter writer : mLoggerWriters) {
             writer.visible(context, source, category);
@@ -53,15 +79,30 @@
         }
     }
 
-    public void actionWithSource(Context context, int source, int category) {
+    /**
+     * Logs a simple action without page id or attribution
+     */
+    public void action(Context context, int category,  Pair<Integer, Object>... taggedData) {
         for (LogWriter writer : mLoggerWriters) {
-            writer.actionWithSource(context, source, category);
+            writer.action(context, category, taggedData);
         }
     }
 
-    public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
+    /**
+     * Logs a generic Settings event.
+     */
+    public void action(Context context, int category, String pkg) {
         for (LogWriter writer : mLoggerWriters) {
-            writer.action(context, category, taggedData);
+            writer.action(context, category, pkg);
+        }
+    }
+
+    /**
+     * Logs a generic Settings event.
+     */
+    public void action(int attribution, int action, int pageId, String key, int value) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.action(attribution, action, pageId, key, value);
         }
     }
 
@@ -77,19 +118,6 @@
         }
     }
 
-    public void action(Context context, int category, String pkg,
-            Pair<Integer, Object>... taggedData) {
-        for (LogWriter writer : mLoggerWriters) {
-            writer.action(context, category, pkg, taggedData);
-        }
-    }
-
-    public void count(Context context, String name, int value) {
-        for (LogWriter writer : mLoggerWriters) {
-            writer.count(context, name, value);
-        }
-    }
-
     public int getMetricsCategory(Object object) {
         if (object == null || !(object instanceof Instrumentable)) {
             return MetricsEvent.VIEW_UNKNOWN;
@@ -109,16 +137,22 @@
                 // Not loggable
                 return;
             }
-            action(context, MetricsEvent.ACTION_SETTINGS_TILE_CLICK, action,
-                    Pair.create(MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
+            action(sourceMetricsCategory,
+                    MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                    SettingsEnums.PAGE_UNKNOWN,
+                    action,
+                    0);
             return;
         } else if (TextUtils.equals(cn.getPackageName(), context.getPackageName())) {
             // Going to a Setting internal page, skip click logging in favor of page's own
             // visibility logging.
             return;
         }
-        action(context, MetricsEvent.ACTION_SETTINGS_TILE_CLICK, cn.flattenToString(),
-                Pair.create(MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
+        action(sourceMetricsCategory,
+                MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                SettingsEnums.PAGE_UNKNOWN,
+                cn.flattenToString(),
+                0);
     }
 
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
index a28e45c..320380f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
@@ -15,6 +15,7 @@
 package com.android.settingslib.core.instrumentation;
 
 import android.annotation.Nullable;
+import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.SharedPreferences;
@@ -22,12 +23,9 @@
 import android.os.AsyncTask;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Pair;
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentSkipListSet;
@@ -116,13 +114,10 @@
             mPreferenceKeySet.add(prefKey);
             return;
         }
-        // TODO: Remove count logging to save some resource.
-        mMetricsFeature.count(mContext, buildCountName(prefKey, value), 1);
 
-        final Pair<Integer, Object> valueData;
+        final int intVal;
         if (value instanceof Long) {
             final Long longVal = (Long) value;
-            final int intVal;
             if (longVal > Integer.MAX_VALUE) {
                 intVal = Integer.MAX_VALUE;
             } else if (longVal < Integer.MIN_VALUE) {
@@ -130,47 +125,45 @@
             } else {
                 intVal = longVal.intValue();
             }
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
-                    intVal);
         } else if (value instanceof Integer) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
-                    value);
+            intVal = (int) value;
         } else if (value instanceof Boolean) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
-                    (Boolean) value ? 1 : 0);
+            intVal = (Boolean) value ? 1 : 0;
         } else if (value instanceof Float) {
-            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE,
-                    value);
-        } else if (value instanceof String) {
-            Log.d(LOG_TAG, "Tried to log string preference " + prefKey + " = " + value);
-            valueData = null;
+            final float floatValue = (float) value;
+            if (floatValue > Integer.MAX_VALUE) {
+                intVal = Integer.MAX_VALUE;
+            } else if (floatValue < Integer.MIN_VALUE) {
+                intVal = Integer.MIN_VALUE;
+            } else {
+                intVal = (int) floatValue;
+            }
         } else {
             Log.w(LOG_TAG, "Tried to log unloggable object" + value);
-            valueData = null;
+            return;
         }
-        if (valueData != null) {
-            // Pref key exists in set, log it's change in metrics.
-            mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE,
-                    Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey),
-                    valueData);
-        }
+        // Pref key exists in set, log it's change in metrics.
+        mMetricsFeature.action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                prefKey,
+                intVal);
     }
 
     @VisibleForTesting
     void logPackageName(String key, String value) {
         final String prefKey = mTag + "/" + key;
-        mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE, value,
-                Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey));
+        mMetricsFeature.action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                prefKey + ":" + value,
+                0);
     }
 
     private void safeLogValue(String key, String value) {
         new AsyncPackageCheck().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, key, value);
     }
 
-    public static String buildCountName(String prefKey, Object value) {
-        return prefKey + "|" + value;
-    }
-
     public static String buildPrefKey(String tag, String key) {
         return tag + "/" + key;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
index 06d7c4d..aed02a2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
@@ -41,11 +41,6 @@
     private int mSourceMetricsCategory = MetricsProto.MetricsEvent.VIEW_UNKNOWN;
     private long mVisibleTimestamp;
 
-    /**
-     * The metrics category constant for logging source when a setting fragment is opened.
-     */
-    public static final String EXTRA_SOURCE_METRICS_CATEGORY = ":settings:source_metrics";
-
     private VisibilityLoggerMixin() {
         mMetricsCategory = METRICS_CATEGORY_UNKNOWN;
     }
@@ -82,7 +77,8 @@
         if (intent == null) {
             return;
         }
-        mSourceMetricsCategory = intent.getIntExtra(EXTRA_SOURCE_METRICS_CATEGORY,
+        mSourceMetricsCategory = intent.getIntExtra(
+                MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY,
                 MetricsProto.MetricsEvent.VIEW_UNKNOWN);
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
index 5a57e69..8f9394f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
@@ -152,7 +152,8 @@
         final MeasurementDetails details = new MeasurementDetails();
         if (mVolume == null) return details;
 
-        if (mVolume.getType() == VolumeInfo.TYPE_PUBLIC) {
+        if (mVolume.getType() == VolumeInfo.TYPE_PUBLIC
+                || mVolume.getType() == VolumeInfo.TYPE_STUB) {
             details.totalSize = mVolume.getPath().getTotalSpace();
             details.availSize = mVolume.getPath().getUsableSpace();
             return details;
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
index dd8bfda..92fd868 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
@@ -51,6 +51,8 @@
     public static final String CATEGORY_GESTURES = "com.android.settings.category.ia.gestures";
     public static final String CATEGORY_NIGHT_DISPLAY =
             "com.android.settings.category.ia.night_display";
+    public static final String CATEGORY_PRIVACY =
+            "com.android.settings.category.ia.privacy";
 
     public static final Map<String, String> KEY_COMPAT_MAP;
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
new file mode 100644
index 0000000..e535348
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.media;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.android.settingslib.R;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
+/**
+ * BluetoothMediaDevice extends MediaDevice to represents Bluetooth device.
+ */
+public class BluetoothMediaDevice extends MediaDevice {
+
+    private static final String TAG = "BluetoothMediaDevice";
+
+    private CachedBluetoothDevice mCachedDevice;
+
+    BluetoothMediaDevice(Context context, CachedBluetoothDevice device) {
+        super(context, MediaDeviceType.TYPE_BLUETOOTH_DEVICE);
+        mCachedDevice = device;
+    }
+
+    @Override
+    public String getName() {
+        return mCachedDevice.getName();
+    }
+
+    @Override
+    public int getIcon() {
+        //TODO(b/117129183): This is not final icon for bluetooth device, just for demo.
+        return R.drawable.ic_bt_headphones_a2dp;
+    }
+
+    @Override
+    public String getId() {
+        return MediaDeviceUtils.getId(mCachedDevice);
+    }
+
+    @Override
+    public void connect() {
+        //TODO(b/117129183): add callback to notify LocalMediaManager connection state.
+        mIsConnected = mCachedDevice.setActive();
+        Log.d(TAG, "connect() device : " + getName() + ", is selected : " + mIsConnected);
+    }
+
+    @Override
+    public void disconnect() {
+        //TODO(b/117129183): disconnected last select device
+        mIsConnected = false;
+    }
+
+    /**
+     * Get current CachedBluetoothDevice
+     */
+    public CachedBluetoothDevice getCachedDevice() {
+        return mCachedDevice;
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
new file mode 100644
index 0000000..04188e9
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaManager.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.media;
+
+import android.app.Notification;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.Context;
+import android.util.Log;
+
+import com.android.settingslib.bluetooth.A2dpProfile;
+import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
+import com.android.settingslib.bluetooth.HearingAidProfile;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * BluetoothMediaManager provide interface to get Bluetooth device list.
+ */
+public class BluetoothMediaManager extends MediaManager implements BluetoothCallback {
+
+    private static final String TAG = "BluetoothMediaManager";
+
+    private final DeviceAttributeChangeCallback mCachedDeviceCallback =
+            new DeviceAttributeChangeCallback();
+
+    private LocalBluetoothManager mLocalBluetoothManager;
+    private LocalBluetoothProfileManager mProfileManager;
+
+    private MediaDevice mLastAddedDevice;
+    private MediaDevice mLastRemovedDevice;
+
+    BluetoothMediaManager(Context context, LocalBluetoothManager localBluetoothManager,
+            Notification notification) {
+        super(context, notification);
+
+        mLocalBluetoothManager = localBluetoothManager;
+        mProfileManager = mLocalBluetoothManager.getProfileManager();
+    }
+
+    @Override
+    public void startScan() {
+        mMediaDevices.clear();
+        mLocalBluetoothManager.getEventManager().registerCallback(this);
+        buildBluetoothDeviceList();
+        dispatchDeviceListAdded();
+    }
+
+    private void buildBluetoothDeviceList() {
+        addConnectedA2dpDevices();
+        addConnectedHearingAidDevices();
+    }
+
+    private void addConnectedA2dpDevices() {
+        final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
+        if (a2dpProfile == null) {
+            Log.w(TAG, "addConnectedA2dpDevices() a2dp profile is null!");
+            return;
+        }
+        final List<BluetoothDevice> devices = a2dpProfile.getConnectedDevices();
+        final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
+                mLocalBluetoothManager.getCachedDeviceManager();
+
+        for (BluetoothDevice device : devices) {
+            final CachedBluetoothDevice cachedDevice =
+                    cachedBluetoothDeviceManager.findDevice(device);
+
+            if (cachedDevice == null) {
+                Log.w(TAG, "Can't found CachedBluetoothDevice : " + device.getName());
+                continue;
+            }
+
+            Log.d(TAG, "addConnectedA2dpDevices() device : " + cachedDevice.getName()
+                    + ", is connected : " + cachedDevice.isConnected());
+
+            if (cachedDevice.isConnected()) {
+                addMediaDevice(cachedDevice);
+            }
+        }
+    }
+
+    private void addConnectedHearingAidDevices() {
+        final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
+        if (hapProfile == null) {
+            Log.w(TAG, "addConnectedA2dpDevices() hap profile is null!");
+            return;
+        }
+        final List<Long> devicesHiSyncIds = new ArrayList<>();
+        final List<BluetoothDevice> devices = hapProfile.getConnectedDevices();
+        final CachedBluetoothDeviceManager cachedBluetoothDeviceManager =
+                mLocalBluetoothManager.getCachedDeviceManager();
+
+        for (BluetoothDevice device : devices) {
+            final CachedBluetoothDevice cachedDevice =
+                    cachedBluetoothDeviceManager.findDevice(device);
+
+            if (cachedDevice == null) {
+                Log.w(TAG, "Can't found CachedBluetoothDevice : " + device.getName());
+                continue;
+            }
+
+            Log.d(TAG, "addConnectedHearingAidDevices() device : " + cachedDevice.getName()
+                    + ", is connected : " + cachedDevice.isConnected());
+            final long hiSyncId = hapProfile.getHiSyncId(device);
+
+            // device with same hiSyncId should not be shown in the UI.
+            // So do not add it into connectedDevices.
+            if (!devicesHiSyncIds.contains(hiSyncId) && cachedDevice.isConnected()) {
+                devicesHiSyncIds.add(hiSyncId);
+                addMediaDevice(cachedDevice);
+            }
+        }
+    }
+
+    private void addMediaDevice(CachedBluetoothDevice cachedDevice) {
+        MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
+        if (mediaDevice == null) {
+            mediaDevice = new BluetoothMediaDevice(mContext, cachedDevice);
+            cachedDevice.registerCallback(mCachedDeviceCallback);
+            mLastAddedDevice = mediaDevice;
+            mMediaDevices.add(mediaDevice);
+        }
+    }
+
+    @Override
+    public void stopScan() {
+        mLocalBluetoothManager.getEventManager().unregisterCallback(this);
+        unregisterCachedDeviceCallback();
+    }
+
+    private void unregisterCachedDeviceCallback() {
+        for (MediaDevice device : mMediaDevices) {
+            if (device instanceof BluetoothMediaDevice) {
+                ((BluetoothMediaDevice) device).getCachedDevice()
+                        .unregisterCallback(mCachedDeviceCallback);
+            }
+        }
+    }
+
+    @Override
+    public void onBluetoothStateChanged(int bluetoothState) {
+        if (BluetoothAdapter.STATE_ON == bluetoothState) {
+            buildBluetoothDeviceList();
+            dispatchDeviceListAdded();
+        } else if (BluetoothAdapter.STATE_OFF == bluetoothState) {
+            final List<MediaDevice> removeDevicesList = new ArrayList<>();
+            for (MediaDevice device : mMediaDevices) {
+                if (device instanceof BluetoothMediaDevice) {
+                    ((BluetoothMediaDevice) device).getCachedDevice()
+                            .unregisterCallback(mCachedDeviceCallback);
+                    removeDevicesList.add(device);
+                }
+            }
+            mMediaDevices.removeAll(removeDevicesList);
+            dispatchDeviceListRemoved(removeDevicesList);
+        }
+    }
+
+    @Override
+    public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
+        if (isCachedDeviceConnected(cachedDevice)) {
+            addMediaDevice(cachedDevice);
+            dispatchDeviceAdded(cachedDevice);
+        }
+    }
+
+    private boolean isCachedDeviceConnected(CachedBluetoothDevice cachedDevice) {
+        final boolean isConnectedHearingAidDevice = cachedDevice.isConnectedHearingAidDevice();
+        final boolean isConnectedA2dpDevice = cachedDevice.isConnectedA2dpDevice();
+        Log.d(TAG, "isCachedDeviceConnected() cachedDevice : " + cachedDevice.getName()
+                + ", is hearing aid connected : " + isConnectedHearingAidDevice
+                + ", is a2dp connected : " + isConnectedA2dpDevice);
+
+        return isConnectedHearingAidDevice || isConnectedA2dpDevice;
+    }
+
+    private void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
+        if (mLastAddedDevice != null
+                && MediaDeviceUtils.getId(cachedDevice) == mLastAddedDevice.getId()) {
+            dispatchDeviceAdded(mLastAddedDevice);
+        }
+    }
+
+    @Override
+    public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
+        if (!isCachedDeviceConnected(cachedDevice)) {
+            removeMediaDevice(cachedDevice);
+            dispatchDeviceRemoved(cachedDevice);
+        }
+    }
+
+    private void removeMediaDevice(CachedBluetoothDevice cachedDevice) {
+        final MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(cachedDevice));
+        if (mediaDevice != null) {
+            cachedDevice.unregisterCallback(mCachedDeviceCallback);
+            mLastRemovedDevice = mediaDevice;
+            mMediaDevices.remove(mediaDevice);
+        }
+    }
+
+    void dispatchDeviceRemoved(CachedBluetoothDevice cachedDevice) {
+        if (mLastRemovedDevice != null
+                && MediaDeviceUtils.getId(cachedDevice) == mLastRemovedDevice.getId()) {
+            dispatchDeviceRemoved(mLastRemovedDevice);
+        }
+    }
+
+    @Override
+    public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state,
+            int bluetoothProfile) {
+        Log.d(TAG, "onProfileConnectionStateChanged() device: " + cachedDevice.getName()
+                + ", state: " + state + ", bluetoothProfile: " + bluetoothProfile);
+
+        if (isCachedDeviceConnected(cachedDevice)) {
+            addMediaDevice(cachedDevice);
+            dispatchDeviceAdded(cachedDevice);
+        } else {
+            removeMediaDevice(cachedDevice);
+            dispatchDeviceRemoved(cachedDevice);
+        }
+    }
+
+    @Override
+    public void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
+        Log.d(TAG, "onAclConnectionStateChanged() device: " + cachedDevice.getName()
+                + ", state: " + state);
+
+        if (isCachedDeviceConnected(cachedDevice)) {
+            addMediaDevice(cachedDevice);
+            dispatchDeviceAdded(cachedDevice);
+        } else {
+            removeMediaDevice(cachedDevice);
+            dispatchDeviceRemoved(cachedDevice);
+        }
+    }
+
+    class DeviceAttributeChangeCallback implements CachedBluetoothDevice.Callback {
+        @Override
+        public void onDeviceAttributesChanged() {
+            dispatchDeviceAttributesChanged();
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
new file mode 100644
index 0000000..498a0fc
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.media;
+
+import android.content.Context;
+
+import androidx.mediarouter.media.MediaRouter;
+
+import com.android.settingslib.R;
+
+/**
+ * InfoMediaDevice extends MediaDevice to represents wifi device.
+ */
+public class InfoMediaDevice extends MediaDevice {
+
+    private static final String TAG = "InfoMediaDevice";
+
+    private MediaRouter.RouteInfo mRouteInfo;
+
+    InfoMediaDevice(Context context, MediaRouter.RouteInfo info) {
+        super(context, MediaDeviceType.TYPE_CAST_DEVICE);
+        mRouteInfo = info;
+    }
+
+    @Override
+    public String getName() {
+        return mRouteInfo.getName();
+    }
+
+    @Override
+    public int getIcon() {
+        //TODO(b/117129183): This is not final icon for cast device, just for demo.
+        return R.drawable.ic_settings_print;
+    }
+
+    @Override
+    public String getId() {
+        return MediaDeviceUtils.getId(mRouteInfo);
+    }
+
+    @Override
+    public void connect() {
+        //TODO(b/117129183): use MediaController2 to transfer media
+        mIsConnected = true;
+    }
+
+    @Override
+    public void disconnect() {
+        //TODO(b/117129183): disconnected last select device
+        mIsConnected = false;
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
new file mode 100644
index 0000000..6907238
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.media;
+
+import android.app.Notification;
+import android.content.Context;
+import android.util.Log;
+
+import androidx.mediarouter.media.MediaRouteSelector;
+import androidx.mediarouter.media.MediaRouter;
+
+/**
+ * InfoMediaManager provide interface to get InfoMediaDevice list.
+ */
+public class InfoMediaManager extends MediaManager {
+
+    private static final String TAG = "InfoMediaManager";
+
+    private final MediaRouterCallback mMediaRouterCallback = new MediaRouterCallback();
+
+    private MediaRouter mMediaRouter;
+    private String mPackageName;
+
+    InfoMediaManager(Context context, String packageName, Notification notification) {
+        super(context, notification);
+
+        mMediaRouter = MediaRouter.getInstance(context);
+        mPackageName = packageName;
+    }
+
+    @Override
+    public void startScan() {
+        mMediaDevices.clear();
+        startScanCastDevice();
+    }
+
+    private void startScanCastDevice() {
+        final MediaRouteSelector selector = new MediaRouteSelector.Builder()
+                .addControlCategory(getControlCategoryByPackageName(mPackageName))
+                .build();
+
+        mMediaRouter.addCallback(selector, mMediaRouterCallback,
+                MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
+    }
+
+    private String getControlCategoryByPackageName(String packageName) {
+        //TODO(b/117129183): Use package name to get ControlCategory.
+        //Since api not ready, return fixed ControlCategory for prototype.
+        return "com.google.android.gms.cast.CATEGORY_CAST/4F8B3483";
+    }
+
+    @Override
+    public void stopScan() {
+        mMediaRouter.removeCallback(mMediaRouterCallback);
+    }
+
+    class MediaRouterCallback extends MediaRouter.Callback {
+        @Override
+        public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo route) {
+            MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(route));
+            if (mediaDevice == null) {
+                mediaDevice = new InfoMediaDevice(mContext, route);
+                Log.d(TAG, "onRouteAdded() route : " + route.getName());
+                mMediaDevices.add(mediaDevice);
+                dispatchDeviceAdded(mediaDevice);
+            }
+        }
+
+        @Override
+        public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo route) {
+            final MediaDevice mediaDevice = findMediaDevice(MediaDeviceUtils.getId(route));
+            if (mediaDevice != null) {
+                Log.d(TAG, "onRouteRemoved() route : " + route.getName());
+                mMediaDevices.remove(mediaDevice);
+                dispatchDeviceRemoved(mediaDevice);
+            }
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
new file mode 100644
index 0000000..e375ea0
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.media;
+
+import android.app.Notification;
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.IntDef;
+
+import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * LocalMediaManager provide interface to get MediaDevice list and transfer media to MediaDevice.
+ */
+public class LocalMediaManager implements BluetoothCallback {
+
+    private static final String TAG = "LocalMediaManager";
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({MediaDeviceState.STATE_CONNECTED,
+            MediaDeviceState.STATE_CONNECTING,
+            MediaDeviceState.STATE_DISCONNECTED})
+    public @interface MediaDeviceState {
+        int STATE_CONNECTED = 1;
+        int STATE_CONNECTING = 2;
+        int STATE_DISCONNECTED = 3;
+    }
+
+    private final Collection<DeviceCallback> mCallbacks = new ArrayList<>();
+    private final MediaDeviceCallback mMediaDeviceCallback = new MediaDeviceCallback();
+
+    private Context mContext;
+    private List<MediaDevice> mMediaDevices = new ArrayList<>();
+    private BluetoothMediaManager mBluetoothMediaManager;
+    private InfoMediaManager mInfoMediaManager;
+
+    private LocalBluetoothManager mLocalBluetoothManager;
+    private MediaDevice mLastConnectedDevice;
+    private MediaDevice mPhoneDevice;
+
+    /**
+     * Register to start receiving callbacks for MediaDevice events.
+     */
+    public void registerCallback(DeviceCallback callback) {
+        synchronized (mCallbacks) {
+            mCallbacks.add(callback);
+        }
+    }
+
+    /**
+     * Unregister to stop receiving callbacks for MediaDevice events
+     */
+    public void unregisterCallback(DeviceCallback callback) {
+        synchronized (mCallbacks) {
+            mCallbacks.remove(callback);
+        }
+    }
+
+    public LocalMediaManager(Context context, String packageName, Notification notification) {
+        mContext = context;
+        mLocalBluetoothManager =
+                LocalBluetoothManager.getInstance(context, /* onInitCallback= */ null);
+        if (mLocalBluetoothManager == null) {
+            Log.e(TAG, "Bluetooth is not supported on this device");
+            return;
+        }
+
+        mBluetoothMediaManager =
+                new BluetoothMediaManager(context, mLocalBluetoothManager, notification);
+        mInfoMediaManager = new InfoMediaManager(context, packageName, notification);
+    }
+
+    /**
+     * Connect the MediaDevice to transfer media
+     * @param connectDevice the MediaDevice
+     */
+    public void connectDevice(MediaDevice connectDevice) {
+        if (connectDevice == mLastConnectedDevice) {
+            return;
+        }
+
+        if (mLastConnectedDevice != null) {
+            mLastConnectedDevice.disconnect();
+        }
+
+        connectDevice.connect();
+        if (connectDevice.isConnected()) {
+            mLastConnectedDevice = connectDevice;
+        }
+
+        final int state = connectDevice.isConnected()
+                ? MediaDeviceState.STATE_CONNECTED
+                : MediaDeviceState.STATE_DISCONNECTED;
+        dispatchSelectedDeviceStateChanged(connectDevice, state);
+    }
+
+    void dispatchSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state) {
+        synchronized (mCallbacks) {
+            for (DeviceCallback callback : mCallbacks) {
+                callback.onSelectedDeviceStateChanged(device, state);
+            }
+        }
+    }
+
+    /**
+     * Start scan connected MediaDevice
+     */
+    public void startScan() {
+        mMediaDevices.clear();
+        mBluetoothMediaManager.registerCallback(mMediaDeviceCallback);
+        mInfoMediaManager.registerCallback(mMediaDeviceCallback);
+        mBluetoothMediaManager.startScan();
+        mInfoMediaManager.startScan();
+    }
+
+    private void addPhoneDeviceIfNecessary() {
+        // add phone device to list if there have any Bluetooth device and cast device.
+        if (mMediaDevices.size() > 0 && !mMediaDevices.contains(mPhoneDevice)) {
+            if (mPhoneDevice == null) {
+                mPhoneDevice = new PhoneMediaDevice(mContext, mLocalBluetoothManager);
+            }
+            mMediaDevices.add(mPhoneDevice);
+        }
+    }
+
+    private void removePhoneMediaDeviceIfNecessary() {
+        // if PhoneMediaDevice is the last item in the list, remove it.
+        if (mMediaDevices.size() == 1 && mMediaDevices.contains(mPhoneDevice)) {
+            mMediaDevices.clear();
+        }
+    }
+
+    void dispatchDeviceListUpdate() {
+        synchronized (mCallbacks) {
+            for (DeviceCallback callback : mCallbacks) {
+                callback.onDeviceListUpdate(new ArrayList<>(mMediaDevices));
+            }
+        }
+    }
+
+    /**
+     * Stop scan MediaDevice
+     */
+    public void stopScan() {
+        mBluetoothMediaManager.unregisterCallback(mMediaDeviceCallback);
+        mInfoMediaManager.unregisterCallback(mMediaDeviceCallback);
+        mBluetoothMediaManager.stopScan();
+        mInfoMediaManager.stopScan();
+    }
+
+    class MediaDeviceCallback implements MediaManager.MediaDeviceCallback {
+        @Override
+        public void onDeviceAdded(MediaDevice device) {
+            if (!mMediaDevices.contains(device)) {
+                mMediaDevices.add(device);
+                addPhoneDeviceIfNecessary();
+                dispatchDeviceListUpdate();
+            }
+        }
+
+        @Override
+        public void onDeviceListAdded(List<MediaDevice> devices) {
+            mMediaDevices.addAll(devices);
+            addPhoneDeviceIfNecessary();
+            dispatchDeviceListUpdate();
+        }
+
+        @Override
+        public void onDeviceRemoved(MediaDevice device) {
+            if (mMediaDevices.contains(device)) {
+                mMediaDevices.remove(device);
+                removePhoneMediaDeviceIfNecessary();
+                dispatchDeviceListUpdate();
+            }
+        }
+
+        @Override
+        public void onDeviceListRemoved(List<MediaDevice> devices) {
+            mMediaDevices.removeAll(devices);
+            removePhoneMediaDeviceIfNecessary();
+            dispatchDeviceListUpdate();
+        }
+
+        @Override
+        public void onDeviceAttributesChanged() {
+            dispatchDeviceListUpdate();
+        }
+    }
+
+
+    /**
+     * Callback for notifying device information updating
+     */
+    public interface DeviceCallback {
+        /**
+         * Callback for notifying device list updated.
+         *
+         * @param devices MediaDevice list
+         */
+        void onDeviceListUpdate(List<MediaDevice> devices);
+
+        /**
+         * Callback for notifying the connected device is changed.
+         *
+         * @param device the changed connected MediaDevice
+         * @param state the current MediaDevice state, the possible values are:
+         * {@link MediaDeviceState#STATE_CONNECTED},
+         * {@link MediaDeviceState#STATE_CONNECTING},
+         * {@link MediaDeviceState#STATE_DISCONNECTED}
+         */
+        void onSelectedDeviceStateChanged(MediaDevice device, @MediaDeviceState int state);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
new file mode 100644
index 0000000..6c536f0
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDevice.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.media;
+
+import android.content.Context;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * MediaDevice represents a media device(such like Bluetooth device, cast device and phone device).
+ */
+public abstract class MediaDevice {
+
+    private static final String TAG = "MediaDevice";
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({MediaDeviceType.TYPE_BLUETOOTH_DEVICE,
+            MediaDeviceType.TYPE_CAST_DEVICE,
+            MediaDeviceType.TYPE_PHONE_DEVICE})
+    public @interface MediaDeviceType {
+        int TYPE_BLUETOOTH_DEVICE = 1;
+        int TYPE_CAST_DEVICE = 2;
+        int TYPE_PHONE_DEVICE = 3;
+    }
+
+    protected boolean mIsConnected = false;
+    protected Context mContext;
+    protected int mType;
+
+    MediaDevice(Context context, @MediaDeviceType int type) {
+        mType = type;
+        mContext = context;
+    }
+
+    /**
+     * Check the MediaDevice is be connected to transfer.
+     *
+     * @return true if the MediaDevice is be connected to transfer, false otherwise.
+     */
+    protected boolean isConnected() {
+        return mIsConnected;
+    }
+
+    /**
+     * Get name from MediaDevice.
+     *
+     * @return name of MediaDevice.
+     */
+    public abstract String getName();
+
+    /**
+     * Get resource id of MediaDevice.
+     *
+     * @return resource id of MediaDevice.
+     */
+    public abstract int getIcon();
+
+    /**
+     * Get unique ID that represent MediaDevice
+     * @return unique id of MediaDevice
+     */
+    public abstract String getId();
+
+    /**
+     * Transfer MediaDevice for media
+     */
+    public abstract void connect();
+
+    /**
+     * Stop transfer MediaDevice
+     */
+    public abstract void disconnect();
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
new file mode 100644
index 0000000..060e9ad
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaDeviceUtils.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.media;
+
+import androidx.mediarouter.media.MediaRouter;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
+/**
+ * MediaDeviceUtils provides utility function for MediaDevice
+ */
+public class MediaDeviceUtils {
+
+    /**
+     * Use CachedBluetoothDevice address to represent unique id
+     *
+     * @param cachedDevice the CachedBluetoothDevice
+     * @return CachedBluetoothDevice address
+     */
+    public static String getId(CachedBluetoothDevice cachedDevice) {
+        return cachedDevice.getAddress();
+    }
+
+    /**
+     * Use RouteInfo id to represent unique id
+     *
+     * @param route the RouteInfo
+     * @return RouteInfo id
+     */
+    public static String getId(MediaRouter.RouteInfo route) {
+        return route.getId();
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
new file mode 100644
index 0000000..72b6b09
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaManager.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.media;
+
+import android.app.Notification;
+import android.content.Context;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * MediaManager provide interface to get MediaDevice list.
+ */
+public abstract class MediaManager {
+
+    private static final String TAG = "MediaManager";
+
+    protected final Collection<MediaDeviceCallback> mCallbacks = new ArrayList<>();
+    protected final List<MediaDevice> mMediaDevices = new ArrayList<>();
+
+    protected Context mContext;
+    protected Notification mNotification;
+
+    MediaManager(Context context, Notification notification) {
+        mContext = context;
+        mNotification = notification;
+    }
+
+    protected void registerCallback(MediaDeviceCallback callback) {
+        synchronized (mCallbacks) {
+            if (!mCallbacks.contains(callback)) {
+                mCallbacks.add(callback);
+            }
+        }
+    }
+
+    protected void unregisterCallback(MediaDeviceCallback callback) {
+        synchronized (mCallbacks) {
+            if (mCallbacks.contains(callback)) {
+                mCallbacks.remove(callback);
+            }
+        }
+    }
+
+    /**
+     * Start scan connected MediaDevice
+     */
+    public abstract void startScan();
+
+    /**
+     * Stop scan MediaDevice
+     */
+    public abstract void stopScan();
+
+    protected MediaDevice findMediaDevice(String id) {
+        for (MediaDevice mediaDevice : mMediaDevices) {
+            if (mediaDevice.getId().equals(id)) {
+                return mediaDevice;
+            }
+        }
+        Log.e(TAG, "findMediaDevice() can't found device");
+        return null;
+    }
+
+    protected void dispatchDeviceAdded(MediaDevice mediaDevice) {
+        synchronized (mCallbacks) {
+            for (MediaDeviceCallback callback : mCallbacks) {
+                callback.onDeviceAdded(mediaDevice);
+            }
+        }
+    }
+
+    protected void dispatchDeviceRemoved(MediaDevice mediaDevice) {
+        synchronized (mCallbacks) {
+            for (MediaDeviceCallback callback : mCallbacks) {
+                callback.onDeviceRemoved(mediaDevice);
+            }
+        }
+    }
+
+    protected void dispatchDeviceListAdded() {
+        synchronized (mCallbacks) {
+            for (MediaDeviceCallback callback : mCallbacks) {
+                callback.onDeviceListAdded(mMediaDevices);
+            }
+        }
+    }
+
+    protected void dispatchDeviceListRemoved(List<MediaDevice> devices) {
+        synchronized (mCallbacks) {
+            for (MediaDeviceCallback callback : mCallbacks) {
+                callback.onDeviceListRemoved(devices);
+            }
+        }
+    }
+
+    protected void dispatchDeviceAttributesChanged() {
+        synchronized (mCallbacks) {
+            for (MediaDeviceCallback callback : mCallbacks) {
+                callback.onDeviceAttributesChanged();
+            }
+        }
+    }
+
+    /**
+     * Callback for notifying device is added, removed and attributes changed.
+     */
+    public interface MediaDeviceCallback {
+        /**
+         * Callback for notifying MediaDevice is added.
+         *
+         * @param device the MediaDevice
+         */
+        void onDeviceAdded(MediaDevice device);
+
+        /**
+         * Callback for notifying MediaDevice list is added.
+         *
+         * @param devices the MediaDevice list
+         */
+        void onDeviceListAdded(List<MediaDevice> devices);
+
+        /**
+         * Callback for notifying MediaDevice is removed.
+         *
+         * @param device the MediaDevice
+         */
+        void onDeviceRemoved(MediaDevice device);
+
+        /**
+         * Callback for notifying MediaDevice list is removed.
+         *
+         * @param devices the MediaDevice list
+         */
+        void onDeviceListRemoved(List<MediaDevice> devices);
+
+        /**
+         * Callback for notifying MediaDevice attributes is changed.
+         */
+        void onDeviceAttributesChanged();
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
new file mode 100644
index 0000000..5e49d6b
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.media;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.android.settingslib.R;
+import com.android.settingslib.bluetooth.A2dpProfile;
+import com.android.settingslib.bluetooth.HearingAidProfile;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+
+/**
+ * PhoneMediaDevice extends MediaDevice to represents Phone device.
+ */
+public class PhoneMediaDevice extends MediaDevice {
+
+    private static final String TAG = "PhoneMediaDevice";
+
+    public static final String ID = "phone_media_device_id_1";
+
+    private LocalBluetoothProfileManager mProfileManager;
+    private LocalBluetoothManager mLocalBluetoothManager;
+
+    PhoneMediaDevice(Context context, LocalBluetoothManager localBluetoothManager) {
+        super(context, MediaDeviceType.TYPE_PHONE_DEVICE);
+
+        mLocalBluetoothManager = localBluetoothManager;
+        mProfileManager = mLocalBluetoothManager.getProfileManager();
+    }
+
+    @Override
+    public String getName() {
+        return mContext
+                .getString(com.android.settingslib.R.string.media_transfer_phone_device_name);
+    }
+
+    @Override
+    public int getIcon() {
+        //TODO(b/117129183): This is not final icon for phone device, just for demo.
+        return R.drawable.ic_bt_cellphone;
+    }
+
+    @Override
+    public String getId() {
+        return ID;
+    }
+
+    @Override
+    public void connect() {
+        final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
+        final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
+
+        if (hapProfile != null && a2dpProfile != null) {
+            mIsConnected =
+                    hapProfile.setActiveDevice(null) && a2dpProfile.setActiveDevice(null);
+        }
+        Log.d(TAG, "connect() device : " + getName() + ", is selected : " + mIsConnected);
+    }
+
+    @Override
+    public void disconnect() {
+        //TODO(b/117129183): disconnected last select device
+        mIsConnected = false;
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
index fa59688..43c97df 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/PowerUtil.java
@@ -81,6 +81,30 @@
         return null;
     }
 
+    /**
+     * Method to produce a shortened string describing the remaining battery. Suitable for Quick
+     * Settings and other areas where space is constrained.
+     *
+     * @param context context to fetch descriptions from
+     * @param drainTimeMs The estimated time remaining before the phone dies in milliseconds.
+     *
+     * @return a properly formatted and localized short string describing how much time remains
+     * before the battery runs out.
+     */
+    @Nullable
+    public static String getBatteryRemainingShortStringFormatted(
+            Context context, long drainTimeMs) {
+        if (drainTimeMs <= 0) {
+            return null;
+        }
+
+        if (drainTimeMs <= ONE_DAY_MILLIS) {
+            return getRegularTimeRemainingShortString(context, drainTimeMs);
+        } else {
+            return getMoreThanOneDayShortString(context, drainTimeMs);
+        }
+    }
+
     private static String getShutdownImminentString(Context context, String percentageString) {
         return TextUtils.isEmpty(percentageString)
                 ? context.getString(R.string.power_remaining_duration_only_shutdown_imminent)
@@ -120,6 +144,14 @@
         }
     }
 
+    private static String getMoreThanOneDayShortString(Context context, long drainTimeMs) {
+        final long roundedTimeMs = roundTimeToNearestThreshold(drainTimeMs, ONE_HOUR_MILLIS);
+        CharSequence timeString = StringUtil.formatElapsedTime(context, roundedTimeMs,
+                false /* withSeconds */);
+
+        return context.getString(R.string.power_remaining_duration_only_short, timeString);
+    }
+
     private static String getMoreThanTwoDaysString(Context context, String percentageString) {
         final Locale currentLocale = context.getResources().getConfiguration().getLocales().get(0);
         final MeasureFormat frmt = MeasureFormat.getInstance(currentLocale, FormatWidth.SHORT);
@@ -162,6 +194,22 @@
         }
     }
 
+    private static String getRegularTimeRemainingShortString(Context context, long drainTimeMs) {
+        // Get the time of day we think device will die rounded to the nearest 15 min.
+        final long roundedTimeOfDayMs =
+                roundTimeToNearestThreshold(
+                        System.currentTimeMillis() + drainTimeMs,
+                        FIFTEEN_MINUTES_MILLIS);
+
+        // convert the time to a properly formatted string.
+        String skeleton = android.text.format.DateFormat.getTimeFormatString(context);
+        DateFormat fmt = DateFormat.getInstanceForSkeleton(skeleton);
+        Date date = Date.from(Instant.ofEpochMilli(roundedTimeOfDayMs));
+        CharSequence timeString = fmt.format(date);
+
+        return context.getString(R.string.power_discharge_by_only_short, timeString);
+    }
+
     public static long convertUsToMs(long timeUs) {
         return timeUs / 1000;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index e950e8e..22d5d83 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -161,6 +161,9 @@
     public static final int SECURITY_WEP = 1;
     public static final int SECURITY_PSK = 2;
     public static final int SECURITY_EAP = 3;
+    public static final int SECURITY_OWE = 4;
+    public static final int SECURITY_SAE = 5;
+    public static final int SECURITY_EAP_SUITE_B = 6;
 
     private static final int PSK_UNKNOWN = 0;
     private static final int PSK_WPA = 1;
@@ -433,7 +436,7 @@
         if (isConnectable()) {
             builder.append(',').append("connectable");
         }
-        if (security != SECURITY_NONE) {
+        if ((security != SECURITY_NONE) && (security != SECURITY_OWE)) {
             builder.append(',').append(securityToString(security, pskType));
         }
         builder.append(",level=").append(getLevel());
@@ -720,6 +723,9 @@
             case SECURITY_EAP:
                 return concise ? context.getString(R.string.wifi_security_short_eap) :
                     context.getString(R.string.wifi_security_eap);
+            case SECURITY_EAP_SUITE_B:
+                return concise ? context.getString(R.string.wifi_security_short_eap_suiteb) :
+                        context.getString(R.string.wifi_security_eap_suiteb);
             case SECURITY_PSK:
                 switch (pskType) {
                     case PSK_WPA:
@@ -739,6 +745,12 @@
             case SECURITY_WEP:
                 return concise ? context.getString(R.string.wifi_security_short_wep) :
                     context.getString(R.string.wifi_security_wep);
+            case SECURITY_SAE:
+                return concise ? context.getString(R.string.wifi_security_short_sae) :
+                    context.getString(R.string.wifi_security_sae);
+            case SECURITY_OWE:
+                return concise ? context.getString(R.string.wifi_security_short_owe) :
+                    context.getString(R.string.wifi_security_owe);
             case SECURITY_NONE:
             default:
                 return concise ? "" : context.getString(R.string.wifi_security_none);
@@ -980,13 +992,20 @@
      * Can only be called for unsecured networks.
      */
     public void generateOpenNetworkConfig() {
-        if (security != SECURITY_NONE)
+        if ((security != SECURITY_NONE) && (security != SECURITY_OWE)) {
             throw new IllegalStateException();
+        }
         if (mConfig != null)
             return;
         mConfig = new WifiConfiguration();
         mConfig.SSID = AccessPoint.convertToQuotedString(ssid);
-        mConfig.allowedKeyManagement.set(KeyMgmt.NONE);
+
+        if (security == SECURITY_NONE) {
+            mConfig.allowedKeyManagement.set(KeyMgmt.NONE);
+        } else {
+            mConfig.allowedKeyManagement.set(KeyMgmt.OWE);
+            mConfig.requirePMF = true;
+        }
     }
 
     public void saveWifiState(Bundle savedState) {
@@ -1288,22 +1307,38 @@
     private static int getSecurity(ScanResult result) {
         if (result.capabilities.contains("WEP")) {
             return SECURITY_WEP;
+        } else if (result.capabilities.contains("SAE")) {
+            return SECURITY_SAE;
         } else if (result.capabilities.contains("PSK")) {
             return SECURITY_PSK;
+        } else if (result.capabilities.contains("EAP_SUITE_B_192")) {
+            return SECURITY_EAP_SUITE_B;
         } else if (result.capabilities.contains("EAP")) {
             return SECURITY_EAP;
+        } else if (result.capabilities.contains("OWE")) {
+            return SECURITY_OWE;
         }
+
         return SECURITY_NONE;
     }
 
     static int getSecurity(WifiConfiguration config) {
+        if (config.allowedKeyManagement.get(KeyMgmt.SAE)) {
+            return SECURITY_SAE;
+        }
         if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
             return SECURITY_PSK;
         }
+        if (config.allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
+            return SECURITY_EAP_SUITE_B;
+        }
         if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
                 config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
             return SECURITY_EAP;
         }
+        if (config.allowedKeyManagement.get(KeyMgmt.OWE)) {
+            return SECURITY_OWE;
+        }
         return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
     }
 
@@ -1321,6 +1356,12 @@
             return "PSK";
         } else if (security == SECURITY_EAP) {
             return "EAP";
+        } else if (security == SECURITY_SAE) {
+            return "SAE";
+        } else if (security == SECURITY_EAP_SUITE_B) {
+            return "SUITE_B";
+        } else if (security == SECURITY_OWE) {
+            return "OWE";
         }
         return "NONE";
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index f3c43cc..db364a3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -200,7 +200,8 @@
         if (frictionImageView == null || mFrictionSld == null) {
             return;
         }
-        if (mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE) {
+        if ((mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE)
+                && (mAccessPoint.getSecurity() != AccessPoint.SECURITY_OWE)) {
             mFrictionSld.setState(STATE_SECURED);
         } else if (mAccessPoint.isMetered()) {
             mFrictionSld.setState(STATE_METERED);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 0dbc037..2f082b9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -152,7 +152,11 @@
     private boolean mNetworkScoringUiEnabled;
     private long mMaxSpeedLabelScoreCacheAge;
 
-
+    private static final String WIFI_SECURITY_PSK = "PSK";
+    private static final String WIFI_SECURITY_EAP = "EAP";
+    private static final String WIFI_SECURITY_SAE = "SAE";
+    private static final String WIFI_SECURITY_OWE = "OWE";
+    private static final String WIFI_SECURITY_SUITE_B_192 = "SUITE_B_192";
 
     @VisibleForTesting
     Scanner mScanner;
@@ -505,13 +509,18 @@
      * {@link #updateAccessPoints(List, List)}.
      */
     private void fetchScansAndConfigsAndUpdateAccessPoints() {
-        final List<ScanResult> newScanResults = mWifiManager.getScanResults();
+        List<ScanResult> newScanResults = mWifiManager.getScanResults();
+
+        // Filter all unsupported networks from the scan result list
+        final List<ScanResult> filteredScanResults =
+                filterScanResultsByCapabilities(newScanResults);
+
         if (isVerboseLoggingEnabled()) {
-            Log.i(TAG, "Fetched scan results: " + newScanResults);
+            Log.i(TAG, "Fetched scan results: " + filteredScanResults);
         }
 
         List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
-        updateAccessPoints(newScanResults, configs);
+        updateAccessPoints(filteredScanResults, configs);
     }
 
     /** Update the internal list of access points. */
@@ -937,4 +946,49 @@
 
         mListener.onAccessPointsChanged();
     }
+
+    /**
+     * Filters unsupported networks from scan results. New WPA3 networks and OWE networks
+     * may not be compatible with the device HW/SW.
+     * @param scanResults List of scan results
+     * @return List of filtered scan results based on local device capabilities
+     */
+    private List<ScanResult> filterScanResultsByCapabilities(List<ScanResult> scanResults) {
+        if (scanResults == null) {
+            return null;
+        }
+
+        // Get and cache advanced capabilities
+        final boolean isOweSupported = mWifiManager.isOweSupported();
+        final boolean isSaeSupported = mWifiManager.isWpa3SaeSupported();
+        final boolean isSuiteBSupported = mWifiManager.isWpa3SuiteBSupported();
+
+        List<ScanResult> filteredScanResultList = new ArrayList<>();
+
+        // Iterate through the list of scan results and filter out APs which are not
+        // compatible with our device.
+        for (ScanResult scanResult : scanResults) {
+            if (scanResult.capabilities.contains(WIFI_SECURITY_PSK)) {
+                // All devices (today) support RSN-PSK or WPA-PSK
+                // Add this here because some APs may support both PSK and SAE and the check
+                // below will filter it out.
+                filteredScanResultList.add(scanResult);
+                continue;
+            }
+
+            if ((scanResult.capabilities.contains(WIFI_SECURITY_SUITE_B_192) && !isSuiteBSupported)
+                    || (scanResult.capabilities.contains(WIFI_SECURITY_SAE) && !isSaeSupported)
+                    || (scanResult.capabilities.contains(WIFI_SECURITY_OWE) && !isOweSupported)) {
+                if (isVerboseLoggingEnabled()) {
+                    Log.v(TAG, "filterScanResultsByCapabilities: Filtering SSID "
+                            + scanResult.SSID + " with capabilities: " + scanResult.capabilities);
+                }
+            } else {
+                // Safe to add
+                filteredScanResultList.add(scanResult);
+            }
+        }
+
+        return filteredScanResultList;
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 7f9a5af..41aadd6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -234,6 +234,37 @@
     }
 
     @Test
+    public void getConnectionSummary_testHearingAidInCall_active() {
+        // Arrange:
+        //   1. Profile:       {HEARING_AID, Connected, Active}
+        //   2. Audio Manager: In Call
+        //   3. Battery Level: Unknown
+        updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
+        mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL);
+
+        // Act & Assert:
+        //   Get "Active" result without Battery Level.
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active");
+    }
+
+    @Test
+    public void getConnectionSummary_testHearingAidInCall_activeBattery10() {
+        // Arrange:
+        //   1. Profile:       {HEARING_AID, Connected, Active}
+        //   2. Audio Manager: In Call
+        //   3. Battery Level: 10
+        updateProfileStatus(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEARING_AID);
+        mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL);
+        mBatteryLevel = 10;
+
+        // Act & Assert:
+        //   Get "Active, 10% battery" result with Battery Level 10.
+        assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Active, 10% battery");
+    }
+
+    @Test
     public void getConnectionSummary_testMultipleProfilesActiveDevice() {
         // Test without battery level
         // Set A2DP and HFP profiles to be connected and test connection state summary
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
index 7a7f0d4..4ec6fb2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
@@ -15,15 +15,16 @@
  */
 package com.android.settingslib.core.instrumentation;
 
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import android.app.Activity;
+import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.util.Pair;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
@@ -33,6 +34,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.util.ReflectionHelpers;
 
@@ -72,10 +74,11 @@
         mProvider.logDashboardStartIntent(mContext, intent, MetricsEvent.SETTINGS_GESTURES);
 
         verify(mLogWriter).action(
-                eq(mContext),
-                eq(MetricsEvent.ACTION_SETTINGS_TILE_CLICK),
-                anyString(),
-                eq(Pair.create(MetricsEvent.FIELD_CONTEXT, MetricsEvent.SETTINGS_GESTURES)));
+                MetricsEvent.SETTINGS_GESTURES,
+                MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                SettingsEnums.PAGE_UNKNOWN,
+                Intent.ACTION_ASSIST,
+                0);
     }
 
     @Test
@@ -85,9 +88,34 @@
         mProvider.logDashboardStartIntent(mContext, intent, MetricsEvent.SETTINGS_GESTURES);
 
         verify(mLogWriter).action(
-                eq(mContext),
-                eq(MetricsEvent.ACTION_SETTINGS_TILE_CLICK),
-                anyString(),
-                eq(Pair.create(MetricsEvent.FIELD_CONTEXT, MetricsEvent.SETTINGS_GESTURES)));
+                MetricsEvent.SETTINGS_GESTURES,
+                MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+                SettingsEnums.PAGE_UNKNOWN,
+                "pkg/cls",
+                0);
+    }
+
+    @Test
+    public void getAttribution_noActivity_shouldReturnUnknown() {
+        assertThat(mProvider.getAttribution(null /* activity */))
+                .isEqualTo(SettingsEnums.PAGE_UNKNOWN);
+    }
+
+    @Test
+    public void getAttribution_notSet_shouldReturnUnknown() {
+        final Activity activity = Robolectric.setupActivity(Activity.class);
+
+        assertThat(mProvider.getAttribution(activity))
+                .isEqualTo(SettingsEnums.PAGE_UNKNOWN);
+    }
+
+    @Test
+    public void getAttribution_set_shouldReturnAttribution() {
+        final Intent intent = new Intent()
+                .putExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, 100);
+
+        final Activity activity = Robolectric.buildActivity(Activity.class, intent).create().get();
+
+        assertThat(mProvider.getAttribution(activity)).isEqualTo(100);
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
index be671e6..6285fcd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
@@ -15,25 +15,16 @@
  */
 package com.android.settingslib.core.instrumentation;
 
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .ACTION_SETTINGS_PREFERENCE_CHANGE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE;
-import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
-        .FIELD_SETTINGS_PREFERENCE_CHANGE_NAME;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE;
 
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.util.Pair;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
@@ -41,7 +32,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
-import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -50,11 +40,11 @@
 
     private static final String TEST_TAG = "tag";
     private static final String TEST_KEY = "key";
+    private static final String TEST_TAGGED_KEY = TEST_TAG + "/" + TEST_KEY;
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
 
-    private ArgumentMatcher<Pair<Integer, Object>> mNamePairMatcher;
     @Mock
     private MetricsFeatureProvider mMetricsFeature;
     private SharedPreferencesLogger mSharedPrefLogger;
@@ -63,7 +53,6 @@
     public void init() {
         MockitoAnnotations.initMocks(this);
         mSharedPrefLogger = new SharedPreferencesLogger(mContext, TEST_TAG, mMetricsFeature);
-        mNamePairMatcher = pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, String.class);
     }
 
     @Test
@@ -77,9 +66,11 @@
         editor.putInt(TEST_KEY, 2);
         editor.putInt(TEST_KEY, 2);
 
-        verify(mMetricsFeature, times(6)).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class)));
+        verify(mMetricsFeature, times(6)).action(eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE),
+                eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(TEST_TAGGED_KEY),
+                anyInt());
     }
 
     @Test
@@ -92,12 +83,16 @@
         editor.putBoolean(TEST_KEY, false);
 
 
-        verify(mMetricsFeature).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, true)));
-        verify(mMetricsFeature, times(3)).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, false)));
+        verify(mMetricsFeature).action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                TEST_TAGGED_KEY,
+                1);
+        verify(mMetricsFeature, times(3)).action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                TEST_TAGGED_KEY,
+                0);
     }
 
     @Test
@@ -109,9 +104,11 @@
         editor.putLong(TEST_KEY, 1);
         editor.putLong(TEST_KEY, 2);
 
-        verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class)));
+        verify(mMetricsFeature, times(4)).action(eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE),
+                eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(TEST_TAGGED_KEY),
+                anyInt());
     }
 
     @Test
@@ -121,10 +118,11 @@
         editor.putLong(TEST_KEY, 1);
         editor.putLong(TEST_KEY, veryBigNumber);
 
-        verify(mMetricsFeature).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(
-                        FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MAX_VALUE)));
+        verify(mMetricsFeature).action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                TEST_TAGGED_KEY,
+                Integer.MAX_VALUE);
     }
 
     @Test
@@ -134,10 +132,10 @@
         editor.putLong(TEST_KEY, 1);
         editor.putLong(TEST_KEY, veryNegativeNumber);
 
-        verify(mMetricsFeature).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(
-                        FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MIN_VALUE)));
+        verify(mMetricsFeature).action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                TEST_TAGGED_KEY, Integer.MIN_VALUE);
     }
 
     @Test
@@ -149,38 +147,20 @@
         editor.putFloat(TEST_KEY, 1);
         editor.putFloat(TEST_KEY, 2);
 
-        verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
-                argThat(mNamePairMatcher),
-                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE, Float.class)));
+        verify(mMetricsFeature, times(4)).action(eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(SettingsEnums.ACTION_SETTINGS_PREFERENCE_CHANGE),
+                eq(SettingsEnums.PAGE_UNKNOWN),
+                eq(TEST_TAGGED_KEY),
+                anyInt());
     }
 
     @Test
     public void logPackage_shouldUseLogPackageApi() {
         mSharedPrefLogger.logPackageName("key", "com.android.settings");
-        verify(mMetricsFeature).action(any(Context.class),
-                eq(ACTION_SETTINGS_PREFERENCE_CHANGE),
-                eq("com.android.settings"),
-                any(Pair.class));
-    }
-
-    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, Class clazz) {
-        return pair -> pair.first == tag && isInstanceOfType(pair.second, clazz);
-    }
-
-    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, boolean bool) {
-        return pair -> pair.first == tag
-                && isInstanceOfType(pair.second, Integer.class)
-                && pair.second.equals((bool ? 1 : 0));
-    }
-
-    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, int val) {
-        return pair -> pair.first == tag
-                && isInstanceOfType(pair.second, Integer.class)
-                && pair.second.equals(val);
-    }
-
-    /** Returns true if the instance is assignable to the type Clazz. */
-    private static boolean isInstanceOfType(Object instance, Class<?> clazz) {
-        return clazz.isInstance(instance);
+        verify(mMetricsFeature).action(SettingsEnums.PAGE_UNKNOWN,
+                ACTION_SETTINGS_PREFERENCE_CHANGE,
+                SettingsEnums.PAGE_UNKNOWN,
+                "tag/key:com.android.settings",
+                0);
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
index f78573a..b251c09 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
@@ -72,7 +72,7 @@
     @Test
     public void shouldLogVisibleWithSource() {
         final Intent sourceIntent = new Intent()
-                .putExtra(VisibilityLoggerMixin.EXTRA_SOURCE_METRICS_CATEGORY,
+                .putExtra(MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY,
                         MetricsProto.MetricsEvent.SETTINGS_GESTURES);
         final Activity activity = mock(Activity.class);
         when(activity.getIntent()).thenReturn(sourceIntent);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 2d43762..cbb6e82 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -481,6 +481,9 @@
         dumpSetting(s, p,
                 Settings.Global.EMULATE_DISPLAY_CUTOUT,
                 GlobalSettingsProto.Development.EMULATE_DISPLAY_CUTOUT);
+        dumpSetting(s, p,
+                Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS,
+                GlobalSettingsProto.Development.FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS);
         p.end(developmentToken);
 
         final long deviceToken = p.start(GlobalSettingsProto.DEVICE);
@@ -569,6 +572,15 @@
                 GlobalSettingsProto.Dropbox.SETTINGS);
         p.end(dropboxToken);
 
+        final long dynamicPowerSavingsToken = p.start(GlobalSettingsProto.DYNAMIC_POWER_SAVINGS);
+        dumpSetting(s, p,
+                Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
+                GlobalSettingsProto.DynamicPowerSavings.DISABLE_THRESHOLD);
+        dumpSetting(s, p,
+                Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
+                GlobalSettingsProto.DynamicPowerSavings.ENABLED);
+        p.end(dynamicPowerSavingsToken);
+
         final long emergencyToken = p.start(GlobalSettingsProto.EMERGENCY);
         dumpSetting(s, p,
                 Settings.Global.EMERGENCY_TONE,
@@ -675,6 +687,9 @@
         dumpSetting(s, p,
                 Settings.Global.GPU_DEBUG_LAYERS_GLES,
                 GlobalSettingsProto.Gpu.DEBUG_LAYERS_GLES);
+        dumpSetting(s, p,
+                Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP,
+                GlobalSettingsProto.Gpu.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP);
         p.end(gpuToken);
 
         final long hdmiToken = p.start(GlobalSettingsProto.HDMI);
@@ -788,6 +803,9 @@
         dumpSetting(s, p,
                 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
                 GlobalSettingsProto.LowPowerMode.TRIGGER_LEVEL_MAX);
+        dumpSetting(s, p,
+                Settings.Global.AUTOMATIC_POWER_SAVER_MODE,
+                GlobalSettingsProto.LowPowerMode.AUTOMATIC_POWER_SAVER_MODE);
         p.end(lpmToken);
 
         dumpSetting(s, p,
@@ -1120,6 +1138,9 @@
         dumpSetting(s, p,
                 Settings.Global.SHOW_FIRST_CRASH_DIALOG,
                 GlobalSettingsProto.SHOW_FIRST_CRASH_DIALOG);
+        dumpSetting(s, p,
+                Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED,
+                GlobalSettingsProto.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED);
         // Settings.Global.SHOW_PROCESSES intentionally excluded since it's deprecated.
         dumpSetting(s, p,
                 Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG,
@@ -1127,6 +1148,9 @@
         dumpSetting(s, p,
                 Settings.Global.SHOW_MUTE_IN_CRASH_DIALOG,
                 GlobalSettingsProto.SHOW_MUTE_IN_CRASH_DIALOG);
+        dumpSetting(s, p,
+                Settings.Global.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED,
+                GlobalSettingsProto.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED);
 
         final long smartSelectToken = p.start(GlobalSettingsProto.SMART_SELECTION);
         dumpSetting(s, p,
@@ -1636,12 +1660,6 @@
         dumpSetting(s, p,
                 Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
                 SecureSettingsProto.Accessibility.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES);
-        dumpSetting(s, p,
-                Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED,
-                SecureSettingsProto.Accessibility.MINIMUM_UI_TIMEOUT_ENABLED);
-        dumpSetting(s, p,
-                Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS,
-                SecureSettingsProto.Accessibility.MINIMUM_UI_TIMEOUT_MS);
         p.end(accessibilityToken);
 
         dumpSetting(s, p,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 822c39b..89690fb 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -83,6 +83,7 @@
     <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
     <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
     <uses-permission android:name="android.permission.DEVICE_POWER" />
+    <uses-permission android:name="android.permission.POWER_SAVER" />
     <uses-permission android:name="android.permission.INSTALL_LOCATION_PROVIDER" />
     <uses-permission android:name="android.permission.BACKUP" />
     <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES" />
diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS
new file mode 100644
index 0000000..75c0391
--- /dev/null
+++ b/packages/Shell/OWNERS
@@ -0,0 +1,10 @@
+svetoslavganov@google.com
+hackbod@google.com
+yamasani@google.com
+moltmann@google.com
+toddke@google.com
+jsharkey@google.com
+cbrubaker@google.com
+omakoto@google.com
+nandana@google.com
+felipeal@google.com
diff --git a/packages/SimAppDialog/res/drawable/illo_sim_app_dialog.xml b/packages/SimAppDialog/res/drawable/illo_sim_app_dialog.xml
new file mode 100644
index 0000000..8dd88b4
--- /dev/null
+++ b/packages/SimAppDialog/res/drawable/illo_sim_app_dialog.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2018 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.
+-->
+<!-- Empty drawable as this is not displayed by default. Must be provided by resource overlay. -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" />
diff --git a/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml b/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml
index 5bcce4d..12f9bb6 100644
--- a/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml
+++ b/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml
@@ -37,6 +37,22 @@
             android:text="@string/install_carrier_app_description_default"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"/>
-    </LinearLayout>
+
+        <com.android.setupwizardlib.view.FillContentLayout
+            android:id="@+id/illo_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:visibility="gone">
+
+            <ImageView
+                android:src="@drawable/illo_sim_app_dialog"
+                style="@style/SuwContentIllustration"
+                android:contentDescription="@string/install_carrier_app_image_content_description"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"/>
+
+        </com.android.setupwizardlib.view.FillContentLayout>
+</LinearLayout>
 
 </com.android.setupwizardlib.GlifLayout>
diff --git a/packages/SimAppDialog/res/values/bools.xml b/packages/SimAppDialog/res/values/bools.xml
new file mode 100644
index 0000000..4953d5e
--- /dev/null
+++ b/packages/SimAppDialog/res/values/bools.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Copyright (C) 2018 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">
+    <!--
+         Whether to show an illustration on the screen asking the user to download the carrier app.
+         May be set to true in a resource overlay as long as a drawable asset with ID
+         illo_sim_app_dialog is provided, along with a content description for accessibility with
+         string ID install_carrier_app_image_content_description.
+    -->
+    <bool name="show_sim_app_dialog_illo">false</bool>
+</resources>
diff --git a/packages/SimAppDialog/res/values/strings.xml b/packages/SimAppDialog/res/values/strings.xml
index 87941cb..9e8359c 100644
--- a/packages/SimAppDialog/res/values/strings.xml
+++ b/packages/SimAppDialog/res/values/strings.xml
@@ -32,4 +32,6 @@
     <string name="install_carrier_app_defer_action">Not now</string>
     <!-- Name of the button for downloading the carrier app [CHAR LIMIT=25] -->
     <string name="install_carrier_app_download_action">Download app</string>
-</resources>
\ No newline at end of file
+    <!-- Empty placeholder string for an illustration content description that is supplied via resource overlay. [DO NOT TRANSLATE] -->
+    <string name="install_carrier_app_image_content_description" translatable="false" />
+</resources>
diff --git a/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java b/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
index 9e9b80d..8e8d9f7 100644
--- a/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
+++ b/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
@@ -65,6 +65,11 @@
         Button downloadButton = findViewById(R.id.download_button);
         downloadButton.setOnClickListener(this);
 
+        // Show/hide illo depending on whether one was provided in a resource overlay
+        boolean showIllo = getResources().getBoolean(R.bool.show_sim_app_dialog_illo);
+        View illoContainer = findViewById(R.id.illo_container);
+        illoContainer.setVisibility(showIllo ? View.VISIBLE : View.GONE);
+
         // Include carrier name in description text if its present in the intent
         Intent intent = getIntent();
         if (intent != null) {
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index b770d5c..a00baad 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -66,7 +66,7 @@
     libs: [
         "telephony-common",
         "android.car",
-        "android.car.user",
+        "android.car.userlib",
     ],
 
     aaptflags: [
@@ -120,7 +120,7 @@
         "android.test.runner",
         "telephony-common",
         "android.car",
-        "android.car.user",
+        "android.car.userlib",
         "android.test.base",
     ],
     aaptflags: [
@@ -146,7 +146,7 @@
     libs: [
         "telephony-common",
         "android.car",
-        "android.car.user",
+        "android.car.userlib",
     ],
 
     dxflags: ["--multi-dex"],
@@ -183,7 +183,7 @@
     libs: [
         "telephony-common",
         "android.car",
-        "android.car.user",
+        "android.car.userlib",
     ],
 
     srcs: [
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index b2bb883..8aced61 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -90,6 +90,7 @@
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
     <uses-permission android:name="android.permission.MANAGE_ACTIVITY_STACKS" />
+    <uses-permission android:name="android.permission.START_ACTIVITY_AS_CALLER" />
     <uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
     <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
 
@@ -568,6 +569,22 @@
             </intent-filter>
         </activity>
 
+        <activity android:name=".chooser.ChooserActivity"
+                android:theme="@*android:style/Theme.NoDisplay"
+                android:finishOnCloseSystemDialogs="true"
+                android:excludeFromRecents="true"
+                android:documentLaunchMode="never"
+                android:relinquishTaskIdentity="true"
+                android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
+                android:process=":ui"
+                android:visibleToInstantApps="true">
+            <intent-filter>
+                <action android:name="android.intent.action.CHOOSER_UI" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.VOICE" />
+            </intent-filter>
+        </activity>
+
         <!-- Doze with notifications, run in main sysui process for every user  -->
         <service
             android:name=".doze.DozeService"
diff --git a/packages/SystemUI/README.md b/packages/SystemUI/README.md
index 33c5551..a8ce196 100644
--- a/packages/SystemUI/README.md
+++ b/packages/SystemUI/README.md
@@ -164,7 +164,7 @@
 
 ### [com.android.systemui.biometrics.BiometricDialogImpl](/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java)
 
-Fingerprint UI.
+Biometric UI.
 
 ---
 
diff --git a/packages/SystemUI/legacy/recents/res/values-as/strings.xml b/packages/SystemUI/legacy/recents/res/values-as/strings.xml
new file mode 100644
index 0000000..c742dab
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values-as/strings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_desc_recent_apps" msgid="2427210347871321373">"অৱলোকন।"</string>
+    <string name="accessibility_recents_item_will_be_dismissed" msgid="2355882496933479534">"শেহতীয়া-ৰ তালিকাৰ পৰা <xliff:g id="APP">%s</xliff:g>ক আঁতৰাওক।"</string>
+    <string name="accessibility_recents_item_dismissed" msgid="4816790842084268400">"শেহতীয়া-ৰ তালিকাৰ পৰা <xliff:g id="APP">%s</xliff:g>ক আঁতৰোৱা হ’ল।"</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="5693205751863608046">"শেহতীয়া-ৰ তালিকাৰ পৰা সকলো এপ্লিকেশ্বন আঁতৰোৱা হ’ল।"</string>
+    <string name="accessibility_recents_item_open_app_info" msgid="3406797323476801016">"<xliff:g id="APP">%s</xliff:g> এপ্লিকেশ্বনৰ তথ্য খোলক।"</string>
+    <string name="accessibility_recents_item_launched" msgid="4519918148638221791">"<xliff:g id="APP">%s</xliff:g>ক আৰম্ভ কৰা হৈছে।"</string>
+    <string name="recents_empty_message" msgid="7967713254531861311">"কোনো শেহতীয়া বস্তু নাই"</string>
+    <string name="recents_empty_message_dismissed_all" msgid="1850214584987361375">"আপুনি সকলো খালী কৰিলে"</string>
+    <string name="recents_app_info_button_label" msgid="8732926607391786762">"এপ্লিকেশ্বনৰ তথ্য"</string>
+    <string name="recents_lock_to_app_button_label" msgid="6087750201863853365">"স্ক্ৰীণ পিনিং"</string>
+    <string name="recents_search_bar_label" msgid="638132045925945941">"সন্ধান কৰক"</string>
+    <string name="recents_launch_error_message" msgid="9107963563503438012">"<xliff:g id="APP">%s</xliff:g>ক আৰম্ভ কৰিব পৰা নগ’ল।"</string>
+    <string name="recents_launch_disabled_message" msgid="826461671965217243">"<xliff:g id="APP">%s</xliff:g>টো সুৰক্ষিত ম’ডত অক্ষম কৰা হ’ল।"</string>
+    <string name="recents_stack_action_button_label" msgid="1974273390109881497">"সকলো মচক"</string>
+    <string name="recents_drag_hint_message" msgid="610417221848280136">"বিভাজিত স্ক্ৰীণ ব্যৱহাৰ কৰিবলৈ ইয়ালৈ টানি আনি এৰক"</string>
+    <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="488987777874979435">"আনুভূমিকভাৱে বিভাজন কৰক"</string>
+    <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="2498375296906391117">"উলম্বভাৱে বিভাজন কৰক"</string>
+    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="7368405969130304811">"কাষ্টম বিভাজন কৰক"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="8773505308411722524">"স্ক্ৰীণখনক ওপৰফাললৈ ভাগ কৰক"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="722594718192007972">"স্ক্ৰীণখনক বাওঁফাললৈ ভাগ কৰক"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="2479764030969301514">"স্ক্ৰীণখনক সোঁফাললৈ ভাগ কৰক"</string>
+</resources>
diff --git a/packages/SystemUI/legacy/recents/res/values-bn/strings.xml b/packages/SystemUI/legacy/recents/res/values-bn/strings.xml
new file mode 100644
index 0000000..b22672e
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values-bn/strings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_desc_recent_apps" msgid="2427210347871321373">"এক নজরে।"</string>
+    <string name="accessibility_recents_item_will_be_dismissed" msgid="2355882496933479534">"<xliff:g id="APP">%s</xliff:g> খারিজ করুন।"</string>
+    <string name="accessibility_recents_item_dismissed" msgid="4816790842084268400">"<xliff:g id="APP">%s</xliff:g> খারিজ করা হয়েছে।"</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="5693205751863608046">"সব সাম্প্রতিক অ্যাপ্লিকেশন খারিজ করা হয়েছে।"</string>
+    <string name="accessibility_recents_item_open_app_info" msgid="3406797323476801016">"<xliff:g id="APP">%s</xliff:g> অ্যাপ্লিকেশনের তথ্য খুলুন।"</string>
+    <string name="accessibility_recents_item_launched" msgid="4519918148638221791">"<xliff:g id="APP">%s</xliff:g> শুরু করা হচ্ছে।"</string>
+    <string name="recents_empty_message" msgid="7967713254531861311">"কোনো সাম্প্রতিক আইটেম নেই"</string>
+    <string name="recents_empty_message_dismissed_all" msgid="1850214584987361375">"আপনি সবকিছু মুছে দিয়েছেন"</string>
+    <string name="recents_app_info_button_label" msgid="8732926607391786762">"অ্যাপ্লিকেশনের তথ্য"</string>
+    <string name="recents_lock_to_app_button_label" msgid="6087750201863853365">"স্ক্রিন পিন করা"</string>
+    <string name="recents_search_bar_label" msgid="638132045925945941">"খুঁজুন"</string>
+    <string name="recents_launch_error_message" msgid="9107963563503438012">"<xliff:g id="APP">%s</xliff:g> চালু করা যায়নি।"</string>
+    <string name="recents_launch_disabled_message" msgid="826461671965217243">"নিরাপদ মোডে <xliff:g id="APP">%s</xliff:g> বন্ধ করা আছে।"</string>
+    <string name="recents_stack_action_button_label" msgid="1974273390109881497">"সবগুলি মুছে দিন"</string>
+    <string name="recents_drag_hint_message" msgid="610417221848280136">"স্প্লিট স্ক্রিন ব্যবহার করতে এখানে টেনে আনুন"</string>
+    <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="488987777874979435">"অনুভূমিক স্প্লিট করুন"</string>
+    <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="2498375296906391117">"উল্লম্ব স্প্লিট করুন"</string>
+    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="7368405969130304811">"কাস্টম স্প্লিট করুন"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="8773505308411722524">"স্ক্রিনটি উপরের দিকে স্প্লিট করুন"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="722594718192007972">"স্ক্রিনটি বাঁদিকে স্প্লিট করুন"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="2479764030969301514">"স্ক্রিনটি ডানদিকে স্প্লিট করুন"</string>
+</resources>
diff --git a/packages/SystemUI/legacy/recents/res/values-es-rUS/strings.xml b/packages/SystemUI/legacy/recents/res/values-es-rUS/strings.xml
index 8bf3807..f212b02 100644
--- a/packages/SystemUI/legacy/recents/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/legacy/recents/res/values-es-rUS/strings.xml
@@ -21,9 +21,9 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="accessibility_desc_recent_apps" msgid="2427210347871321373">"Recientes"</string>
     <string name="accessibility_recents_item_will_be_dismissed" msgid="2355882496933479534">"Permite descartar <xliff:g id="APP">%s</xliff:g>."</string>
-    <string name="accessibility_recents_item_dismissed" msgid="4816790842084268400">"<xliff:g id="APP">%s</xliff:g> descartada"</string>
+    <string name="accessibility_recents_item_dismissed" msgid="4816790842084268400">"Se descartó <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="5693205751863608046">"Se descartaron todas las aplicaciones recientes."</string>
-    <string name="accessibility_recents_item_open_app_info" msgid="3406797323476801016">"Permite abrir la información de aplicación de <xliff:g id="APP">%s</xliff:g>."</string>
+    <string name="accessibility_recents_item_open_app_info" msgid="3406797323476801016">"Permite abrir la información de la aplicación de <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="accessibility_recents_item_launched" msgid="4519918148638221791">"Iniciando <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="recents_empty_message" msgid="7967713254531861311">"No hay elementos recientes"</string>
     <string name="recents_empty_message_dismissed_all" msgid="1850214584987361375">"Todo borrado"</string>
diff --git a/packages/SystemUI/legacy/recents/res/values-hi/strings.xml b/packages/SystemUI/legacy/recents/res/values-hi/strings.xml
index c9ac2a0..3f19f33 100644
--- a/packages/SystemUI/legacy/recents/res/values-hi/strings.xml
+++ b/packages/SystemUI/legacy/recents/res/values-hi/strings.xml
@@ -37,7 +37,7 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="488987777874979435">"क्षैतिज रूप से दो हिस्सों में बाँटें (स्प्लिट करें)"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="2498375296906391117">"लम्बवत रूप से दो हिस्सों में बाँटें (स्प्लिट करें)"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="7368405969130304811">"अपने मुताबिक दो हिस्सों में बाँटें (स्प्लिट स्क्रीन करें)"</string>
-    <string name="recents_accessibility_split_screen_top" msgid="8773505308411722524">"ऊपर की ओर दो स्क्रीन बनाएं"</string>
-    <string name="recents_accessibility_split_screen_left" msgid="722594718192007972">"बाईं ओर दो स्क्रीन बनाएं"</string>
-    <string name="recents_accessibility_split_screen_right" msgid="2479764030969301514">"दाईं ओर दो स्क्रीन बनाएं"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="8773505308411722524">"ऊपर की ओर दूसरी स्क्रीन बनाएं"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="722594718192007972">"बाईं ओर दूसरी स्क्रीन बनाएं"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="2479764030969301514">"दाईं ओर दूसरी स्क्रीन बनाएं"</string>
 </resources>
diff --git a/packages/SystemUI/legacy/recents/res/values-ml/strings.xml b/packages/SystemUI/legacy/recents/res/values-ml/strings.xml
new file mode 100644
index 0000000..6dd797e
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values-ml/strings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_desc_recent_apps" msgid="2427210347871321373">"അവലോകനം."</string>
+    <string name="accessibility_recents_item_will_be_dismissed" msgid="2355882496933479534">"<xliff:g id="APP">%s</xliff:g> ഡിസ്‌മിസ് ചെയ്യുക."</string>
+    <string name="accessibility_recents_item_dismissed" msgid="4816790842084268400">"<xliff:g id="APP">%s</xliff:g> ഡിസ്‌മിസ് ചെയ്‌തു."</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="5693205751863608046">"അടുത്തിടെയുള്ള എല്ലാ ആപ്പുകളും ഡിസ്‌മിസ് ചെയ്‌തു."</string>
+    <string name="accessibility_recents_item_open_app_info" msgid="3406797323476801016">"<xliff:g id="APP">%s</xliff:g> ആപ്പ് വിവരങ്ങൾ തുറക്കുക."</string>
+    <string name="accessibility_recents_item_launched" msgid="4519918148638221791">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കുന്നു."</string>
+    <string name="recents_empty_message" msgid="7967713254531861311">"സമീപകാല ഇനങ്ങൾ ഒന്നുമില്ല"</string>
+    <string name="recents_empty_message_dismissed_all" msgid="1850214584987361375">"നിങ്ങൾ എല്ലാം മായ്ച്ചിരിക്കുന്നു"</string>
+    <string name="recents_app_info_button_label" msgid="8732926607391786762">"ആപ്പ് വിവരങ്ങൾ"</string>
+    <string name="recents_lock_to_app_button_label" msgid="6087750201863853365">"സ്ക്രീൻ പിൻ ചെയ്യൽ"</string>
+    <string name="recents_search_bar_label" msgid="638132045925945941">"തിരയുക"</string>
+    <string name="recents_launch_error_message" msgid="9107963563503438012">"<xliff:g id="APP">%s</xliff:g> ആരംഭിക്കാനായില്ല"</string>
+    <string name="recents_launch_disabled_message" msgid="826461671965217243">"സുരക്ഷിത മോഡിൽ <xliff:g id="APP">%s</xliff:g> പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു."</string>
+    <string name="recents_stack_action_button_label" msgid="1974273390109881497">"എല്ലാം മായ്‌ക്കുക"</string>
+    <string name="recents_drag_hint_message" msgid="610417221848280136">"സ്പ്ലിറ്റ് സ്ക്രീൻ ഉപയോഗിക്കാൻ, ഇവിടെ വലിച്ചിടുക"</string>
+    <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="488987777874979435">"തിരശ്ചീനമായി സ്‌പ്ലിറ്റ് ചെയ്യുക"</string>
+    <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="2498375296906391117">"ലംബമായി സ്‌പ്ലിറ്റ് ചെയ്യുക"</string>
+    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="7368405969130304811">"ഇഷ്‌ടാനുസൃതമായി സ്‌പ്ലിറ്റ് ചെയ്യുക"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="8773505308411722524">"സ്ക്രീൻ മുകളിലോട്ട് സ്പ്ലിറ്റ് ചെയ്യുക"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="722594718192007972">"സ്ക്രീൻ ഇടത്തോട്ട് സ്പ്ലിറ്റ് ചെയ്യുക"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="2479764030969301514">"സ്ക്രീൻ വലത്തോട്ട് സ്‌പ്ലിറ്റ് ചെയ്യുക"</string>
+</resources>
diff --git a/packages/SystemUI/legacy/recents/res/values-ne/strings.xml b/packages/SystemUI/legacy/recents/res/values-ne/strings.xml
new file mode 100644
index 0000000..0113833
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values-ne/strings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_desc_recent_apps" msgid="2427210347871321373">"परिदृश्य।"</string>
+    <string name="accessibility_recents_item_will_be_dismissed" msgid="2355882496933479534">"<xliff:g id="APP">%s</xliff:g> खारेज गर्नुहोस्।"</string>
+    <string name="accessibility_recents_item_dismissed" msgid="4816790842084268400">"<xliff:g id="APP">%s</xliff:g> खारेज गरिएको छ।"</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="5693205751863608046">"हालका सबै अनुप्रयोगहरू खारेज गरियो।"</string>
+    <string name="accessibility_recents_item_open_app_info" msgid="3406797323476801016">"<xliff:g id="APP">%s</xliff:g> अनुप्रयोग सम्बन्धी जानकारी खोल्नुहोस्।"</string>
+    <string name="accessibility_recents_item_launched" msgid="4519918148638221791">"<xliff:g id="APP">%s</xliff:g> सुरु गर्दै।"</string>
+    <string name="recents_empty_message" msgid="7967713254531861311">"हालसालैको कुनै पनि वस्तु छैन"</string>
+    <string name="recents_empty_message_dismissed_all" msgid="1850214584987361375">"तपाईंले सबै कुरा खाली गर्नुभएको छ"</string>
+    <string name="recents_app_info_button_label" msgid="8732926607391786762">"अनुप्रयोगको जानकारी"</string>
+    <string name="recents_lock_to_app_button_label" msgid="6087750201863853365">"स्क्रिन पिनिसङ"</string>
+    <string name="recents_search_bar_label" msgid="638132045925945941">"खोज्नुहोस्"</string>
+    <string name="recents_launch_error_message" msgid="9107963563503438012">"<xliff:g id="APP">%s</xliff:g> सुरु गर्न सकिएन।"</string>
+    <string name="recents_launch_disabled_message" msgid="826461671965217243">"<xliff:g id="APP">%s</xliff:g> लाई सुरक्षित मोडमा असक्षम पारिएको छ।"</string>
+    <string name="recents_stack_action_button_label" msgid="1974273390109881497">"सबै हटाउनुहोस्"</string>
+    <string name="recents_drag_hint_message" msgid="610417221848280136">"विभाजित स्क्रिनको प्रयोग गर्न यहाँ तान्नुहोस्"</string>
+    <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="488987777874979435">"तेर्सो रूपमा विभाजन गर्नुहोस्"</string>
+    <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="2498375296906391117">"ठाडो रूपमा विभाजन गर्नुहोस्"</string>
+    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="7368405969130304811">"आफू अनुकूल विभाजन गर्नुहोस्"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="8773505308411722524">"विभाजित स्क्रिन शीर्ष स्थानमा राख्नुहोस्‌"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="722594718192007972">"विभाजित स्क्रिन बायाँतर्फ राख्नुहोस्‌"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="2479764030969301514">"विभाजित स्क्रिन दायाँतर्फ राख्नुहोस्‌"</string>
+</resources>
diff --git a/packages/SystemUI/legacy/recents/res/values-or/strings.xml b/packages/SystemUI/legacy/recents/res/values-or/strings.xml
new file mode 100644
index 0000000..7ffcc94
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values-or/strings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_desc_recent_apps" msgid="2427210347871321373">"ସଂକ୍ଷିପ୍ତ ବିବରଣୀ"</string>
+    <string name="accessibility_recents_item_will_be_dismissed" msgid="2355882496933479534">"<xliff:g id="APP">%s</xliff:g> ଖାରଜ।"</string>
+    <string name="accessibility_recents_item_dismissed" msgid="4816790842084268400">"<xliff:g id="APP">%s</xliff:g> ଖାରଜ କରିଦିଆଗଲା।"</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="5693205751863608046">"ସମସ୍ତ ସମ୍ପ୍ରତି ଆପ୍ଲିକେସନ୍‍ଗୁଡ଼ିକ ଖାରଜ କରାଯାଇଛି।"</string>
+    <string name="accessibility_recents_item_open_app_info" msgid="3406797323476801016">"<xliff:g id="APP">%s</xliff:g> ଆପ୍ଲିକେସନ୍‍ ସୂଚନା ଖୋଲନ୍ତୁ।"</string>
+    <string name="accessibility_recents_item_launched" msgid="4519918148638221791">"<xliff:g id="APP">%s</xliff:g> ଆରମ୍ଭ ହେଉଛି।"</string>
+    <string name="recents_empty_message" msgid="7967713254531861311">"କୌଣସି ସାମ୍ପ୍ରତିକ ଆଇଟମ୍ ନାହିଁ"</string>
+    <string name="recents_empty_message_dismissed_all" msgid="1850214584987361375">"ଆପଣ ସୁବୁକିଛି ଖାଲି କରିଦେଇଛନ୍ତି"</string>
+    <string name="recents_app_info_button_label" msgid="8732926607391786762">"ଆପ୍ଲିକେସନ୍‍ ସୂଚନା"</string>
+    <string name="recents_lock_to_app_button_label" msgid="6087750201863853365">"ସ୍କ୍ରିନ୍‌ ଲକ୍‌"</string>
+    <string name="recents_search_bar_label" msgid="638132045925945941">"ଖୋଜନ୍ତୁ"</string>
+    <string name="recents_launch_error_message" msgid="9107963563503438012">"<xliff:g id="APP">%s</xliff:g> କୁ ଆରମ୍ଭ କରାଯାଇପାରିଲା ନାହିଁ।"</string>
+    <string name="recents_launch_disabled_message" msgid="826461671965217243">"<xliff:g id="APP">%s</xliff:g> ସୁରକ୍ଷିତ-ମୋଡ୍‌ରେ ଅକ୍ଷମ ଅଟେ।"</string>
+    <string name="recents_stack_action_button_label" msgid="1974273390109881497">"ସବୁ ଖାଲି କରନ୍ତୁ"</string>
+    <string name="recents_drag_hint_message" msgid="610417221848280136">"ସ୍ପ୍ଲିଟ୍‍ ସ୍କ୍ରିନ୍‍ ବ୍ୟବହାର କରିବା ପାଇଁ ଏଠାକୁ ଡ୍ରାଗ୍‌ କରନ୍ତୁ"</string>
+    <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="488987777874979435">"ଭୂସମାନ୍ତରଭାବରେ ଭାଗ କରନ୍ତୁ"</string>
+    <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="2498375296906391117">"ଭୂଲମ୍ବଭାବରେ ଭାଗ କରନ୍ତୁ"</string>
+    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="7368405969130304811">"କଷ୍ଟମ୍‍ କରି ଭାଗ କରନ୍ତୁ"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="8773505308411722524">"ସ୍କ୍ରିନ୍‌କୁ ଉପର ଆଡ଼କୁ ଭାଗ କରନ୍ତୁ"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="722594718192007972">"ସ୍କ୍ରିନ୍‌କୁ ବାମ ଆଡ଼କୁ ଭାଗ କରନ୍ତୁ"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="2479764030969301514">"ସ୍କ୍ରିନ୍‌କୁ ଡାହାଣ ଆଡ଼କୁ ଭାଗ କରନ୍ତୁ"</string>
+</resources>
diff --git a/packages/SystemUI/legacy/recents/res/values-si/strings.xml b/packages/SystemUI/legacy/recents/res/values-si/strings.xml
new file mode 100644
index 0000000..cae8357
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values-si/strings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_desc_recent_apps" msgid="2427210347871321373">"දළ විශ්ලේෂණය."</string>
+    <string name="accessibility_recents_item_will_be_dismissed" msgid="2355882496933479534">"<xliff:g id="APP">%s</xliff:g> ඉවත ලන්න."</string>
+    <string name="accessibility_recents_item_dismissed" msgid="4816790842084268400">"<xliff:g id="APP">%s</xliff:g> ඉවත දමා ඇත."</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="5693205751863608046">"සියලුම මෑත යෙඳුම් ඉවත ලන ලදී."</string>
+    <string name="accessibility_recents_item_open_app_info" msgid="3406797323476801016">"<xliff:g id="APP">%s</xliff:g> යෙදුම් තොරතුරු විවෘත කරයි."</string>
+    <string name="accessibility_recents_item_launched" msgid="4519918148638221791">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කරමින්."</string>
+    <string name="recents_empty_message" msgid="7967713254531861311">"මෑත අයිතම නැත"</string>
+    <string name="recents_empty_message_dismissed_all" msgid="1850214584987361375">"ඔබ සියලු දේ හිස් කර ඇත"</string>
+    <string name="recents_app_info_button_label" msgid="8732926607391786762">"යෙදුම් තොරතුරු"</string>
+    <string name="recents_lock_to_app_button_label" msgid="6087750201863853365">"තිර ඇමිණීම"</string>
+    <string name="recents_search_bar_label" msgid="638132045925945941">"සෙවීම"</string>
+    <string name="recents_launch_error_message" msgid="9107963563503438012">"<xliff:g id="APP">%s</xliff:g> ආරම්භ කළ නොහැකි විය."</string>
+    <string name="recents_launch_disabled_message" msgid="826461671965217243">"<xliff:g id="APP">%s</xliff:g> ආරක්ෂිත ප්‍රකාරය තුළ අබලයි."</string>
+    <string name="recents_stack_action_button_label" msgid="1974273390109881497">"සියල්ල හිස් කරන්න"</string>
+    <string name="recents_drag_hint_message" msgid="610417221848280136">"බෙදුම් තිරය භාවිත කිරීමට මෙතැනට අදින්න"</string>
+    <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="488987777874979435">"තිරස්ව වෙන් කරන්න"</string>
+    <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="2498375296906391117">"සිරස්ව වෙන් කරන්න"</string>
+    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="7368405969130304811">"අභිමත ලෙස වෙන් කරන්න"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="8773505308411722524">"තිරය ඉහළට බෙදන්න"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="722594718192007972">"තිරය වමට බෙදන්න"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="2479764030969301514">"තිරය දකුණට බෙදන්න"</string>
+</resources>
diff --git a/packages/SystemUI/legacy/recents/res/values-ta/strings.xml b/packages/SystemUI/legacy/recents/res/values-ta/strings.xml
new file mode 100644
index 0000000..91643fd
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values-ta/strings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_desc_recent_apps" msgid="2427210347871321373">"மேலோட்டப் பார்வை."</string>
+    <string name="accessibility_recents_item_will_be_dismissed" msgid="2355882496933479534">"<xliff:g id="APP">%s</xliff:g> ஆப்ஸை அகற்றும்."</string>
+    <string name="accessibility_recents_item_dismissed" msgid="4816790842084268400">"<xliff:g id="APP">%s</xliff:g> அகற்றப்பட்டது."</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="5693205751863608046">"அனைத்துச் சமீபத்திய ஆப்ஸும் அகற்றப்பட்டன."</string>
+    <string name="accessibility_recents_item_open_app_info" msgid="3406797323476801016">"<xliff:g id="APP">%s</xliff:g> ஆப்ஸ் பற்றிய தகவலைத் திறக்கும்."</string>
+    <string name="accessibility_recents_item_launched" msgid="4519918148638221791">"<xliff:g id="APP">%s</xliff:g> ஆப்ஸைத் தொடங்குகிறது."</string>
+    <string name="recents_empty_message" msgid="7967713254531861311">"சமீபத்தியவை எதுவுமில்லை"</string>
+    <string name="recents_empty_message_dismissed_all" msgid="1850214584987361375">"அனைத்தையும் அழித்துவிட்டீர்கள்"</string>
+    <string name="recents_app_info_button_label" msgid="8732926607391786762">"ஆப்ஸ் பற்றிய தகவல்"</string>
+    <string name="recents_lock_to_app_button_label" msgid="6087750201863853365">"திரையைப் பின் செய்"</string>
+    <string name="recents_search_bar_label" msgid="638132045925945941">"தேடு"</string>
+    <string name="recents_launch_error_message" msgid="9107963563503438012">"<xliff:g id="APP">%s</xliff:g> ஆப்ஸைத் தொடங்க இயலவில்லை."</string>
+    <string name="recents_launch_disabled_message" msgid="826461671965217243">"பாதுகாப்புப் பயன்முறையில் <xliff:g id="APP">%s</xliff:g> முடக்கப்பட்டது."</string>
+    <string name="recents_stack_action_button_label" msgid="1974273390109881497">"அனைத்தையும் அழி"</string>
+    <string name="recents_drag_hint_message" msgid="610417221848280136">"\'திரைப் பிரிப்பைப்\' பயன்படுத்த இங்கே இழுக்கவும்"</string>
+    <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="488987777874979435">"கிடைமட்டமாகப் பிரி"</string>
+    <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="2498375296906391117">"செங்குத்தாகப் பிரி"</string>
+    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="7368405969130304811">"தனிப்பயன் விருப்பத்தில் பிரி"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="8773505308411722524">"திரையை மேற்புறமாகப் பிரிக்கும்"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="722594718192007972">"திரையை இடப்புறமாகப் பிரிக்கும்"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="2479764030969301514">"திரையை வலப்புறமாகப் பிரிக்கும்"</string>
+</resources>
diff --git a/packages/SystemUI/legacy/recents/res/values-te/strings.xml b/packages/SystemUI/legacy/recents/res/values-te/strings.xml
new file mode 100644
index 0000000..ea4e638
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values-te/strings.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="accessibility_desc_recent_apps" msgid="2427210347871321373">"అవలోకనం."</string>
+    <string name="accessibility_recents_item_will_be_dismissed" msgid="2355882496933479534">"<xliff:g id="APP">%s</xliff:g>ని తీసివేయండి."</string>
+    <string name="accessibility_recents_item_dismissed" msgid="4816790842084268400">"<xliff:g id="APP">%s</xliff:g> తీసివేయబడింది."</string>
+    <string name="accessibility_recents_all_items_dismissed" msgid="5693205751863608046">"అన్ని ఇటీవలి యాప్‌లు తీసివేయబడ్డాయి."</string>
+    <string name="accessibility_recents_item_open_app_info" msgid="3406797323476801016">"<xliff:g id="APP">%s</xliff:g> యాప్ సమాచారాన్ని తెరుస్తుంది."</string>
+    <string name="accessibility_recents_item_launched" msgid="4519918148638221791">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభిస్తోంది."</string>
+    <string name="recents_empty_message" msgid="7967713254531861311">"ఇటీవలి అంశాలు ఏవీ లేవు"</string>
+    <string name="recents_empty_message_dismissed_all" msgid="1850214584987361375">"మీరు అన్నింటినీ తీసివేసారు"</string>
+    <string name="recents_app_info_button_label" msgid="8732926607391786762">"యాప్ సమాచారం"</string>
+    <string name="recents_lock_to_app_button_label" msgid="6087750201863853365">"స్క్రీన్‌కు పిన్ చేయడం"</string>
+    <string name="recents_search_bar_label" msgid="638132045925945941">"వెతుకు"</string>
+    <string name="recents_launch_error_message" msgid="9107963563503438012">"<xliff:g id="APP">%s</xliff:g>ని ప్రారంభించడం సాధ్యపడలేదు."</string>
+    <string name="recents_launch_disabled_message" msgid="826461671965217243">"<xliff:g id="APP">%s</xliff:g> సురక్షిత-మోడ్‌లో నిలిపివేయబడింది."</string>
+    <string name="recents_stack_action_button_label" msgid="1974273390109881497">"అన్నీ తీసివేయి"</string>
+    <string name="recents_drag_hint_message" msgid="610417221848280136">"విభజన స్క్రీన్‌ను ఉపయోగించడానికి ఇక్కడ లాగండి"</string>
+    <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="488987777874979435">"అడ్డంగా విభజించు"</string>
+    <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="2498375296906391117">"నిలువుగా విభజించు"</string>
+    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="7368405969130304811">"అనుకూలంగా విభజించు"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="8773505308411722524">"స్క్రీన్‌ని ఎగువకు విభజించు"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="722594718192007972">"స్క్రీన్‌ని ఎడమ వైపుకి విభజించు"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="2479764030969301514">"స్క్రీన్‌ని కుడి వైపుకి విభజించు"</string>
+</resources>
diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsView.java
index 0d758df..dfa38ba 100644
--- a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsView.java
@@ -497,7 +497,7 @@
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        mSystemInsets.set(insets.getSystemWindowInsets());
+        mSystemInsets.set(insets.getSystemWindowInsetsAsRect());
         mTaskStackView.setSystemInsets(mSystemInsets);
         requestLayout();
         return insets;
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
index b4fc820..7cb63ea 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
@@ -13,11 +13,11 @@
  */
 package com.android.systemui.plugins;
 
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-
 import android.graphics.Paint.Style;
 import android.view.View;
 
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
 /**
  * This plugin is used to replace main clock in keyguard.
  */
@@ -44,4 +44,15 @@
      * @param color A color value.
      */
     void setTextColor(int color);
+
+    /**
+     * Notifies that time tick alarm from doze service fired.
+     */
+    default void dozeTimeTick() { }
+
+    /**
+     * Set the amount (ratio) that the device has transitioned to doze.
+     * @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
+     */
+    default void setDarkAmount(float darkAmount) {}
 }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingPlugin.java
new file mode 100644
index 0000000..dce02e1
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingPlugin.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 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.plugins;
+
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
+/**
+ * Used to capture Falsing data (related to unlocking the screen).
+ *
+ * The intent is that the data can later be analyzed to validate the quality of the
+ * {@link com.android.systemui.classifier.FalsingManager}.
+ */
+@ProvidesInterface(action = FalsingPlugin.ACTION, version = FalsingPlugin.VERSION)
+public interface FalsingPlugin extends Plugin {
+    String ACTION = "com.android.systemui.action.FALSING_PLUGIN";
+    int VERSION = 1;
+
+    /**
+     * Called when there is data to be recorded.
+     *
+     * @param success Indicates whether the action is considered a success.
+     * @param data The raw data to be recorded for analysis.
+     */
+    void dataCollected(boolean success, byte[] data);
+}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
index 814324e..99cc3a3 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/phone/NavGesture.java
@@ -36,7 +36,7 @@
 
         public boolean onInterceptTouchEvent(MotionEvent event);
 
-        public void setBarState(boolean vertical, boolean isRtl);
+        public void setBarState(boolean isRtl, int navBarPosition);
 
         public void onDraw(Canvas canvas);
 
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index b51ad1c..51f6a4b 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -20,8 +20,8 @@
 <!-- This is a view that shows general status information in Keyguard. -->
 <com.android.keyguard.KeyguardSliceView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_marginStart="16dp"
-    android:layout_marginEnd="16dp"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_gravity="center_horizontal"
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index 50dc26b..f4a3794 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -118,14 +118,14 @@
     <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"Skift indtastningsmetode"</string>
     <string name="airplane_mode" msgid="3807209033737676010">"Flytilstand"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"Du skal angive et mønster, når du har genstartet enheden"</string>
-    <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"Der skal indtastes en pinkode efter genstart af enheden"</string>
-    <string name="kg_prompt_reason_restart_password" msgid="6984641181515902406">"Der skal indtastes en adgangskode efter genstart af enheden"</string>
+    <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"Der skal angives en pinkode efter genstart af enheden"</string>
+    <string name="kg_prompt_reason_restart_password" msgid="6984641181515902406">"Der skal angives en adgangskode efter genstart af enheden"</string>
     <string name="kg_prompt_reason_timeout_pattern" msgid="5304487696073914063">"Der kræves et mønster som ekstra beskyttelse"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="8851462864335757813">"Der kræves en pinkode som ekstra beskyttelse"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="6563904839641583441">"Der kræves en adgangskode som ekstra beskyttelse"</string>
     <string name="kg_prompt_reason_switch_profiles_pattern" msgid="3398054847288438444">"Du skal angive et mønster, når du skifter profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="7426368139226961699">"Der skal indtastes en pinkode, når du skifter profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="8383831046318421845">"Der skal indtastes en adgangskode, når du skifter profil"</string>
+    <string name="kg_prompt_reason_switch_profiles_pin" msgid="7426368139226961699">"Der skal angives en pinkode, når du skifter profil"</string>
+    <string name="kg_prompt_reason_switch_profiles_password" msgid="8383831046318421845">"Der skal angives en adgangskode, når du skifter profil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="3452168247888906179">"Enheden er blevet låst af administratoren"</string>
     <string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"Enheden blev låst manuelt"</string>
     <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="71299470072448533">
diff --git a/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png b/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png
new file mode 100644
index 0000000..311f30bc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/work_challenge_background.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/biometric_dialog_bg.xml b/packages/SystemUI/res/drawable/biometric_dialog_bg.xml
index d4dfdee..d041556 100644
--- a/packages/SystemUI/res/drawable/biometric_dialog_bg.xml
+++ b/packages/SystemUI/res/drawable/biometric_dialog_bg.xml
@@ -21,6 +21,6 @@
     <corners android:radius="1dp"
         android:topLeftRadius="@dimen/biometric_dialog_corner_size"
         android:topRightRadius="@dimen/biometric_dialog_corner_size"
-        android:bottomLeftRadius="0dp"
-        android:bottomRightRadius="0dp"/>
+        android:bottomLeftRadius="@dimen/biometric_dialog_corner_size"
+        android:bottomRightRadius="@dimen/biometric_dialog_corner_size"/>
 </shape>
diff --git a/packages/SystemUI/res/drawable/ic_home_button_outline.xml b/packages/SystemUI/res/drawable/ic_home_button_outline.xml
new file mode 100644
index 0000000..5bf345d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_home_button_outline.xml
@@ -0,0 +1,25 @@
+<!--
+  ~ Copyright (C) 2018 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="28dp"
+        android:height="10dp"
+        android:viewportWidth="28"
+        android:viewportHeight="10">
+    <path
+        android:pathData="M23,1H5C2.7909,1 1,2.7909 1,5C1,7.2091 2.7909,9 5,9H23C25.2091,9 27,7.2091 27,5C27,2.7909 25.2091,1 23,1ZM5,0C2.2386,0 0,2.2386 0,5C0,7.7614 2.2386,10 5,10H23C25.7614,10 28,7.7614 28,5C28,2.2386 25.7614,0 23,0H5Z"
+        android:fillColor="?attr/wallpaperTextColor"
+        android:fillType="evenOdd"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_notification_block.xml b/packages/SystemUI/res/drawable/ic_notification_block.xml
new file mode 100644
index 0000000..572e97b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_notification_block.xml
@@ -0,0 +1,25 @@
+<!--
+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 xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12.0,2.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0zM4.0,12.0c0.0,-4.42 3.58,-8.0 8.0,-8.0 1.85,0.0 3.5,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4.0,13.85 4.0,12.0zm8.0,8.0c-1.85,0.0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20.0,10.15 20.0,12.0c0.0,4.42 -3.58,8.0 -8.0,8.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_notifications_alert.xml b/packages/SystemUI/res/drawable/ic_notifications_alert.xml
new file mode 100644
index 0000000..eb7b8ee
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_notifications_alert.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2018 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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M7.58 4.08L6.15 2.65C3.75 4.48 2.17 7.3 2.03 10.5h2c.15-2.65 1.51-4.97 3.55-6.42zm12.39 6.42h2c-.15-3.2-1.73-6.02-4.12-7.85l-1.42 1.43c2.02 1.45 3.39 3.77 3.54 6.42zM18 11c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2v-5zm-6 11c.14 0 .27-.01.4-.04.65-.14 1.18-.58 1.44-1.18.1-.24.15-.5.15-.78h-4c.01 1.1.9 2 2.01 2z"
+        android:fillColor="#FF000000"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_notifications_silence.xml b/packages/SystemUI/res/drawable/ic_notifications_silence.xml
new file mode 100644
index 0000000..ff136eb
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_notifications_silence.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2018 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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M0 0h24v24H0z"
+    />
+    <path
+        android:pathData="M20 18.69L7.84 6.14 5.27 3.49 4 4.76l2.8 2.8v.01c-.52.99-.8 2.16-.8 3.42v5l-2 2v1h13.73l2 2L21 19.72l-1-1.03zM12 22c1.11 0 2-.89 2-2h-4c0 1.11.89 2 2 2zm6-7.32V11c0-3.08-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68c-.15.03-.29.08-.42.12-.1.03-.2.07-.3.11h-.01c-.01 0-.01 0-.02.01-.23.09-.46.2-.68.31 0 0-.01 0-.01.01L18 14.68z"
+        android:fillColor="#FF000000"
+    />
+</vector>
diff --git a/packages/SystemUI/res/drawable/privacy_chip_bg.xml b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
index 8247c27..36d0659 100644
--- a/packages/SystemUI/res/drawable/privacy_chip_bg.xml
+++ b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
@@ -16,7 +16,7 @@
 -->
 
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#bbbbbb" />
+    <solid android:color="#4a4a4a" />
     <padding android:padding="@dimen/ongoing_appops_chip_bg_padding" />
     <corners android:radius="@dimen/ongoing_appops_chip_bg_corner_radius" />
 </shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/stat_sys_camera.xml b/packages/SystemUI/res/drawable/stat_sys_camera.xml
new file mode 100644
index 0000000..eb3e963
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_camera.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2018, 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.
+*/
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+    android:insetLeft="3dp"
+    android:insetRight="3dp">
+    <vector
+            android:width="17dp"
+            android:height="17dp"
+            android:viewportWidth="24.0"
+            android:viewportHeight="24.0">
+        <path
+            android:fillColor="#FFF"
+            android:pathData="M20,5h-3.17L15,3H9L7.17,5H4C2.9,5 2,5.9 2,7v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V7C22,5.9 21.1,5 20,5zM20,19H4V7h16V19zM12,9c-2.21,0 -4,1.79 -4,4c0,2.21 1.79,4 4,4s4,-1.79 4,-4C16,10.79 14.21,9 12,9z"/>
+    </vector>
+</inset>
diff --git a/packages/SystemUI/res/drawable/stat_sys_mic_none.xml b/packages/SystemUI/res/drawable/stat_sys_mic_none.xml
new file mode 100644
index 0000000..d6bdf9f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_mic_none.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="18dp"
+    android:height="18dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFF"
+        android:pathData="M12,14c1.66,0 3,-1.34 3,-3V5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6C9,12.66 10.34,14 12,14zM11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v6c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V5z"/>
+    <path
+        android:fillColor="#FFF"
+        android:pathData="M17,11c0,2.76 -2.24,5 -5,5s-5,-2.24 -5,-5H5c0,3.53 2.61,6.43 6,6.92V21h2v-3.08c3.39,-0.49 6,-3.39 6,-6.92H17z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml
index ec25e31..5ca34b0 100644
--- a/packages/SystemUI/res/layout/biometric_dialog.xml
+++ b/packages/SystemUI/res/layout/biometric_dialog.xml
@@ -14,154 +14,169 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/layout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:gravity="bottom"
-    android:background="@color/biometric_dialog_dim_color"
-    android:orientation="vertical">
+    android:layout_height="match_parent">
 
-    <!-- This is not a Space since Spaces cannot be clicked -->
-    <View
-        android:id="@+id/space"
+    <ImageView
+        android:id="@+id/background"
         android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1" />
+        android:layout_height="match_parent"
+        android:scaleType="center" />
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content">
+        android:layout_height="match_parent"
+        android:gravity="bottom"
+        android:background="@color/biometric_dialog_dim_color"
+        android:orientation="vertical">
 
-        <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
-         on horizontal/portrait orientation -->
+        <!-- This is not a Space since Spaces cannot be clicked -->
         <View
-            android:id="@+id/left_space"
-            android:layout_weight="1"
-            android:layout_width="0dp"
-            android:layout_height="match_parent"/>
+            android:id="@+id/space"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="1" />
 
         <LinearLayout
-            android:id="@+id/dialog"
-            android:layout_width="0dp"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="vertical"
-            android:elevation="2dp"
-            android:background="@drawable/biometric_dialog_bg">
+            android:orientation="horizontal">
 
-            <TextView
-                android:id="@+id/title"
-                android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginEnd="24dp"
-                android:layout_marginStart="24dp"
-                android:layout_marginTop="24dp"
-                android:gravity="@integer/biometric_dialog_text_gravity"
-                android:textSize="20sp"
-                android:maxLines="1"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:marqueeRepeatLimit="marquee_forever"
-                android:textColor="?android:attr/textColorPrimary"/>
-
-            <TextView
-                android:id="@+id/subtitle"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="8dp"
-                android:layout_marginStart="24dp"
-                android:layout_marginEnd="24dp"
-                android:gravity="@integer/biometric_dialog_text_gravity"
-                android:textSize="16sp"
-                android:maxLines="1"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:marqueeRepeatLimit="marquee_forever"
-                android:textColor="?android:attr/textColorPrimary"/>
-
-            <TextView
-                android:id="@+id/description"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginEnd="24dp"
-                android:layout_marginStart="24dp"
-                android:gravity="@integer/biometric_dialog_text_gravity"
-                android:paddingTop="8dp"
-                android:textSize="16sp"
-                android:maxLines="4"
-                android:textColor="?android:attr/textColorPrimary"/>
-
-            <ImageView
-                android:id="@+id/biometric_icon"
-                android:layout_width="@dimen/biometric_dialog_biometric_icon_size"
-                android:layout_height="@dimen/biometric_dialog_biometric_icon_size"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginTop="48dp"
-                android:scaleType="fitXY" />
-
-            <TextView
-                android:id="@+id/error"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginEnd="24dp"
-                android:layout_marginStart="24dp"
-                android:paddingTop="16dp"
-                android:paddingBottom="24dp"
-                android:textSize="12sp"
-                android:gravity="center_horizontal"
-                android:accessibilityLiveRegion="polite"
-                android:contentDescription="@string/accessibility_biometric_dialog_help_area"
-                android:textColor="?android:attr/textColorSecondary"/>
+            <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
+             on horizontal/portrait orientation -->
+            <View
+                android:id="@+id/left_space"
+                android:layout_weight="1"
+                android:layout_width="0dp"
+                android:layout_height="match_parent"/>
 
             <LinearLayout
+                android:id="@+id/dialog"
                 android:layout_width="match_parent"
-                android:layout_height="72dip"
-                android:paddingTop="24dp"
-                android:layout_gravity="center_vertical"
-                style="?android:attr/buttonBarStyle"
-                android:orientation="horizontal"
-                android:measureWithLargestChild="true">
-                <Space android:id="@+id/leftSpacer"
-                    android:layout_width="12dp"
-                    android:layout_height="match_parent"
-                    android:visibility="visible" />
-                <!-- Negative Button -->
-                <Button android:id="@+id/button2"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
-                    android:gravity="center"
-                    android:maxLines="2" />
-                <Space android:id="@+id/middleSpacer"
-                    android:layout_width="0dp"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:visibility="visible" />
-                <!-- Positive Button -->
-                <Button android:id="@+id/button1"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    style="@*android:style/Widget.DeviceDefault.Button.Colored"
-                    android:gravity="center"
-                    android:maxLines="2"
-                    android:text="@string/biometric_dialog_confirm"
-                    android:visibility="gone"/>
-                <Space android:id="@+id/rightSpacer"
-                    android:layout_width="12dip"
-                    android:layout_height="match_parent"
-                    android:visibility="visible" />
-            </LinearLayout>
-        </LinearLayout>
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:background="@drawable/biometric_dialog_bg"
+                android:layout_marginBottom="@dimen/biometric_dialog_border_padding"
+                android:layout_marginLeft="@dimen/biometric_dialog_border_padding"
+                android:layout_marginRight="@dimen/biometric_dialog_border_padding">
 
-        <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
-         on horizontal/portrait orientation -->
-        <View
-            android:id="@+id/right_space"
-            android:layout_weight="1"
-            android:layout_width="0dp"
-            android:layout_height="match_parent" />
+                <TextView
+                    android:id="@+id/title"
+                    android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginEnd="24dp"
+                    android:layout_marginStart="24dp"
+                    android:layout_marginTop="24dp"
+                    android:gravity="@integer/biometric_dialog_text_gravity"
+                    android:textSize="20sp"
+                    android:maxLines="1"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:marqueeRepeatLimit="marquee_forever"
+                    android:textColor="?android:attr/textColorPrimary"/>
+
+                <TextView
+                    android:id="@+id/subtitle"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="8dp"
+                    android:layout_marginStart="24dp"
+                    android:layout_marginEnd="24dp"
+                    android:gravity="@integer/biometric_dialog_text_gravity"
+                    android:textSize="16sp"
+                    android:maxLines="1"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:marqueeRepeatLimit="marquee_forever"
+                    android:textColor="?android:attr/textColorPrimary"/>
+
+                <TextView
+                    android:id="@+id/description"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginEnd="24dp"
+                    android:layout_marginStart="24dp"
+                    android:gravity="@integer/biometric_dialog_text_gravity"
+                    android:paddingTop="8dp"
+                    android:textSize="16sp"
+                    android:maxLines="4"
+                    android:textColor="?android:attr/textColorPrimary"/>
+
+                <ImageView
+                    android:id="@+id/biometric_icon"
+                    android:layout_width="@dimen/biometric_dialog_biometric_icon_size"
+                    android:layout_height="@dimen/biometric_dialog_biometric_icon_size"
+                    android:layout_gravity="center_horizontal"
+                    android:layout_marginTop="48dp"
+                    android:scaleType="fitXY" />
+
+                <TextView
+                    android:id="@+id/error"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginEnd="24dp"
+                    android:layout_marginStart="24dp"
+                    android:paddingTop="16dp"
+                    android:paddingBottom="24dp"
+                    android:textSize="12sp"
+                    android:gravity="center_horizontal"
+                    android:accessibilityLiveRegion="polite"
+                    android:contentDescription="@string/accessibility_biometric_dialog_help_area"
+                    android:textColor="?android:attr/textColorSecondary"/>
+
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="72dip"
+                    android:paddingTop="24dp"
+                    android:layout_gravity="center_vertical"
+                    style="?android:attr/buttonBarStyle"
+                    android:orientation="horizontal"
+                    android:measureWithLargestChild="true">
+                    <Space android:id="@+id/leftSpacer"
+                        android:layout_width="12dp"
+                        android:layout_height="match_parent"
+                        android:visibility="visible" />
+                    <!-- Negative Button -->
+                    <Button android:id="@+id/button2"
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
+                        android:gravity="center"
+                        android:maxLines="2" />
+                    <Space android:id="@+id/middleSpacer"
+                        android:layout_width="0dp"
+                        android:layout_height="match_parent"
+                        android:layout_weight="1"
+                        android:visibility="visible" />
+                    <!-- Positive Button -->
+                    <Button android:id="@+id/button1"
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        style="@*android:style/Widget.DeviceDefault.Button.Colored"
+                        android:gravity="center"
+                        android:maxLines="2"
+                        android:text="@string/biometric_dialog_confirm"
+                        android:visibility="gone"/>
+                    <Space android:id="@+id/rightSpacer"
+                        android:layout_width="12dip"
+                        android:layout_height="match_parent"
+                        android:visibility="visible" />
+                </LinearLayout>
+            </LinearLayout>
+
+            <!-- This is not a Space since Spaces cannot be clicked. The width of this changes depending
+             on horizontal/portrait orientation -->
+            <View
+                android:id="@+id/right_space"
+                android:layout_weight="1"
+                android:layout_width="0dp"
+                android:layout_height="match_parent" />
+
+        </LinearLayout>
 
     </LinearLayout>
 
-</LinearLayout>
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout/navigation_bar_window.xml b/packages/SystemUI/res/layout/navigation_bar_window.xml
index 6fa46d4..f98cbd8 100644
--- a/packages/SystemUI/res/layout/navigation_bar_window.xml
+++ b/packages/SystemUI/res/layout/navigation_bar_window.xml
@@ -20,6 +20,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/navigation_bar_frame"
+    android:theme="@style/Theme.SystemUI"
     android:layout_height="match_parent"
     android:layout_width="match_parent">
 
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index f138685..c86ebe7 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -152,6 +152,13 @@
                 android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
                 style="@style/TextAppearance.NotificationInfo.Button" />
             <TextView
+                android:id="@+id/toggle_silent"
+                android:text="@string/inline_silent_button_silent"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
+                style="@style/TextAppearance.NotificationInfo.Button" />
+            <TextView
                 android:id="@+id/keep"
                 android:minWidth="48dp"
                 android:text="@string/inline_keep_button"
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index 5e952e3..cbdd51b 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -18,10 +18,14 @@
 <com.android.systemui.privacy.OngoingPrivacyChip
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/privacy_chip"
-    android:layout_width="wrap_content"
     android:layout_height="match_parent"
-    android:layout_margin="@dimen/ongoing_appops_chip_margin"
-    android:gravity="center_vertical|end"
+    android:layout_width="wrap_content"
+    android:layout_marginLeft="@dimen/ongoing_appops_chip_margin"
+    android:layout_marginRight="@dimen/ongoing_appops_chip_margin"
+    android:layout_marginTop="@dimen/ongoing_appops_top_chip_margin"
+    android:layout_marginBottom="@dimen/ongoing_appops_top_chip_margin"
+    android:gravity="center_vertical|center_horizontal"
+    android:layout_gravity="center_vertical|start"
     android:orientation="horizontal"
     android:paddingStart="@dimen/ongoing_appops_chip_side_padding"
     android:paddingEnd="@dimen/ongoing_appops_chip_side_padding"
@@ -32,13 +36,22 @@
             android:id="@+id/icons_container"
             android:layout_height="match_parent"
             android:layout_width="wrap_content"
-            android:gravity="center_vertical|start"
+            android:layout_gravity="center_vertical|start"
+            android:gravity="center_vertical"
             />
 
         <TextView
-            android:id="@+id/app_name"
+            android:id="@+id/text_container"
             android:layout_height="match_parent"
             android:layout_width="wrap_content"
-            android:gravity="center_vertical|end"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:lines="1"
+            android:layout_gravity="center_vertical|end"
+            android:gravity="center_vertical"
+            android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+            android:textColor="@color/status_bar_clock_color"
+            android:layout_marginStart="@dimen/ongoing_appops_chip_icon_margin"
+            android:layout_marginEnd="@dimen/ongoing_appops_chip_icon_margin"
         />
 </com.android.systemui.privacy.OngoingPrivacyChip>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml b/packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml
index b5e24a0..2f7d486 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml
@@ -29,22 +29,30 @@
         android:orientation="vertical"
         android:padding="@dimen/ongoing_appops_dialog_content_padding">
 
-        <LinearLayout
-            android:id="@+id/icons_container"
+        <TextView
+            android:id="@+id/title"
             android:layout_width="match_parent"
-            android:layout_height="@dimen/ongoing_appops_dialog_icon_height"
-            android:orientation="horizontal"
+            android:layout_height="wrap_content"
             android:gravity="center"
-            android:importantForAccessibility="no"
+            android:textDirection="locale"
+            android:textAppearance="@style/TextAppearance.AppOpsDialog.Title"
+            android:textColor="@*android:color/text_color_primary"
+            android:paddingStart="@dimen/ongoing_appops_dialog_title_padding"
+            android:paddingEnd="@dimen/ongoing_appops_dialog_title_padding"
+            android:paddingBottom="@dimen/ongoing_appops_dialog_sep"
         />
 
         <LinearLayout
-            android:id="@+id/text_container"
+            android:id="@+id/items_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
             android:gravity="start"
         />
+
+        <include android:id="@+id/overflow" layout="@layout/ongoing_privacy_dialog_item"
+                 android:visibility="gone" />
+
     </LinearLayout>
 
 </ScrollView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_dialog_item.xml b/packages/SystemUI/res/layout/ongoing_privacy_dialog_item.xml
new file mode 100644
index 0000000..f05f7ba
--- /dev/null
+++ b/packages/SystemUI/res/layout/ongoing_privacy_dialog_item.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 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="match_parent"
+    android:layout_height="wrap_content"
+    android:fillViewport="true"
+    android:orientation="horizontal"
+    android:layout_marginTop="@dimen/ongoing_appops_dialog_text_margin"
+    android:focusable="true" >
+
+    <ImageView
+        android:id="@+id/app_icon"
+        android:layout_height="@dimen/ongoing_appops_dialog_icon_height"
+        android:layout_width="@dimen/ongoing_appops_dialog_icon_height"
+    />
+
+    <TextView
+        android:id="@+id/app_name"
+        android:layout_height="@dimen/ongoing_appops_dialog_icon_height"
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:gravity="bottom|start"
+        android:textDirection="locale"
+        android:textAppearance="@style/TextAppearance.AppOpsDialog.Item"
+        android:textColor="@*android:color/text_color_primary"
+        android:paddingStart="@dimen/ongoing_appops_dialog_text_padding"
+        android:paddingEnd="@dimen/ongoing_appops_dialog_text_padding"
+
+    />
+
+    <LinearLayout
+        android:id="@+id/icons"
+        android:layout_height="@dimen/ongoing_appops_dialog_icon_height"
+        android:layout_width="wrap_content"
+        android:gravity="end"
+        android:visibility="gone"
+    />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index f554150..890bf5d 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -62,7 +62,7 @@
                 android:layout_weight="1"
                 android:layout_marginEnd="32dp"
                 android:ellipsize="marquee"
-                android:textAppearance="@style/TextAppearance.QS.TileLabel"
+                android:textAppearance="@style/TextAppearance.QS.CarrierInfo"
                 android:textColor="?android:attr/textColorPrimary"
                 android:textDirection="locale"
                 android:singleLine="true" />
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index 980442c..f34161e 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -79,7 +79,7 @@
         android:padding="0dp"
         android:visibility="gone"
         android:gravity="center"
-        android:textAppearance="@style/TextAppearance.QS.TileLabel"
+        android:textAppearance="@style/TextAppearance.QS.TileLabel.Secondary"
         android:textColor="?android:attr/textColorSecondary"/>
 
     <View
diff --git a/packages/SystemUI/res/layout/quick_qs_status_icons.xml b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
index 94189bb..2000104 100644
--- a/packages/SystemUI/res/layout/quick_qs_status_icons.xml
+++ b/packages/SystemUI/res/layout/quick_qs_status_icons.xml
@@ -42,6 +42,20 @@
         android:id="@+id/statusIcons"
         android:layout_width="0dp"
         android:layout_height="match_parent"
-        android:layout_weight="1" />
+        android:layout_weight="1"
+        android:paddingEnd="@dimen/signal_cluster_battery_padding" />
+
+    <com.android.systemui.BatteryMeterView
+        android:id="@+id/batteryRemainingIcon"
+        android:layout_height="match_parent"
+        android:layout_width="wrap_content"
+        android:paddingEnd="2dp" />
+
+    <TextView
+        android:id="@+id/batteryRemainingText"
+        android:textAppearance="@style/TextAppearance.QS.TileLabel"
+        android:layout_height="match_parent"
+        android:layout_width="wrap_content"
+        android:gravity="center_vertical" />
 
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index 007070e..22b8d2f 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -27,6 +27,13 @@
     android:paddingStart="@dimen/status_bar_padding_start"
     android:paddingEnd="@dimen/status_bar_padding_end" >
 
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:orientation="horizontal"
+        android:gravity="center_vertical|start" >
+
     <com.android.systemui.statusbar.policy.Clock
         android:id="@+id/clock"
         android:layout_width="wrap_content"
@@ -38,13 +45,21 @@
         android:singleLine="true"
         android:textAppearance="@style/TextAppearance.StatusBar.Clock"
         systemui:showDark="false" />
+    </LinearLayout>
 
     <android.widget.Space
         android:id="@+id/space"
         android:layout_width="0dp"
         android:layout_height="match_parent"
+        android:layout_gravity="center_vertical|center_horizontal"
+        android:visibility="gone" />
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
         android:layout_weight="1"
-        android:gravity="center_vertical|center_horizontal" />
+        android:orientation="horizontal"
+        android:gravity="center_vertical|end" >
 
     <include layout="@layout/ongoing_privacy_chip" />
 
@@ -52,5 +67,7 @@
         android:id="@+id/battery"
         android:layout_height="match_parent"
         android:layout_width="wrap_content"
-        android:gravity="center_vertical|end" />
+        android:gravity="center_vertical|end"
+        android:layout_gravity="center_vertical|end" />
+    </LinearLayout>
 </LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 1835a56..de1ef3d 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Probeer weer skermkiekie neem"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Kan weens beperkte bergingspasie nie skermkiekie stoor nie"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Die program of jou organisasie laat nie toe dat skermkiekies geneem word nie"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Skermopname"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Deurlopende kennisgewing vir \'n skermopnamesessie"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Begin opname"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Neem stemopname op"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Wys tikke"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Stop"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Laat wag"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Hervat"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Kanselleer"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Deel"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Vee uit"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Skermopname is gekanselleer"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Skermopname is gestoor, tik om te sien"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Skermopname is uitgevee"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Kon nie skermopname uitvee nie"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Kon nie toestemmings kry nie"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-lêeroordrag-opsies"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Heg as \'n mediaspeler (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Heg as \'n kamera (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Kennisgewings"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Jy sal nie meer hierdie kennisgewings sien nie"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Hierdie kennisgewings sal geminimeer word"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Jy maak hierdie kennisgewings gewoonlik toe. \nMoet ons aanhou om hulle te wys?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Hou aan om hierdie kennisgewings te wys?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Stop kennisgewings"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Hou aan wys"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimeer"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Hou aan om kennisgewings van hierdie program af te wys?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Hierdie kennisgewings kan nie afgeskakel word nie"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Hierdie program gebruik tans die kamera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Hierdie program gebruik tans die mikrofoon."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Hierdie program wys tans bo-oor ander programme op jou skerm."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Wys persentasie wanneer gelaai word (verstek)"</item>
     <item msgid="3327323682209964956">"Moenie hierdie ikoon wys nie"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Wys laeprioriteit-kennisgewingikone"</string>
     <string name="other" msgid="4060683095962566764">"Ander"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Skermverdeler"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Volskerm links"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Program is oopgemaak sonder dat dit geïnstalleer is."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Program is oopgemaak sonder dat dit geïnstalleer is. Tik om meer te wete te kom."</string>
     <string name="app_info" msgid="6856026610594615344">"Programinligting"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Gaan na web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Gaan na blaaier"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobiele data"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is af"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Instellings"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Het dit"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Stort SysUI-hoop"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> gebruik tans jou <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Programme gebruik tans jou <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Open app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Kanselleer"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Goed"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Stellings"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> gebruik die afgelope <xliff:g id="TIME">%3$d</xliff:g> min. jou <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> gebruik tans jou <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> gebruik tans jou <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"ligging"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofoon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index dea4256..04f5d4c 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"ቅጽበታዊ ገጽ ዕይታን እንደገና ማንሳት ይሞክሩ"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"ባለው ውሱን የማከማቻ ቦታ ምክንያት ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አይችልም"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ቅጽበታዊ ገጽ እይታዎችን ማንሳት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"የማያ ገጽ ቀረጻ"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"ለአንድ የማያ ገጽ ቀረጻ ክፍለ-ጊዜ በመካሄድ ያለ ማሳወቂያ"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"መቅረጽ ጀምር"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"ድምጽን ቅረጽ"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"መታ ማድረጎችን አሳይ"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"አቁም"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"ባለበት አቁም"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"ከቆመበት ቀጥል"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"ይቅር"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"አጋራ"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"ሰርዝ"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"የማያ ገጽ ቀረጻ ተሰርዟል"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"የማያ ገጽ ቀረጻ ተቀምጧል፣ ለመመልከት መታ ያድርጉ"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"የማያ ገጽ ቀረጻ ተሰርዟል"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"የማያ ገጽ ቀረጻን መሰረዝ ላይ ስህተት"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"ፈቃዶችን ማግኘት አልተቻለም"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"የUSB ፋይል ሰደዳ አማራጮች"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"እንደ ማህደረ አጫዋች (MTP) ሰካ"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"እንደ ካሜራ (PTP) ሰካ"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ማሳወቂያዎች"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"እነዚህን ማሳወቂያዎችን ከእንግዲህ አይመለከቷቸውም"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"እነዚህ ማሳወቂያዎች እንዲያንሱ ይደረጋሉ"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"አብዛኛውን ጊዜ እነዚህን ማሳወቂያዎች ያሰናብቷቸዋል። \nመታየታቸው ይቀጥል??"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"እነዚህን ማሳወቂያዎች ማሳየት ይቀጥሉ?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"ማሳወቂያዎችን አስቁም"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"ማሳየትን ቀጥል"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"አሳንስ"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"ከዚህ መተግበሪያ ማሳወቂያዎችን ማሳየት ይቀጥል?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"እነዚህ ማሳወቂያዎች ሊጠፉ አይችሉም"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"ይህ መተግበሪያ ካሜራውን እየተጠቀመ ነው።"</string>
     <string name="appops_microphone" msgid="741508267659494555">"ይህ መተግበሪያ ማይክሮፎኑን እየተጠቀመ ነው።"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"ይህ መተግበሪያ በማያ ገጽዎ ላይ ባሉ ሌሎች መተግበሪያዎች ላይ እያሳየ ነው።"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"የባትሪ ኃይል በሚሞላበት ጊዜ መቶኛ አሳይ (ነባሪ)"</item>
     <item msgid="3327323682209964956">"ይህን አዶ አታሳይ"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"አነስተኛ ቅድሚያ ያላቸው የማሳወቂያ አዶዎችን አሳይ"</string>
     <string name="other" msgid="4060683095962566764">"ሌላ"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"የተከፈለ የማያ ገጽ ከፋይ"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"የግራ ሙሉ ማያ ገጽ"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"መተግበሪያ ሳይጫን ተከፍቷል።"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"መተግበሪያ ሳይጫን ተከፍቷል። ተጨማሪ ለማወቅ መታ ያድርጉ።"</string>
     <string name="app_info" msgid="6856026610594615344">"የመተግበሪያ መረጃ"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ወደ ድር ሂድ"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ወደ አሳሽ ሂድ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g>— <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ጠፍቷል"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"ቅንብሮች"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"ገባኝ"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"SysUI Heap አራግፍ"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> የእርስዎን <xliff:g id="TYPES_LIST">%2$s</xliff:g> እየተጠቀመ ነው።"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"መተግበሪያዎች የእርስዎን <xliff:g id="TYPES_LIST">%s</xliff:g> እየተጠቀሙ ነው።"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"መተግበሪያን ክፈት"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"ይቅር"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"እሺ"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"ቅንብሮች"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> የእርስዎን <xliff:g id="TYPE">%2$s</xliff:g> ላለፉት <xliff:g id="TIME">%3$d</xliff:g> ደቂቃዎች እየተጠቀመ ነው"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> የእርስዎን <xliff:g id="TYPE">%2$s</xliff:g> እየተጠቀመ ነው"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> የእርስዎን <xliff:g id="TYPES_LIST">%2$s</xliff:g> እየተጠቀመ ነው"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"ካሜራ"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"አካባቢ"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"ማይክሮፎን"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index b3ac2cd..11144ee 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"جرّب أخذ لقطة الشاشة مرة أخرى"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"يتعذر حفظ لقطة الشاشة لأن مساحة التخزين المتاحة محدودة."</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"يحظر التطبيق أو تحظر مؤسستك التقاط لقطات شاشة"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"تسجيل الشاشة"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"إشعار مستمر لجلسة تسجيل شاشة"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"بدء التسجيل"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"تسجيل التعليق الصوتي"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"عرض النقرات"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"إيقاف"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"إيقاف مؤقت"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"استئناف"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"إلغاء"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"مشاركة"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"حذف"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"تمّ إلغاء تسجيل الشاشة."</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"تمّ حفظ تسجيل الشاشة، انقر لعرضه."</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"تمّ حذف تسجيل الشاشة."</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"حدث خطأ أثناء حذف تسجيل الشاشة."</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"تعذّر الحصول على أذونات."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏خيارات نقل الملفات عبر USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏تثبيت كمشغل وسائط (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"‏تثبيت ككاميرا (PTP)"</string>
@@ -304,7 +320,7 @@
     <string name="quick_settings_wifi_on_label" msgid="7607810331387031235">"‏تم تشغيل Wi-Fi"</string>
     <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"‏لا تتوفر أي شبكة Wi-Fi"</string>
     <string name="quick_settings_wifi_secondary_label_transient" msgid="7748206246119760554">"جارٍ التفعيل…"</string>
-    <string name="quick_settings_cast_title" msgid="7709016546426454729">"إرسال"</string>
+    <string name="quick_settings_cast_title" msgid="7709016546426454729">"الإرسال"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"جارٍ الإرسال"</string>
     <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"جهاز لا يحمل اسمًا"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"جاهز للإرسال"</string>
@@ -346,7 +362,7 @@
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"حتى شروق الشمس"</string>
     <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"تفعيل الإعداد في <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"حتى <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"‏الاتصال القريب المدى (NFC)"</string>
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"‏الاتصالات قصيرة المدى (NFC)"</string>
     <string name="quick_settings_nfc_off" msgid="6883274004315134333">"تم إيقاف الاتصال القريب المدى"</string>
     <string name="quick_settings_nfc_on" msgid="6680317193676884311">"تم تفعيل الاتصال القريب المدى"</string>
     <string name="recents_swipe_up_onboarding" msgid="3824607135920170001">"مرّر سريعًا لأعلى لتبديل التطبيقات"</string>
@@ -594,15 +610,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"الإشعارات"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"لن تتلقى هذه الإشعارات بعد الآن."</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"سيتم تصغير هذه الإشعارات."</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"يتم عرض هذه الإشعارات بدون تنبيه صوتي"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"يتم عرض هذه الإشعارات مع تنبيه صوتي"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"أنت تتجاهل عادةً هذه الإشعارات. \nهل تريد الاستمرار في عرضها؟"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"هل تريد الاستمرار في تلقي هذه الإشعارات؟"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"إيقاف الإشعارات"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"الاستمرار في تلقّي الإشعارات"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"تصغير"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"عرض بدون تنبيه صوتي"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"العرض والتنبيه"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"هل تريد الاستمرار في تلقي إشعارات من هذا التطبيق؟"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"يتعذَّر إيقاف هذه الإشعارات."</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"يستخدم هذا التطبيق الكاميرا."</string>
     <string name="appops_microphone" msgid="741508267659494555">"يستخدم هذا التطبيق الميكروفون."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"يتم عرض هذا التطبيق فوق التطبيقات الأخرى على شاشتك."</string>
@@ -745,8 +763,7 @@
     <item msgid="2139628951880142927">"عرض النسبة المئوية عند الشحن (تلقائي)"</item>
     <item msgid="3327323682209964956">"عدم عرض هذا الرمز"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"إظهار رموز الإشعارات ذات الأولوية المنخفضة"</string>
     <string name="other" msgid="4060683095962566764">"غير ذلك"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"أداة تقسيم الشاشة"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"عرض النافذة اليسرى بملء الشاشة"</string>
@@ -826,7 +843,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"تمّ فتح التطبيق بدون تثبيته."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"تمّ فتح التطبيق بدون تثبيته. انقر لمعرفة مزيد من المعلومات."</string>
     <string name="app_info" msgid="6856026610594615344">"معلومات عن التطبيق"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"الانتقال إلى الويب"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"الانتقال إلى المتصفح"</string>
     <string name="mobile_data" msgid="7094582042819250762">"بيانات الجوّال"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"‏تم إيقاف شبكة Wi-Fi"</string>
@@ -858,4 +875,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"الإعدادات"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"حسنًا"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"‏تفريغ ذاكرة SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"التطبيق <xliff:g id="APP">%1$s</xliff:g> يستخدم <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"تستخدم التطبيقات <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"فتح التطبيق"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"إلغاء"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"موافق"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"الإعدادات"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"التطبيق <xliff:g id="APP">%1$s</xliff:g> يستخدم <xliff:g id="TYPE">%2$s</xliff:g> منذ <xliff:g id="TIME">%3$d</xliff:g> من الدقائق مضت."</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"التطبيقات <xliff:g id="APPS">%1$s</xliff:g> تستخدم <xliff:g id="TYPE">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"التطبيق <xliff:g id="APP">%1$s</xliff:g> يستخدم <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"الكاميرا"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"الموقع"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"الميكروفون"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 2574838..c60d2d4 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"স্ক্ৰীণশ্বট আকৌ ল\'বলৈ চেষ্টা কৰক"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"সঞ্চয়াগাৰত সীমিত খালী ঠাই থকাৰ বাবে স্ক্ৰীণশ্বট ছেভ কৰিব পৰা নগ\'ল"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"এপটোৱে বা আপোনাৰ প্ৰতিষ্ঠানে স্ক্ৰীণশ্বট ল\'বলৈ অনুমতি নিদিয়ে"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"স্ক্রীণ ৰেকৰ্ডিং"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"স্ক্রীণ ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"ৰেকৰ্ডিং কৰা আৰম্ভ কৰক"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"পাৰ্শ্ব-ধ্বনি ৰেকৰ্ড কৰক"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"টিপা ঠাইসমূহ দেখুৱাওক"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"বন্ধ কৰক"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"প\'জ কৰক"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"ৰখোৱাৰ পৰা পুনৰ আৰম্ভ কৰক"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"বাতিল কৰক"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"শ্বেয়াৰ কৰক"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"মচক"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"স্ক্রীণ ৰেকৰ্ড কৰাটো বাতিল কৰা হ\'ল"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"স্ক্রীণ ৰেকৰ্ডিং ছেভ কৰা হ\'ল, চাবলৈ টিপক"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"স্ক্রীণ ৰেকৰ্ডিং মচা হ\'ল"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"স্ক্রীণ ৰেকৰ্ডিং মচি থাকোঁতে কিবা আসোঁৱাহ হ\'ল"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"অনুমতি পাব পৰা নগ\'ল"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"ইউএছবিৰে ফাইল স্থানান্তৰণৰ বিকল্পসমূহ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"মিডিয়া প্লেয়াৰ (এমটিপি) হিচাপে সংলগ্ন কৰক"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"কেমেৰা (পিটিপি) হিচাপে সংলগ্ন কৰক"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"জাননীসমূহ"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"আপোনাক এই জাননীসমূহ আৰু দেখুওৱা নহ\'ব"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"এই জাননীসমূহ মিনিমাইজ কৰি থোৱা হ\'ব"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"আপুনি সাধাৰণতে এই জাননীসমূহ অগ্ৰাহ্য কৰে। \nসেইবোৰ দেখুওৱাই থাকিব লাগিবনে?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"এই জাননীসমূহ দেখুওৱাই থাকিব লাগিবনে?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"জাননী বন্ধ কৰক"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"দেখুওৱাই থাকক"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"সৰু কৰক"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"এই এপটোৰ জাননী দেখুওৱাই থাকিব লাগিবনে?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"এই জাননীসমূহ বন্ধ কৰিব নোৱাৰি"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"এই এপে কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string>
     <string name="appops_microphone" msgid="741508267659494555">"এই এপে মাইক্ৰ\'ফ\'ন ব্য়ৱহাৰ কৰি আছে।"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"এই এপটো আপোনাৰ স্ক্ৰীণত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ আছে।"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"চ্চাৰ্জ কৰি থকাৰ সময়ত শতাংশ দেখুৱাওক (ডিফ\'ল্ট)"</item>
     <item msgid="3327323682209964956">"এই আইকনটো নেদেখুৱাব"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"কম গুৰুত্বপূৰ্ণ জাননীৰ আইকনসমূহ দেখুৱাওক"</string>
     <string name="other" msgid="4060683095962566764">"অন্যান্য"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"স্প্লিট স্ক্ৰীণৰ বিভাজক"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"বাওঁফালৰ স্ক্ৰীণখন সম্পূৰ্ণ স্ক্ৰীণ কৰক"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"ইনষ্ট\'ল নকৰাকৈয়েই এপটো খোলা হৈছে।"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"ইনষ্ট\'ল নকৰাকৈয়েই এপটো খোলা হৈছে। অধিক জানিবলৈ টিপক।"</string>
     <string name="app_info" msgid="6856026610594615344">"এপ্ সম্পৰ্কীয় তথ্য"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ৱেবলৈ যাওক"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ব্ৰাউজাৰলৈ যাওক"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ম\'বাইল ডেটা"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"ৱাই-ফাই অফ অৱস্থাত আছে"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"ছেটিংবোৰ"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"বুজি পালোঁ"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"SysUI হীপ ডাম্প কৰক"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ব্যৱহাৰ কৰি আছে।"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"এপ্লিকেশ্বনসমূহে আপোনাৰ <xliff:g id="TYPES_LIST">%s</xliff:g> ব্যৱহাৰ কৰি আছে।"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"এপ্ খোলক"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"বাতিল কৰক"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ঠিক আছে"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"ছেটিংসমূহ"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g>এ যোৱা <xliff:g id="TIME">%3$d</xliff:g> মিনিটৰ পৰা আপোনাৰ <xliff:g id="TYPE">%2$s</xliff:g> ব্যৱহাৰ কৰি আছে"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="TYPE">%2$s</xliff:g> ব্যৱহাৰ কৰি আছে"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ব্যৱহাৰ কৰি আছে"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"কেমেৰা"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"অৱস্থান"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"মাইক্ৰ\'ফ\'ন"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 58947da..b47d5ff 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Skrinşotu yenidən çəkin"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Yaddaş ehtiyatının az olması səbəbindən skrinşotu yadda saxlamaq olmur"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Skrinşot çəkməyə tətbiq və ya təşkilat tərəfindən icazə verilmir"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Ekranın Video Çəkimi"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Ekranın video çəkimi ərzində silinməyən bildiriş"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Ekranın Video Çəkimini Başladın"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Ekranın səsli video çəkimi"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Klikləmələri göstərin"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Dayandırın"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Dayandırın"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Davam edin"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Ləğv edin"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Paylaşın"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Silin"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Ekranın video çəkimi ləğv edildi"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Ekranın video çəkimi yadda saxlanıldı. Baxmaq üçün klikləyin"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Ekranın video çəkimi silindi"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Ekranın video çəkiminin silinməsi zamanı xəta baş verdi"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"İcazələr əldə edilmədi"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fayl transferi seçimləri"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Media pleyer (MTP) kimi montaj edin"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Kamera kimi birləşdir (PTP)"</string>
@@ -582,14 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Bildirişlər"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Artıq bu bildirişləri görməyəcəkəsiniz"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Bu bildirişlər kiçildiləcək"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"Bu bildirişlər səssiz görünəcək"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Bu bildirişlər Sizi xəbərdar edəcək"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Adətən bu bildirişləri rədd edirsiniz. \nBildirişlər göstərilsin?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Bu bildirişlər göstərilməyə davam edilsin?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Bildirişləri dayandırın"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Göstərməyə davam edin"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Kiçildin"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Səssiz göstərin"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Göstərin və xəbərdar edin"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Bu tətbiqin bildirişləri göstərilməyə davam edilsin?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Bu bildirişlər deaktiv edilə bilməz"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"<xliff:g id="APP_NAME">%1$s</xliff:g> vasitəsilə"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Bu tətbiq kameradan istifadə edir."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Bu tətbiq mikrofondan istifadə edir."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Bu tətbiqdə ekranda digər tətbiqlərin üzərində göstərilir."</string>
@@ -804,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Quraşdırılmadan açılan tətbiq."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Quraşdırılmadan açılan tətbiq. Ətraflı məlumat üçün klikləyin."</string>
     <string name="app_info" msgid="6856026610594615344">"Tətbiq məlumatı"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Vebə keçin"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Brauzerə daxil edin"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobil data"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi deaktivdir"</string>
@@ -836,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Ayarlar"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Anladım"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="TYPES_LIST">%2$s</xliff:g> tətbiqlərindən istifadə edir."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Tətbiqlər <xliff:g id="TYPES_LIST">%s</xliff:g> istifadə edir."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Tətbiqi açın"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Ləğv edin"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Oldu"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Ayarlar"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> son <xliff:g id="TIME">%3$d</xliff:g> dəqiqədir ki, <xliff:g id="TYPE">%2$s</xliff:g> tətbiqindən istifadə edir"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> <xliff:g id="TYPE">%2$s</xliff:g> tətbiqindən istifadə edir"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="TYPES_LIST">%2$s</xliff:g> tətbiqlərindən istifadə edir"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"məkan"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</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 b2bcda8..8538565 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Probajte da ponovo napravite snimak ekrana"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Čuvanje snimka ekrana nije uspelo zbog ograničenog memorijskog prostora"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Snimanje ekrana"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Obaveštenje o sesiji snimanja ekrana je aktivno"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Započni snimanje"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Snimi prenos glasa"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Prikazuj dodire"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Zaustavi"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pauziraj"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Nastavi"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Otkaži"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Deli"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Izbriši"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Snimanje ekrana je otkazano"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Snimak ekrana je sačuvan, dodirnite da biste pregledali"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Snimak ekrana je izbrisan"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Došlo je do problema pri brisanju snimka ekrana"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Preuzimanje dozvola nije uspelo"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prenosa datoteka"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Priključi kao medija plejer (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Priključi kao kameru (PTP)"</string>
@@ -585,15 +601,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Obaveštenja"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Više nećete videti ova obaveštenja"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Ova obaveštenja će se umanjiti"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Obično odbacujete ova obaveštenja. \nŽelite li da se i dalje prikazuju?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Želite li da se ova obaveštenja i dalje prikazuju?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Prestani da prikazuješ obaveštenja"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Nastavi da prikazuješ"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Umanji"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Želite li da se obaveštenja iz ove aplikacije i dalje prikazuju?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ne možete da isključite ova obaveštenja"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Ova aplikacija koristi kameru."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Ova aplikacija koristi mikrofon."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Ova aplikacija se prikazuje preko drugih aplikacija na ekranu."</string>
@@ -730,8 +752,7 @@
     <item msgid="2139628951880142927">"Prikaži procenat tokom punjenja (podrazumevano)"</item>
     <item msgid="3327323682209964956">"Ne prikazuj ovu ikonu"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Prikaži ikone obaveštenja niskog prioriteta"</string>
     <string name="other" msgid="4060683095962566764">"Drugo"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Razdelnik podeljenog ekrana"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Režim celog ekrana za levi ekran"</string>
@@ -811,7 +832,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Aplikacija se otvorila bez instaliranja."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Aplikacija se otvorila bez instaliranja. Dodirnite da biste saznali više."</string>
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Idi na veb"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Idi na pregledač"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilni podaci"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je isključen"</string>
@@ -843,4 +864,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Podešavanja"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Važi"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Izdvoji SysUI mem."</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> koristi <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplikacije koriste <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Otvori"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Otkaži"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Potvrdi"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Podešavanja"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> tokom nekoliko poslednjih minuta (<xliff:g id="TIME">%3$d</xliff:g>) koristi <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> koriste <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> koristi <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kameru"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"lokaciju"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index ac430ba..e83b9be 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Паспрабуйце зрабіць здымак экрана яшчэ раз"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Немагчыма захаваць здымак экрана, бо мала месца ў сховішчы"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Рабіць здымкі экрана не дазваляе праграма ці ваша арганізацыя"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Запіс экрана"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Бягучае апавяшчэнне для сеанса запісу экрана"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Пачаць запіс"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Закадравае агучванне запісу"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Паказваць дотыкі"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Спыніць"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Прыпыніць"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Узнавіць"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Скасаваць"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Абагуліць"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Выдаліць"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Запіс экрана скасаваны"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Запіс экрана захаваны. Націсніце, каб прагледзець"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Запіс экрана выдалены"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Памылка выдалення запісу экрана"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Не ўдалося атрымаць дазволы"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Парам. перадачы файлаў па USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Падлучыць як медыяпрайгравальнік (ССП)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Падлучыць як камеру (PTP)"</string>
@@ -590,15 +606,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Апавяшчэнні"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Вы больш не будзеце бачыць гэтыя апавяшчэнні"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Апавяшчэнні будуць згорнуты"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Звычайна вы адхіляеце гэтыя апавяшчэнні. \nПаказваць іх?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Працягваць паказваць гэтыя апавяшчэнні?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Спыніць апавяшчэнні"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Працягваць паказваць"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Згарнуць"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Працягваць паказваць апавяшчэнні гэтай праграмы?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Немагчыма адключыць гэтыя апавяшчэнні"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Гэта праграма выкарыстоўвае камеру."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Гэта праграма выкарыстоўвае мікрафон."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Гэта праграма паказваецца на экране паверх іншых праграм."</string>
@@ -737,8 +759,7 @@
     <item msgid="2139628951880142927">"Паказваць працэнты падчас зарадкі (стандартна)"</item>
     <item msgid="3327323682209964956">"Не паказваць гэты значок"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Паказваць значкі апавяшчэнняў з нізкім прыярытэтам"</string>
     <string name="other" msgid="4060683095962566764">"Іншае"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Раздзяляльнік падзеленага экрана"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Левы экран – поўнаэкранны рэжым"</string>
@@ -818,7 +839,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Праграма адкрыта без усталёўкі."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Праграма адкрыта без усталёўкі. Націсніце, каб даведацца больш."</string>
     <string name="app_info" msgid="6856026610594615344">"Інфармацыя пра праграму"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Перайсці ў інтэрнэт"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Перайсці ў браўзер"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Маб. перадача даных"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi выключаны"</string>
@@ -850,4 +871,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Налады"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Зразумела"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Дамп кучы SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"Праграма \"<xliff:g id="APP">%1$s</xliff:g>\" выкарыстоўвае: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Праграмы выкарыстоўваюць: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Адкрыць"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Скасаваць"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ОК"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Налады"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"Праграма \"<xliff:g id="APP">%1$s</xliff:g>\" на працягу апошніх <xliff:g id="TIME">%3$d</xliff:g> хв. выкарыстоўвае: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Праграма \"<xliff:g id="APPS">%1$s</xliff:g>\" выкарыстоўвае: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"Праграма \"<xliff:g id="APP">%1$s</xliff:g>\" выкарыстоўвае: <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"камера"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"геалакацыя"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"мікрафон"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index c6bc414..bdc561a 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Опитайте да направите екранна снимка отново"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Екранната снимка не може да се запази поради ограничено място в хранилището"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Правенето на екранни снимки не е разрешено от приложението или организацията ви"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Записване на екрана"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Текущо известие за сесия за записване на екрана"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Стартиране на записа"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Записване на озвучаване"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Показване на докосванията"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Спиране"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Поставяне на пауза"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Възобновяване"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Отказ"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Споделяне"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Изтриване"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Записването на екрана е анулирано"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Записът на екрана е запазен. Докоснете, за да го видите"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Записът на екрана е изтрит"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"При изтриването на записа на екрана възникна грешка"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Извличането на разрешенията не бе успешно."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Опции за пренос на файлове чрез USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Свързване като медиен плейър (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Свързване като камера (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Известия"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Вече няма да виждате тези известия"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Тези известия ще бъдат намалени"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Обикновено отхвърляте тези известия. \nИскате ли да продължат да се показват?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Тези известия да продължат ли да се показват?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Спиране на известията"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Да продължат да се показват"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Намаляване"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Да продължат ли да се показват известията от това приложение?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Тези известия не могат да бъдат изключени"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Това приложение използва камерата."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Това приложение използва микрофона."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Това приложение се показва върху други приложения на екрана."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Процентът да се показва при зареждане (по подразбиране)"</item>
     <item msgid="3327323682209964956">"Тази икона да не се показва"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Показване на иконите за известията с нисък приоритет"</string>
     <string name="other" msgid="4060683095962566764">"Друго"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Разделител в режима за разделен екран"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Ляв екран: Показване на цял екран"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Приложението се отвори, без да бъде инсталирано."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Приложението се отвори, без да бъде инсталирано. Докоснете, за да научите повече."</string>
     <string name="app_info" msgid="6856026610594615344">"Информация за приложението"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Към мрежата"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Към браузъра"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобилни данни"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Функцията за Wi‑Fi е изключена"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Настройки"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Разбрах"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> използва <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Някои приложения използват <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Отваряне"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Отказ"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Настройки"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> използва <xliff:g id="TYPE">%2$s</xliff:g> през последните <xliff:g id="TIME">%3$d</xliff:g> минути"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> използват <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> използва <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"камерата"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"местополож."</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"микрофона"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 412f90cf..b22714d 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"আবার স্ক্রিনশট নেওয়ার চেষ্টা করুন"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"বেশি জায়গা নেই তাই স্ক্রিনশটটি সেভ করা যাবে না৷"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"এই অ্যাপ বা আপনার প্রতিষ্ঠান স্ক্রিনশট নেওয়ার অনুমতি দেয়নি"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"স্ক্রিন রেকর্ডিং"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"স্ক্রিন রেকর্ডিং সেশন চলার বিজ্ঞপ্তি"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"রেকর্ডিং শুরু করুন"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"ভয়েসওভার রেকর্ড করুন"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"ট্যাপগুলি দেখুন"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"বন্ধ করুন"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"পজ করুন"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"আবার চালু করুন"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"বাতিল করুন"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"শেয়ার করুন"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"মুছুন"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"স্ক্রিন রেকর্ডিং বাতিল করা হয়েছে"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"স্ক্রিন রেকর্ডিং সেভ করা হয়েছে, দেখতে ট্যাপ করুন"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"স্ক্রিন রেকর্ডিং মুছে ফেলা হয়েছে"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"স্ক্রিন রেকডিং মুছে ফেলার সময় সমস্যা হয়েছে"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"অনুমতি পাওয়া যায়নি"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ফাইল স্থানান্তরের বিকল্পগুলি"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"একটি মিডিয়া প্লেয়ার হিসেবে মাউন্ট করুন (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"একটি ক্যামেরা হিসেবে মাউন্ট করুন (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"বিজ্ঞপ্তি"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"এই বিজ্ঞপ্তিগুলি আপনাকে আর দেখানো হবে না"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"এই বিজ্ঞপ্তিগুলি ছোট করে দেওয়া হবে"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"এই বিজ্ঞপ্তিগুলিকে আপনি সাধারণত বাতিল করেন। \nসেগুলি দেখতে চান?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"এই বিজ্ঞপ্তিগুলি পরেও দেখে যেতে চান?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"বিজ্ঞপ্তি বন্ধ করুন"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"দেখতে থাকুন"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"ছোট করে দিন"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"এই অ্যাপের বিজ্ঞপ্তি পরেও দেখে যেতে চান?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"এই বিজ্ঞপ্তিগুলি বন্ধ করা যাবে না"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"এই অ্যাপটি ক্যামেরা ব্যবহার করছে।"</string>
     <string name="appops_microphone" msgid="741508267659494555">"এই অ্যাপটি মাইক্রোফোন ব্যবহার করছে।"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"এই অ্যাপটি স্ক্রিনে অন্যান্য অ্যাপের উপরে দেখানো হচ্ছে।"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"চার্জ করার সময় শতাংশ দেখান (ডিফল্ট)"</item>
     <item msgid="3327323682209964956">"এই আইকনটি দেখাবেন না"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"কম-গুরুত্বপূর্ণ বিজ্ঞপ্তির আইকন দেখুন"</string>
     <string name="other" msgid="4060683095962566764">"অন্যান্য"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"বিভক্ত-স্ক্রিন বিভাজক"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"বাঁ দিকের অংশ নিয়ে পূর্ণ স্ক্রিন"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"অ্যাপটি ইনস্টল না করে চালু করা হয়েছে।"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"অ্যাপটি ইনস্টল না করে চালু করা হয়েছে। আরও জানতে ট্যাপ করুন।"</string>
     <string name="app_info" msgid="6856026610594615344">"অ্যাপের তথ্য"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ওয়েবে যান"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ব্রাউজারে যান"</string>
     <string name="mobile_data" msgid="7094582042819250762">"মোবাইল ডেটা"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"ওয়াই ফাই বন্ধ আছে"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"সেটিংস"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"বুঝেছি"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> আপনার <xliff:g id="TYPES_LIST">%2$s</xliff:g> ব্যবহার করছে।"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"অ্যাপ্লিকেশনগুলি আপনার <xliff:g id="TYPES_LIST">%s</xliff:g> ব্যবহার করছে।"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"অ্যাপ খুলুন"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"বাতিল করুন"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ঠিক আছে"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"সেটিংস"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> আপনার <xliff:g id="TYPE">%2$s</xliff:g> গত <xliff:g id="TIME">%3$d</xliff:g> মিনিট ধরে ব্যবহার করছে"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> আপনার <xliff:g id="TYPE">%2$s</xliff:g> ব্যবহার করছে"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> আপনার <xliff:g id="TYPES_LIST">%2$s</xliff:g> ব্যবহার করছে"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"ক্যামেরা"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"লোকেশন"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"মাইক্রোফোন"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 42616a6..bd48839 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Pokušajte ponovo snimiti ekran"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Snimak ekrana se ne može sačuvati zbog manjka prostora za pohranu"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Ova aplikacija ili vaša organizacija ne dozvoljavaju snimanje ekrana"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Snimanje ekrana"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Obavještenje za sesiju snimanja ekrana je u toku"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Započni snimanje"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Govor snimka"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Prikaži dodirivanja"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Zaustavi"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pauza"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Nastavi"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Otkaži"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Dijeli"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Izbriši"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Snimanje ekrana je otkazano"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Snimak ekrana je sačuvan. Dodirnite za prikaz."</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Snimak ekrana je izbrisan"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Greška prilikom brisanja snimka ekrana"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Dobijanje odobrenja nije uspjelo"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa fajlova"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Reproduciranje medijskih sadržaja (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Priključiti kao kameru (PTP)"</string>
@@ -587,14 +603,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Obavještenja"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Nećete više vidjeti ova obavještenja"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Ova obavještenja će se minimizirati"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"Ove obavijesti prikazivat će se tiho"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Ove obavijesti imat će zvučni signal"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Obično odbacujete ova obavještenja. \nNastaviti ih prikazivati?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Nastaviti prikazivanje ovih obavještenja?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Zaustavi obavještenja"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Nastavi prikazivanje"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimiziraj"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Prikaži tiho"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Prikaži uz zvučni signal"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Nastaviti prikazivanje obavještenja iz ove aplikacije?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ova obavještenja nije moguće isključiti"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"putem aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Ova aplikacija koristi kameru."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Ova aplikacija koristi mikrofon."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Ova aplikacija prekriva druge aplikacije na ekranu."</string>
@@ -731,7 +750,7 @@
     <item msgid="2139628951880142927">"Pokaži postotak u toku punjenja (zadano)"</item>
     <item msgid="3327323682209964956">"Ne prikazuj ovu ikonu"</item>
   </string-array>
-    <string name="tuner_low_priority" msgid="1325884786608312358">"Prikaži ikone obavijesti niskog prioriteta"</string>
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Prikaži ikone obavještenja niskog prioriteta"</string>
     <string name="other" msgid="4060683095962566764">"Ostalo"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Razdjelnik ekrana"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Lijevo cijeli ekran"</string>
@@ -811,7 +830,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Aplikacija je otvorena bez prethodne instalacije."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Aplikacija je otvorena bez prethodne instalacije. Dodirnite da saznate više."</string>
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Idite na internet"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Idi na preglednik"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Prijenos podataka"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"WiFi veza je isključena"</string>
@@ -843,4 +862,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Postavke"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Razumijem"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Izdvoji SysUI mem."</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> koristi <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplikacije koriste <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Otvori"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Otkaži"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Uredu"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Postavke"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> koristi <xliff:g id="TYPE">%2$s</xliff:g> u vremenskom periodu od <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Aplikacije <xliff:g id="APPS">%1$s</xliff:g> koriste <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> koristi <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kameru"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"lokaciju"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index d7300f6..0e91142 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Prova de tornar a fer una captura de pantalla"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"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="173674476457581486">"L\'aplicació o la teva organització no permeten fer captures de pantalla"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Gravació de la pantalla"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Notificació en curs d\'una sessió de gravació de la pantalla"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Inicia la gravació"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Grava la veu en off"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Mostra els tocs"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Atura"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Posa en pausa"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Reprèn"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Cancel·la"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Comparteix"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Suprimeix"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"S\'ha cancel·lat la gravació de la pantalla"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"S\'ha desat la gravació de la pantalla; toca per mostrar"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"S\'ha suprimit la gravació de la pantalla"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"S\'ha produït un error en suprimir la gravació de la pantalla"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"No s\'han pogut obtenir els permisos"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcions transf. fitxers USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Munta com a reproductor multimèdia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Munta com a càmera (PTP)"</string>
@@ -582,14 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificacions"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Ja no veuràs aquestes notificacions"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Aquestes notificacions es minimitzaran"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Normalment ignores aquestes notificacions. \nVols que es continuïn mostrant?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Vols continuar rebent aquestes notificacions?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Deixa d\'enviar notificacions"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Continua rebent"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimitza"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Vols continuar rebent notificacions d\'aquesta aplicació?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Aquestes notificacions no es poden desactivar"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"mitjançant <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Aquesta aplicació utilitza la càmera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Aquesta aplicació utilitza el micròfon."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Aquesta aplicació es mostra sobre altres aplicacions a la pantalla."</string>
@@ -804,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"L\'aplicació s\'ha obert sense instal·lar-se."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"L\'aplicació s\'ha obert sense instal·lar-se. Toca per obtenir més informació."</string>
     <string name="app_info" msgid="6856026610594615344">"Informació de l\'aplicació"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Ves al web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Ves al navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Dades mòbils"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"La Wi-Fi està desactivada"</string>
@@ -836,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Configuració"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"D\'acord"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Aboca espai de SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> està fent servir el següent: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Algunes aplicacions estan fent servir el següent: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Obre l\'app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Cancel·la"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"D\'acord"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Configuració"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"Durant els <xliff:g id="TIME">%3$d</xliff:g> últims minuts, <xliff:g id="APP">%1$s</xliff:g> ha estat fent servir el següent: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> estan fent servir el següent: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> està fent servir el següent: <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"càmera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"ubicació"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"micròfon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 0efbe7d..b246579 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Zkuste snímek pořídit znovu"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Snímek obrazovky kvůli nedostatku místa v úložišti nelze uložit"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikace nebo organizace zakazuje pořizování snímků obrazovky"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Nahrávání obrazovky"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Trvalé oznámení o relaci nahrávání"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Spustit nahrávání"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Nahrávat komentář"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Zobrazovat klepnutí"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Zastavit"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pozastavit"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Obnovit"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Zrušit"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Sdílet"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Smazat"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Nahrávání obrazovky bylo zrušeno"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Záznam obrazovky byl uložen, zobrazíte jej klepnutím"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Záznam obrazovky byl smazán"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Při mazání záznamu obrazovky došlo k chybě"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Nepodařilo se načíst oprávnění"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti přenosu souborů pomocí rozhraní USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Připojit jako přehrávač médií (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Připojit jako fotoaparát (PTP)"</string>
@@ -588,15 +604,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Oznámení"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Tato oznámení již nebudete dostávat"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Tato oznámení budou minimalizována"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Tato oznámení obvykle odmítáte. \nChcete je nadále zobrazovat?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Mají se tato oznámení nadále zobrazovat?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Přestat zobrazovat oznámení"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Nadále zobrazovat"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimalizovat"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Mají se oznámení z této aplikace nadále zobrazovat?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Tato oznámení nelze deaktivovat"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Tato aplikace využívá fotoaparát."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Tato aplikace využívá mikrofon."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Tato aplikace se zobrazuje přes ostatní aplikace na obrazovce."</string>
@@ -735,8 +757,7 @@
     <item msgid="2139628951880142927">"Zobrazovat procento při nabíjení (výchozí nastavení)"</item>
     <item msgid="3327323682209964956">"Tuto ikonu nezobrazovat"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Zobrazit ikony oznámení s nízkou prioritou"</string>
     <string name="other" msgid="4060683095962566764">"Jiné"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Čára rozdělující obrazovku"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Levá část na celou obrazovku"</string>
@@ -816,7 +837,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Aplikace byla otevřena bez instalace."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Aplikace byla otevřena bez instalace. Klepnutím zobrazíte další informace."</string>
     <string name="app_info" msgid="6856026610594615344">"O aplikaci"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Přejít na web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Přejít do prohlížeče"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilní data"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je vypnuta"</string>
@@ -848,4 +869,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Nastavení"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Rozumím"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Výpis haldy SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"Aplikace <xliff:g id="APP">%1$s</xliff:g> využívá tato oprávnění: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplikace využívají tato oprávnění: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Otevřít aplikaci"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Zrušit"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Nastavení"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"Aplikace <xliff:g id="APP">%1$s</xliff:g> v posledních <xliff:g id="TIME">%3$d</xliff:g> min využívá toto oprávnění: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Aplikace <xliff:g id="APPS">%1$s</xliff:g> využívají toto oprávnění: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"Aplikace <xliff:g id="APP">%1$s</xliff:g> využívá tato oprávnění: <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"fotoaparát"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"poloha"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index d470582..c30441b 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Prøv at tage et screenshot igen"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Screenshottet kan ikke gemmes, fordi der er begrænset lagerplads"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Appen eller din organisation tillader ikke, at du tager screenshots"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Skærmoptagelse"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Konstant underretning om skærmoptagelse"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Start optagelse"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Optag voiceover"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Vis tryk"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Stop"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Sæt på pause"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Genoptag"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Annuller"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Del"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Slet"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Skærmoptagelsen er annulleret"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Skærmoptagelsen er gemt. Tryk for at se den."</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Skærmoptagelsen er slettet"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Der opstod en fejl ved sletning af skærmoptagelsen"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Det lykkedes ikke et hente tilladelserne"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Muligheder for USB-filoverførsel"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Isæt som en medieafspiller (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Isæt som et kamera (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Underretninger"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Du får ikke længere vist disse underretninger"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Disse underretninger minimeres"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Du afviser som regel disse underretninger. \nVil du blive ved med at se dem?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Vil du fortsætte med at se disse underretninger?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Stop underretninger"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Fortsæt med at vise underretninger"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimer"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Vil du fortsætte med at se underretninger fra denne app?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Disse underretninger kan ikke deaktiveres"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Denne app anvender kameraet."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Denne app anvender mikrofonen."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Denne app vises over andre apps på din skærm."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Vis procent ved opladning (standard)"</item>
     <item msgid="3327323682209964956">"Vis ikke dette ikon"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Vis ikoner for underretninger med lav prioritet"</string>
     <string name="other" msgid="4060683095962566764">"Andet"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Adskiller til opdelt skærm"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Vis venstre del i fuld skærm"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"En app blev åbnet uden at blive installeret."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"En app blev åbnet uden at blive installeret. Tryk for at få flere oplysninger."</string>
     <string name="app_info" msgid="6856026610594615344">"Appinfo"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Gå til website"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Gå til en browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobildata"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi er slået fra"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Indstillinger"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Gem SysUI-heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> anvender enhedens <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Apps anvender enhedens <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Åbn app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Luk"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Indstillinger"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> har anvendt enhedens <xliff:g id="TYPE">%2$s</xliff:g> i de sidste <xliff:g id="TIME">%3$d</xliff:g> min."</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> anvender enhedens <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> anvender enhedens <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"placering"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 7fcb02c..69af8f7 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Versuche noch einmal, den Screenshot zu erstellen"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Speichern des Screenshots aufgrund von zu wenig Speicher nicht möglich"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Die App oder deine Organisation lässt das Erstellen von Screenshots nicht zu"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Bildschirmaufzeichnung"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Fortlaufende Benachrichtigung für eine Bildschirmaufzeichnung"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Aufzeichnung starten"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Voice-over aufnehmen"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Fingertipps anzeigen"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Anhalten"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pausieren"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Fortsetzen"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Abbrechen"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Teilen"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Löschen"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Bildschirmaufzeichnung abgebrochen"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Bildschirmaufzeichnung gespeichert, zum Ansehen tippen"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Bildschirmaufzeichnung gelöscht"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Fehler beim Löschen der Bildschirmaufzeichnung"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Berechtigungen nicht erhalten"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-Dateiübertragungsoptionen"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Als Medienplayer (MTP) bereitstellen"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Als Kamera (PTP) bereitstellen"</string>
@@ -586,14 +602,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Benachrichtigungen"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Du erhältst diese Benachrichtigungen nicht mehr"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Diese Benachrichtigungen werden minimiert"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Normalerweise schließt du diese Benachrichtigungen. \nSollen sie trotzdem weiter angezeigt werden?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Diese Benachrichtigungen weiterhin anzeigen?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Benachrichtigungen nicht mehr anzeigen"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Weiterhin anzeigen"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimieren"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Benachrichtigungen dieser App weiterhin anzeigen?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Diese Benachrichtigungen können nicht deaktiviert werden"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"über <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Diese App verwendet die Kamera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Diese App verwendet das Mikrofon."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Diese App wird über anderen Apps auf dem Bildschirm angezeigt."</string>
@@ -808,7 +831,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"App wurde geöffnet, ohne vorher installiert zu werden."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"App wurde geöffnet, ohne vorher installiert zu werden. Tippe, um weitere Informationen zu erhalten."</string>
     <string name="app_info" msgid="6856026610594615344">"App-Informationen"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Web aufrufen"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Browser öffnen"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobile Daten"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"WLAN ist deaktiviert"</string>
@@ -840,4 +863,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Einstellungen"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> verwendet gerade Folgendes: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Apps verwenden gerade Folgendes: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"App öffnen"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Abbrechen"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Einstellungen"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> verwendet seit <xliff:g id="TIME">%3$d</xliff:g> Minuten Folgendes: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> verwenden gerade Folgendes: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> verwendet gerade Folgendes: <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"Kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"Standort"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"Mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 12f0d532..67355ef 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Δοκιμάστε να κάνετε ξανά λήψη του στιγμιότυπου οθόνης"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Αδύνατη η αποθήκευση του στιγμιότυπου οθόνης λόγω περιορισμένου αποθηκευτικού χώρου"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Η λήψη στιγμιότυπων οθόνης δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Εγγραφή οθόνης"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Ειδοποίηση σε εξέλιξη για μια περίοδο λειτουργίας εγγραφής οθόνης"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Έναρξη εγγραφής"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Εγγραφή σπικάζ"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Εμφάνιση πατημάτων"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Διακοπή"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Παύση"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Συνέχιση"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Ακύρωση"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Κοινοποίηση"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Διαγραφή"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Η εγγραφή οθόνης ακυρώθηκε"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Η εγγραφή οθόνης αποθηκεύτηκε. Πατήστε για προβολή."</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Η εγγραφή οθόνης διαγράφηκε"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Παρουσιάστηκε σφάλμα κατά τη διαγραφή της εγγραφής οθόνης"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Η λήψη αδειών απέτυχε"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Επιλογές μεταφοράς αρχείων μέσω USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Προσάρτηση ως μονάδας αναπαραγωγής μέσων (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Προσάρτηση ως κάμερας (PTP)"</string>
@@ -130,7 +146,7 @@
     <string name="accessibility_ethernet_disconnected" msgid="5896059303377589469">"Το Ethernet αποσυνδέθηκε."</string>
     <string name="accessibility_ethernet_connected" msgid="2692130313069182636">"Το Ethernet συνδέθηκε."</string>
     <string name="accessibility_no_signal" msgid="7064645320782585167">"Δεν υπάρχει σήμα."</string>
-    <string name="accessibility_not_connected" msgid="6395326276213402883">"Δεν έχει συνδεθεί."</string>
+    <string name="accessibility_not_connected" msgid="6395326276213402883">"Μη συνδεδεμένο"</string>
     <string name="accessibility_zero_bars" msgid="3806060224467027887">"Μηδέν γραμμές."</string>
     <string name="accessibility_one_bar" msgid="1685730113192081895">"Μία γραμμή."</string>
     <string name="accessibility_two_bars" msgid="6437363648385206679">"Δύο γραμμές."</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Ειδοποιήσεις"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Δεν θα βλέπετε πλέον αυτές τις ειδοποιήσεις"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Αυτές οι ειδοποιήσεις θα ελαχιστοποιηθούν"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Συνήθως απορρίπτετε αυτές τις ειδοποιήσεις. \nΝα εξακολουθήσουν να εμφανίζονται;"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Να συνεχίσουν να εμφανίζονται αυτές οι ειδοποιήσεις;"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Διακοπή ειδοποιήσεων"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Συνέχιση εμφάνισης"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Ελαχιστοποίηση"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Να συνεχίσουν να εμφανίζονται ειδοποιήσεις από αυτήν την εφαρμογή;"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Αδύνατη η απενεργοποίηση αυτών των ειδοποιήσεων"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Αυτή η εφαρμογή χρησιμοποιεί την κάμερα."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Αυτή η εφαρμογή χρησιμοποιεί το μικρόφωνο."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Αυτή η εφαρμογή εμφανίζεται πάνω σε άλλες εφαρμογές στην οθόνη σας."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Να εμφανίζεται ποσοστό κατά τη φόρτιση (προεπιλογή)"</item>
     <item msgid="3327323682209964956">"Να μην εμφανίζεται αυτό το εικονίδιο"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Εμφάνιση εικονιδίων ειδοποιήσεων χαμηλής προτεραιότητας"</string>
     <string name="other" msgid="4060683095962566764">"Άλλο"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Διαχωριστικό οθόνης"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Αριστερή πλήρης οθόνη"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Η εφαρμογή άνοιξε χωρίς να έχει εγκατασταθεί."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Η εφαρμογή άνοιξε χωρίς να έχει εγκατασταθεί. Πατήστε για να μάθετε περισσότερα."</string>
     <string name="app_info" msgid="6856026610594615344">"Πληροφορίες εφαρμογής"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Μετάβαση στον ιστό"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Μετάβ. σε πρόγ. περ."</string>
     <string name="mobile_data" msgid="7094582042819250762">"Δεδομένα κινητής τηλεφωνίας"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Το Wi-Fi είναι ανενεργό"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Ρυθμίσεις"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Το κατάλαβα"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Στιγμ. μνήμης SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> χρησιμοποιεί τις λειτουργίες <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Οι εφαρμογές χρησιμοποιούν τις λειτουργίες <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Άν. εφαρμ."</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Ακύρωση"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ΟΚ"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Ρυθμίσεις"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> χρησιμοποιεί τη λειτουργία <xliff:g id="TYPE">%2$s</xliff:g> εδώ και <xliff:g id="TIME">%3$d</xliff:g> λ."</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Οι εφαρμογές <xliff:g id="APPS">%1$s</xliff:g> χρησιμοποιούν τη λειτουργία <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> χρησιμοποιεί τις λειτουργίες <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"κάμερα"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"τοποθεσία"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"μικρόφωνο"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 82c91c7..26590be 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Screen Recording"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Ongoing notification for a screen record session"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Start Recording"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Record voiceover"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Show taps"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Stop"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pause"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Resume"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Cancel"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Share"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Delete"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Screen recording cancelled"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Screen recording saved, tap to view"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Screen recording deleted"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Error deleting screen recording"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Failed to get permissions"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
@@ -582,14 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"These notifications will be minimised"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"These notifications will be shown silently"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"These notifications will alert you"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"You usually dismiss these notifications. \nKeep showing them?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimise"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Show silently"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Show and alert"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"These notifications can\'t be turned off"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"via <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"This app is using the camera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"This app is using the microphone."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"This app is displaying over other apps on your screen."</string>
@@ -804,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"App opened without being installed."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"App opened without being installed. Tap to find out more."</string>
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Go to web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
@@ -836,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Settings"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Open app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Cancel"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Settings"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPE">%2$s</xliff:g> for the last <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> are using your <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"camera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"location"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"microphone"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 361310e..2a59d07 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Screen Recording"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Ongoing notification for a screen record session"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Start Recording"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Record voiceover"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Show taps"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Stop"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pause"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Resume"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Cancel"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Share"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Delete"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Screen recording cancelled"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Screen recording saved, tap to view"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Screen recording deleted"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Error deleting screen recording"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Failed to get permissions"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
@@ -582,14 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"These notifications will be minimised"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"These notifications will be shown silently"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"These notifications will alert you"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"You usually dismiss these notifications. \nKeep showing them?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimise"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Show silently"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Show and alert"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"These notifications can\'t be turned off"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"via <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"This app is using the camera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"This app is using the microphone."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"This app is displaying over other apps on your screen."</string>
@@ -804,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"App opened without being installed."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"App opened without being installed. Tap to find out more."</string>
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Go to web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
@@ -836,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Settings"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Open app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Cancel"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Settings"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPE">%2$s</xliff:g> for the last <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> are using your <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"camera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"location"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"microphone"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 82c91c7..26590be 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Screen Recording"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Ongoing notification for a screen record session"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Start Recording"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Record voiceover"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Show taps"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Stop"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pause"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Resume"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Cancel"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Share"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Delete"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Screen recording cancelled"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Screen recording saved, tap to view"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Screen recording deleted"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Error deleting screen recording"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Failed to get permissions"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
@@ -582,14 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"These notifications will be minimised"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"These notifications will be shown silently"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"These notifications will alert you"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"You usually dismiss these notifications. \nKeep showing them?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimise"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Show silently"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Show and alert"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"These notifications can\'t be turned off"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"via <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"This app is using the camera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"This app is using the microphone."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"This app is displaying over other apps on your screen."</string>
@@ -804,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"App opened without being installed."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"App opened without being installed. Tap to find out more."</string>
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Go to web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
@@ -836,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Settings"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Open app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Cancel"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Settings"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPE">%2$s</xliff:g> for the last <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> are using your <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"camera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"location"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"microphone"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 82c91c7..26590be 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Try taking screenshot again"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Can\'t save screenshot due to limited storage space"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Taking screenshots isn\'t allowed by the app or your organisation"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Screen Recording"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Ongoing notification for a screen record session"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Start Recording"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Record voiceover"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Show taps"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Stop"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pause"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Resume"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Cancel"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Share"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Delete"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Screen recording cancelled"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Screen recording saved, tap to view"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Screen recording deleted"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Error deleting screen recording"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Failed to get permissions"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
@@ -582,14 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"You won\'t see these notifications anymore"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"These notifications will be minimised"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"These notifications will be shown silently"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"These notifications will alert you"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"You usually dismiss these notifications. \nKeep showing them?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Keep showing these notifications?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Stop notifications"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Keep showing"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimise"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Show silently"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Show and alert"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Keep showing notifications from this app?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"These notifications can\'t be turned off"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"via <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"This app is using the camera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"This app is using the microphone."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"This app is displaying over other apps on your screen."</string>
@@ -804,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"App opened without being installed."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"App opened without being installed. Tap to find out more."</string>
     <string name="app_info" msgid="6856026610594615344">"App info"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Go to web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Go to browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi is off"</string>
@@ -836,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Settings"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Open app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Cancel"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Settings"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPE">%2$s</xliff:g> for the last <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> are using your <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"camera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"location"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"microphone"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 8005d79..35075a7 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‏‎Try taking screenshot again‎‏‎‎‏‎"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎Can\'t save screenshot due to limited storage space‎‏‎‎‏‎"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‏‏‏‎‏‎‏‏‏‎‎Taking screenshots isn\'t allowed by the app or your organization‎‏‎‎‏‎"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎Screen Recording‎‏‎‎‏‎"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‏‎‎Ongoing notification for a screen record session‎‏‎‎‏‎"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎Start Recording‎‏‎‎‏‎"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎‏‎‏‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‏‏‎Record voiceover‎‏‎‎‏‎"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‎‎‎‎‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‎Show taps‎‏‎‎‏‎"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‎‏‎‎‎‎‎‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‎‎‎‏‏‎‎Stop‎‏‎‎‏‎"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‏‏‎Pause‎‏‎‎‏‎"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‎‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‏‎‎Resume‎‏‎‎‏‎"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‎‏‎Cancel‎‏‎‎‏‎"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎Share‎‏‎‎‏‎"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‎‎‏‏‎‏‎Delete‎‏‎‎‏‎"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‎‎Screen recording canceled‎‏‎‎‏‎"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‏‏‏‏‏‎‏‎‎Screen recording saved, tap to view‎‏‎‎‏‎"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‏‎‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‏‏‎‎‏‎Screen recording deleted‎‏‎‎‏‎"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‎Error deleting screen recording‎‏‎‎‏‎"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‏‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‎‎‎Failed to get permissions‎‏‎‎‏‎"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎USB file transfer options‎‏‎‎‏‎"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‎‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎Mount as a media player (MTP)‎‏‎‎‏‎"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‏‎‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‏‎Mount as a camera (PTP)‎‏‎‎‏‎"</string>
@@ -582,14 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎‏‎Notifications‎‏‎‎‏‎"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎You won\'t see these notifications anymore‎‏‎‎‏‎"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‏‏‏‏‎‎‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎These notifications will be minimized‎‏‎‎‏‎"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‏‏‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎These notifications will be shown silently‎‏‎‎‏‎"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‎‎‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‏‎‎‏‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‎These notifications will alert you‎‏‎‎‏‎"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‎‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‏‏‏‏‏‏‎You usually dismiss these notifications. ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Keep showing them?‎‏‎‎‏‎"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‎Keep showing these notifications?‎‏‎‎‏‎"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‏‎Stop notifications‎‏‎‎‏‎"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‎‏‎‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎Keep showing‎‏‎‎‏‎"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‎‎‎‎‎‎‎‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‏‏‏‎‎‏‏‎Minimize‎‏‎‎‏‎"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎Show silently‎‏‎‎‏‎"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‏‏‏‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎‎‏‏‏‎Show and alert‎‏‎‎‏‎"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‎Keep showing notifications from this app?‎‏‎‎‏‎"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‎‎‎‏‎‎‎‎‏‎‎‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎These notifications can\'t be turned off‎‏‎‎‏‎"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎via ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="appops_camera" msgid="8100147441602585776">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‎‎‎This app is using the camera.‎‏‎‎‏‎"</string>
     <string name="appops_microphone" msgid="741508267659494555">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‏‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‏‎This app is using the microphone.‎‏‎‎‏‎"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‎‏‏‏‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎This app is displaying over other apps on your screen.‎‏‎‎‏‎"</string>
@@ -804,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‎‏‏‎‏‎‎‏‏‎‎App opened without being installed.‎‏‎‎‏‎"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎App opened without being installed. Tap to learn more.‎‏‎‎‏‎"</string>
     <string name="app_info" msgid="6856026610594615344">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‏‏‎‎‎‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎‎‎‎App info‎‏‎‎‏‎"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎Go to web‎‏‎‎‏‎"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‎Go to browser‎‏‎‎‏‎"</string>
     <string name="mobile_data" msgid="7094582042819250762">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‎Mobile data‎‏‎‎‏‎"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="ID_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎ — ‎‏‎‎‏‏‎<xliff:g id="ID_2">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‏‏‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‏‏‎‏‎Wi-Fi is off‎‏‎‎‏‎"</string>
@@ -836,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‏‎‏‏‏‏‏‎‎‏‏‎‎‏‎‎‎‎‏‎Settings‎‏‎‎‏‎"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎Got it‎‏‎‎‏‎"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎Dump SysUI Heap‎‏‎‎‏‎"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‏‎‎‏‎‏‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is using your ‎‏‎‎‏‏‎<xliff:g id="TYPES_LIST">%2$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎Applications are using your ‎‏‎‎‏‏‎<xliff:g id="TYPES_LIST">%s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‎Open app‎‏‎‎‏‎"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎Cancel‎‏‎‎‏‎"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎Okay‎‏‎‎‏‎"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎Settings‎‏‎‎‏‎"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is using your ‎‏‎‎‏‏‎<xliff:g id="TYPE">%2$s</xliff:g>‎‏‎‎‏‏‏‎ for the last ‎‏‎‎‏‏‎<xliff:g id="TIME">%3$d</xliff:g>‎‏‎‎‏‏‏‎ min‎‏‎‎‏‎"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="APPS">%1$s</xliff:g>‎‏‎‎‏‏‏‎ are using your ‎‏‎‎‏‏‎<xliff:g id="TYPE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‏‏‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is using your ‎‏‎‎‏‏‎<xliff:g id="TYPES_LIST">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‏‏‎‏‎camera‎‏‎‎‏‎"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎location‎‏‎‎‏‎"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‎‎‎‏‏‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎microphone‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 3f3187b..54362c3 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Vuelve a hacer una captura de pantalla"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"No se puede guardar la captura de pantalla debido a que no hay suficiente espacio de almacenamiento"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"La app o tu organización no permiten las capturas de pantalla"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Grabación de pantalla"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Notificación constante para una sesión de grabación de pantalla"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Iniciar grabación"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Grabar voz superpuesta"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Mostrar toques"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Detener"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pausar"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Reanudar"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Cancelar"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Compartir"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Borrar"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Se canceló la grabación de pantalla"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Se guardó la grabación de pantalla; presiona para verla"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Se borró la grabación de pantalla"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Error al borrar la grabación de pantalla"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Error al obtener permisos"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Activar como cámara (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificaciones"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Ya no verás estas notificaciones"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Se minimizarán estas notificaciones"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Sueles descartar estas notificaciones. \n¿Quieres seguir recibiéndolas?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"¿Quieres seguir viendo estas notificaciones?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Detener notificaciones"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Seguir viendo"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimizar"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"¿Quieres seguir viendo las notificaciones de esta app?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"No se pueden desactivar estas notificaciones"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Esta app está usando la cámara."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Esta app está usando el micrófono."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Esta app se muestra sobre otras apps en la pantalla."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Mostrar el porcentaje durante la carga (predeterminado)"</item>
     <item msgid="3327323682209964956">"No mostrar este ícono"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Mostrar íconos de notificaciones con prioridad baja"</string>
     <string name="other" msgid="4060683095962566764">"Otros"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Divisor de pantalla dividida"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Pantalla izquierda completa"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"La app se abrió sin instalarse."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"La app se abrió sin instalarse. Presiona para obtener más información."</string>
     <string name="app_info" msgid="6856026610594615344">"Información de apps"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Ir a la Web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Ir al navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Datos móviles"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desactivado"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Configuración"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Entendido"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Volcar pila de SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> está usando tu <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Hay aplicaciones que están usando tu <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Abrir app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Cancelar"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Aceptar"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Ajustes"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> lleva <xliff:g id="TIME">%3$d</xliff:g> min usando tu <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> están usando tu <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> está usando tu <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"cámara"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"ubicación"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"micrófono"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 356ef45..7fb2b8e 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Vuelve a intentar hacer la captura de pantalla"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"No se puede guardar la captura de pantalla porque no hay espacio de almacenamiento suficiente"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"La aplicación o tu organización no permiten realizar capturas de pantalla"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Grabación de la pantalla"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Notificación continua de una sesión de grabación de la pantalla"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Iniciar grabación"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Grabar voz en off"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Mostrar toques"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Detener"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pausar"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Seguir"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Cancelar"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Compartir"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Eliminar"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Se ha cancelado la grabación de la pantalla"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Se ha guardado la grabación de la pantalla; toca para verla"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Se ha eliminado la grabación de la pantalla"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"No se ha podido eliminar la grabación de la pantalla"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"No se han podido obtener los permisos"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Activar como cámara (PTP)"</string>
@@ -582,14 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificaciones"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"No volverás a ver estas notificaciones"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Se minimizarán estas notificaciones"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"Estas notificaciones se mostrarán de forma silenciosa"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Estas notificaciones te avisarán con sonido"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Normalmente ignoras estas notificaciones. \n¿Quieres seguir viéndolas?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"¿Quieres seguir viendo estas notificaciones?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Detener las notificaciones"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Seguir mostrando"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimizar"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Mostrar en silencio"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Mostrar y sonar"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"¿Quieres seguir viendo las notificaciones de esta aplicación?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Estas notificaciones no se pueden desactivar"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"mediante <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Esta aplicación está usando la cámara."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Esta aplicación está usando el micrófono."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Esta aplicación se está mostrando sobre otras aplicaciones en tu pantalla."</string>
@@ -804,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"La aplicación se ha abierto sin instalarse."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"La aplicación se ha abierto sin instalarse. Toca para obtener más información."</string>
     <string name="app_info" msgid="6856026610594615344">"Información de la aplicación"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Ir a la Web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Ir al navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Datos móviles"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> ‑ <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desactivado"</string>
@@ -836,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Ajustes"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Entendido"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Volcar pila de SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> está usando tu <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Hay aplicaciones que usan tu <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Abrir app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Cancelar"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Aceptar"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Ajustes"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> está usando tu <xliff:g id="TYPE">%2$s</xliff:g> desde hace <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> están usando tu <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> está usando tu <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"cámara"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"ubicación"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"micrófono"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index f125b84..65a42a6 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Proovige ekraanipilt uuesti jäädvustada"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Piiratud salvestusruumi tõttu ei saa ekraanipilti salvestada"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Rakendus või teie organisatsioon ei luba ekraanipilte jäädvustada"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Ekraanikuva salvestamine"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Pooleli märguanne ekraanikuva salvestamise seansi puhul"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Alusta salvestamist"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Salvesta hääl"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Kuva puudutused"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Peata"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Peata"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Jätka"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Tühista"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Jaga"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Kustuta"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Ekraanikuva salvestamine on tühistatud"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Ekraanikuva salvestis on salvestatud, puudutage vaatamiseks"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Ekraanikuva salvestis on kustutatud"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Viga ekraanikuva salvestise kustutamisel"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Lubade hankimine ebaõnnestus"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-failiedastuse valikud"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Paigalda meediumimängijana (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Paigalda kaamerana (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Märguanded"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Te ei näe enam neid märguandeid"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Need märguanded minimeeritakse"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Tavaliselt loobute nendest märguannetest. \nKas soovite neid jätkuvalt näidata?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Kas soovite nende märguannete kuvamist jätkata?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Peata märguanded"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Jätka kuvamist"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimeeri"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Kas jätkata selle rakenduse märguannete kuvamist?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Neid märguandeid ei saa välja lülitada"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"See rakendus kasutab kaamerat."</string>
     <string name="appops_microphone" msgid="741508267659494555">"See rakendus kasutab mikrofoni."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"See rakendus kuvatakse teie ekraanil muude rakenduste peal."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Kuva protsent laadimisel (vaikimisi)"</item>
     <item msgid="3327323682209964956">"Ära kuva seda ikooni"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Kuva madala prioriteediga märguande ikoonid"</string>
     <string name="other" msgid="4060683095962566764">"Muu"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Ekraanijagaja"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Vasak täisekraan"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Rakendus avati installimata."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Rakendus avati installimata. Lisateabe saamiseks puudutage."</string>
     <string name="app_info" msgid="6856026610594615344">"Rakenduse teave"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Avage veebis"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Ava brauser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobiilne andmeside"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"WiFi on välja lülitatud"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Seaded"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Selge"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> kasutab järgmisi: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Rakendused kasutavad järgmisi: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Ava rakendus"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Tühista"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Seaded"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> on viimased <xliff:g id="TIME">%3$d</xliff:g> minutit kasutanud järgmist: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> kasutavad järgmist: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> kasutab järgmisi: <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kaamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"asukoht"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 6e3f094..97ba5b9 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Saiatu berriro pantaila-argazkia ateratzen"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Ezin da gorde pantaila-argazkia ez delako gelditzen tokirik"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikazioak edo erakundeak ez du onartzen pantaila-argazkiak ateratzea"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Pantailaren grabaketa"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Pantailaren grabaketa-saioaren jakinarazpen jarraitua"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Hasi grabatzen"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Grabatu off ahotsa"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Erakutsi sakatzeak"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Utzi"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pausatu"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Berrekin"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Utzi"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Partekatu"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Ezabatu"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Utzi zaio pantaila grabatzeari"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Gorde da pantailaren grabaketa; sakatu ikusteko"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Ezabatu da pantailaren grabaketa"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Errore bat gertatu da pantailaren grabaketa ezabatzean"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Ezin izan dira lortu baimenak"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fitxategiak transferitzeko aukerak"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Muntatu multimedia-erreproduzigailu gisa (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Muntatu kamera gisa (PTP)"</string>
@@ -582,14 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Jakinarazpenak"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Aurrerantzean ez duzu ikusiko horrelako jakinarazpenik"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Minimizatu egingo dira jakinarazpen hauek"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"Jakinarazpen hauek soinurik egin gabe erakutsiko dira"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Jakinarazpen hauek soinu bidezko alerta bidez erakutsiko dira"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Baztertu egin ohi dituzu jakinarazpen hauek. \nHaiek erakusten jarraitzea nahi duzu?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Jakinarazpenak erakusten jarraitzea nahi duzu?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Blokeatu jakinarazpenak"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Jarraitu erakusten"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimizatu"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Erakutsi soinurik egin gabepen"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Erakutsi eta egin soinua"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Aplikazio honen jakinarazpenak erakusten jarraitzea nahi duzu?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Jakinarazpen hauek ezin dira desaktibatu"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren bidez"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Kamera erabiltzen ari da aplikazioa."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Mikrofonoa erabiltzen ari da aplikazioa."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Pantailako beste aplikazioen gainean agertzen da aplikazioa."</string>
@@ -804,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Ezer instalatu gabe ireki da aplikazioa."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Ezer instalatu gabe ireki da aplikazioa. Sakatu informazio gehiago lortzeko."</string>
     <string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Joan sarera"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Joan arakatzailera"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Datu-konexioa"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi konexioa desaktibatuta dago"</string>
@@ -836,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Ezarpenak"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Ados"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="TYPES_LIST">%2$s</xliff:g> erabiltzen ari da."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplikazio batzuk <xliff:g id="TYPES_LIST">%s</xliff:g> erabiltzen ari dira."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Ireki aplikazioa"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Utzi"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Ados"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Ezarpenak"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> aplikazioak <xliff:g id="TYPE">%2$s</xliff:g> erabili du azken <xliff:g id="TIME">%3$d</xliff:g> minutuetan"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> <xliff:g id="TYPE">%2$s</xliff:g> erabiltzen ari dira"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="TYPES_LIST">%2$s</xliff:g> erabiltzen ari da"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"kokapena"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofonoa"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index e785f76..049513a 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"دوباره عکس صفحه‌نمایش بگیرید"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"به دلیل محدود بودن فضای ذخیره‌سازی نمی‌توان عکس صفحه‌نمایش را ذخیره کرد"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"برنامه یا سازمان شما اجازه نمی‌دهند عکس صفحه‌نمایش بگیرید."</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"ضبط صفحه‌نمایش"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"اعلان درحال انجام برای جلسه ضبط صفحه‌نمایش"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"شروع ضبط"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"ضبط صدا روی تصویر"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"نمایش ضربه‌ها"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"توقف"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"مکث"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"ازسرگیری"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"لغو"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"هم‌رسانی"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"حذف"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"ضبط صفحه‌نمایش لغو شد"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"ضبط صفحه‌نمایش ذخیره شد، برای مشاهده ضربه بزنید"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"فایل ضبط صفحه‌نمایش حذف شد"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"خطا در حذف فایل ضبط صفحه‌نمایش"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"مجوزها دریافت نشدند"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏گزینه‌های انتقال فایل USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏نصب به‌عنوان دستگاه پخش رسانه (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"‏تصب به‌عنوان دوربین (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"اعلان‌ها"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"دیگر این اعلان‌ها را نخواهید دید"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"این اعلان‌ها کوچک خواهد شد"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"معمولاً این اعلان‌ها را رد می‌کنید. \nهمچنان نشان داده شود؟"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"نمایش این اعلان‌ها ادامه یابد؟"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"توقف اعلان‌ها"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"همچنان نشان داده شود"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"کوچک کردن"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"نمایش اعلان از این برنامه ادامه یابد؟"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"نمی‌توان این اعلان‌ها را خاموش کرد"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"این برنامه از دوربین استفاده می‌کند."</string>
     <string name="appops_microphone" msgid="741508267659494555">"این برنامه از میکروفون استفاده می‌کند."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"این برنامه روی برنامه‌های دیگر در صفحه‌نمایش نشان داده می‌شود."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"هنگام شارژ شدن درصد نشان داده شود (پیش‌فرض)"</item>
     <item msgid="3327323682209964956">"این نماد نشان داده نشود"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"نمایش نمادهای اعلان کم‌اهمیت"</string>
     <string name="other" msgid="4060683095962566764">"موارد دیگر"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"تقسیم‌کننده صفحه"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"تمام‌صفحه چپ"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"برنامه بدون نصب شدن باز شد."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"برنامه بدون نصب شدن باز شد. برای اطلاعات بیشتر ضربه بزنید."</string>
     <string name="app_info" msgid="6856026610594615344">"اطلاعات برنامه"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"رفتن به وب"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"رفتن به مرورگر"</string>
     <string name="mobile_data" msgid="7094582042819250762">"داده تلفن همراه"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"‏Wi-Fi خاموش است"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"تنظیمات"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"متوجه شدم"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> از <xliff:g id="TYPES_LIST">%2$s</xliff:g> شما استفاده می‌کند."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"برنامه‌ها از <xliff:g id="TYPES_LIST">%s</xliff:g> شما استفاده می‌‌کنند."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"باز کردن برنامه"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"لغو"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"خوب"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"تنظیمات"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> از <xliff:g id="TYPE">%2$s</xliff:g> در <xliff:g id="TIME">%3$d</xliff:g> دقیقه آخر استفاده می‌کند"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> از <xliff:g id="TYPE">%2$s</xliff:g> شما استفاده می‌کند"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> از <xliff:g id="TYPES_LIST">%2$s</xliff:g> شما استفاده می‌کند"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"دوربین"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"مکان"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"میکروفون"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index af35a85..277ef5d 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Yritä ottaa kuvakaappaus uudelleen."</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Kuvakaappauksen tallennus epäonnistui, sillä tallennustilaa ei ole riittävästi"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Sovellus tai organisaatio ei salli kuvakaappauksien tallentamista."</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Näytön tallennus"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Pysyvä ilmoitus näytön tallentamisesta"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Aloita tallennus"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Äänitä taustaselostus"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Näytä napautukset"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Lopeta"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Keskeytä"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Jatka"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Peruuta"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Jaa"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Poista"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Näytön tallennus peruutettu"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Näyttötallenne tallennettu, katso napauttamalla"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Näyttötallenne poistettu"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Virhe poistettaessa näyttötallennetta"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Käyttöoikeuksien hakeminen epäonnistui."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-tiedostonsiirtoasetukset"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Käytä mediasoittimena (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Käytä kamerana (PTP)"</string>
@@ -582,14 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Ilmoitukset"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Et näe näitä ilmoituksia enää"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Nämä ilmoitukset pienennetään"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Hylkäät yleensä nämä ilmoitukset. \nHaluatko, että niitä näytetään myös jatkossa?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Jatketaanko näiden ilmoitusten näyttämistä?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Lopeta ilmoitukset"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Jatka näyttämistä"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Pienennä"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Jatketaanko ilmoitusten näyttämistä tästä sovelluksesta?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Näitä ilmoituksia ei voi poistaa käytöstä"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Tämä sovellus käyttää kameraa."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Tämä sovellus käyttää mikrofonia."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Tämä sovellus näkyy näytöllä muiden sovellusten päällä."</string>
@@ -804,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Sovellus avattiin ilman asennusta."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Sovellus avattiin ilman asennusta. Katso lisätietoja napauttamalla."</string>
     <string name="app_info" msgid="6856026610594615344">"Sovelluksen tiedot"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Avaa verkossa"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Siirry selaimeen"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobiilitiedonsiirto"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi on pois käytöstä"</string>
@@ -836,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Asetukset"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Selvä"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Luo SysUI-keon vedos"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> käyttää ominaisuuksia (<xliff:g id="TYPES_LIST">%2$s</xliff:g>)."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"<xliff:g id="TYPES_LIST">%s</xliff:g> ovat sovellusten käytössä."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Avaa"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Peruuta"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Asetukset"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> on käyttänyt ominaisuutta (<xliff:g id="TYPE">%2$s</xliff:g>) <xliff:g id="TIME">%3$d</xliff:g> minuutin ajan."</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> käyttävät ominaisuutta (<xliff:g id="TYPE">%2$s</xliff:g>)."</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> käyttää ominaisuuksia (<xliff:g id="TYPES_LIST">%2$s</xliff:g>)."</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"sijainti"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofoni"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 06f178a..905af5b 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Essayez de faire une autre capture d\'écran"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"L\'application ou votre organisation n\'autorise pas les saisies d\'écran"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Enregistrement d\'écran"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Notification en cours pour une session d\'enregistrement d\'écran"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Commencer l\'enregistrement"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Enregistrer la voix hors champ"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Afficher les éléments sélectionnés"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Arrêter"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pause"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Reprendre"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Annuler"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Partager"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Supprimer"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"L\'enregistrement d\'écran a été annulé"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"L\'enregistrement d\'écran est terminé. Touchez ici pour l\'afficher."</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"L\'enregistrement d\'écran a été supprimé"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Une erreur s\'est produite lors de la suppression de l\'enregistrement d\'écran"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Impossible d\'obtenir les autorisations"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Installer comme un lecteur multimédia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Installer comme un appareil photo (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Vous ne verrez plus ces notifications"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Ces notifications seront réduites"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Vous ignorez habituellement ces notifications. \nSouhaitez-vous continuer à les afficher?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Continuer à afficher ces notifications?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Arrêter les notifications"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Continuer à afficher"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Réduire"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuer à afficher les notifications de cette application?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ces notifications ne peuvent pas être désactivées"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Cette application utilise l\'appareil photo."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Cette application utilise le microphone."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Cette application superpose du contenu par-dessus d\'autres applications à l\'écran."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Montrer le pourcentage durant la charge (par défaut)"</item>
     <item msgid="3327323682209964956">"Ne pas afficher cette icône"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Afficher les icônes de notification de faible priorité"</string>
     <string name="other" msgid="4060683095962566764">"Autre"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Séparateur d\'écran partagé"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Plein écran à la gauche"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Application ouverte sans avoir été installée."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Application ouverte sans avoir été installée. Touchez ici pour en savoir plus."</string>
     <string name="app_info" msgid="6856026610594615344">"Détails de l\'application"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Accéder au Web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Ouvrir le navigateur"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Données cellulaires"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> : <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Le Wi-Fi est désactivé"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Paramètres"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Capturer mémoire SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> utilise votre <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Des applications utilisent votre <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Ouv. appli"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Annuler"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Paramètres"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> utilise votre <xliff:g id="TYPE">%2$s</xliff:g> depuis <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> utilisent votre <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> utilise votre <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"appareil photo"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"position"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"microphone"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7157cb5..88e5f6cd 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Essayez de nouveau de faire une capture d\'écran"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Les captures d\'écran ne sont pas autorisées par l\'application ni par votre organisation"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Enregistrement de l\'écran"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Notification en cours pour une session d\'enregistrement de l\'écran"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Démarrer l\'enregistrement"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Enregistrer une voix off"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Afficher les éléments sélectionnés"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Arrêter"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pause"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Reprendre"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Annuler"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Partager"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Supprimer"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Enregistrement de l\'écran annulé"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Enregistrement de l\'écran enregistré. Appuyez pour afficher"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Enregistrement de l\'écran supprimé"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Erreur lors de la suppression de l\'enregistrement de l\'écran"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Échec d\'obtention des autorisations"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Installer en tant que lecteur multimédia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Installer en tant qu\'appareil photo (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifications"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Vous ne recevrez plus ces notifications"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Ces notifications seront réduites"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Vous ignorez généralement ces notifications. \nSouhaitez-vous continuer de les recevoir ?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Continuer d\'afficher ces notifications ?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Arrêter les notifications"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Continuer d\'afficher les notifications"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Réduire"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuer d\'afficher les notifications de cette application ?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ces notifications ne peuvent pas être désactivées"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Cette application utilise la caméra."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Cette application utilise le micro."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Cette application se superpose aux autres applications sur l\'écran."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Afficher le pourcentage lorsque l\'appareil est en charge (option par défaut)"</item>
     <item msgid="3327323682209964956">"Ne plus afficher cette icône"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Afficher les icônes de notification à faible priorité"</string>
     <string name="other" msgid="4060683095962566764">"Autre"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Séparateur d\'écran partagé"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Écran de gauche en plein écran"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Vous pouvez ouvrir cette application sans l\'installer."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Vous pouvez ouvrir cette application sans l\'installer. Appuyez pour en savoir plus."</string>
     <string name="app_info" msgid="6856026610594615344">"Infos sur l\'appli"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Accéder au site Web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Accéder au navigateur"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Données mobiles"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi désactivé"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Paramètres"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Copier mémoire SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> utilise votre <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Des applications utilisent votre <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Ouvrir appli"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Annuler"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Paramètres"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> utilise votre <xliff:g id="TYPE">%2$s</xliff:g> depuis <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> utilisent votre <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> utilise votre <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"appareil photo"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"position"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"micro"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index f17243e..999c1ca 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Volve tentar crear unha captura de pantalla"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Non se puido gardar a captura de pantalla porque o espazo de almacenamento é limitado"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"A aplicación ou a túa organización non permite realizar capturas de pantalla"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Gravación de pantalla"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Notificación en curso sobre unha sesión de gravación de pantalla"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Iniciar gravación"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Gravar voz en off"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Mostrar toques"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Deter"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Poñer en pausa"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Retomar"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Cancelar"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Compartir"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Eliminar"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Cancelouse a gravación de pantalla"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Gardouse a gravación de pantalla; toca esta notificación para visualizala"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Eliminouse a gravación de pantalla"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Produciuse un erro ao eliminar a gravación de pantalla"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Produciuse un erro ao obter os permisos"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcións de transferencia USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Inserir como reprodutor multimedia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Inserir como cámara (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificacións"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Deixarás de ver estas notificacións"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Minimizaranse estas notificacións"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Ignoras estas notificacións a miúdo. \nQueres seguir recibíndoas?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Queres seguir mostrando estas notificacións?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Deter notificacións"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Continuar mostrando notificacións"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimizar"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Queres seguir mostrando as notificacións desta aplicación?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Non se poden desactivar estas notificacións"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Esta aplicación está utilizando a cámara."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Esta aplicación está utilizando o micrófono."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Esta aplicación móstrase sobre outras aplicacións da pantalla."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Mostrar porcentaxe durante a carga (predeterminado)"</item>
     <item msgid="3327323682209964956">"Non mostrar esta icona"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Mostrar iconas das notificacións que teñan baixa prioridade"</string>
     <string name="other" msgid="4060683095962566764">"Outros"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Divisor de pantalla dividida"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Pantalla completa á esquerda"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Abriuse a aplicación sen ter que instalala."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Abriuse a aplicación sen ter que instalala. Tocar para obter máis información."</string>
     <string name="app_info" msgid="6856026610594615344">"Info. da aplicación"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Acceder á web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Ir ao navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Datos móbiles"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g>-<xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"A wifi está desactivada"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Configuración"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"De acordo"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Baleirar mont. SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> está utilizando <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Hai aplicacións que están utilizando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Abrir app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Cancelar"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Aceptar"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Axustes"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> está utilizando <xliff:g id="TYPE">%2$s</xliff:g> desde hai <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> están utilizando <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> está utilizando <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"a cámara"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"a localiz."</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"o micrófono"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 1d55555..ecaa321 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"ફરીથી સ્ક્રીનશૉટ લેવાનો પ્રયાસ કરો"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"મર્યાદિત સ્ટોરેજ સ્પેસને કારણે સ્ક્રીનશૉટ સાચવી શકાતો નથી"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશૉટ લેવાની મંજૂરી નથી"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"સ્ક્રીન રેકોર્ડિંગ"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"સ્ક્રીન રેકોર્ડિંગ સત્ર માટે ચાલુ નોટિફિકેશન"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"રેકોર્ડિંગ શરૂ કરો"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"વૉઇસઓવર રેકોર્ડ કરો"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"ટૅપ કર્યાની સંખ્યા બતાવો"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"રોકો"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"થોભાવો"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"ફરી શરૂ કરો"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"રદ કરો"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"શેર કરો"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"ડિલીટ કરો"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"સ્ક્રીન રેકોર્ડિંગ રદ કર્યું"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"સ્ક્રીન રેકોર્ડિંગ સાચવ્યું, જોવા માટે ટૅપ કરો"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"સ્ક્રીન રેકોર્ડિંગ ડિલીટ કર્યું"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"સ્ક્રીન રેકોર્ડિંગ ડિલીટ કરવામાં ભૂલ આવી"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"પરવાનગીઓ મેળવવામાં નિષ્ફળ રહ્યાં"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ફાઇલ ટ્રાન્સફર વિકલ્પો"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"મીડિયા પ્લેયર તરીકે માઉન્ટ કરો (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"કૅમેરા તરીકે માઉન્ટ કરો (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"નોટિફિકેશનો"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"તમને હવેથી આ નોટિફિકેશન દેખાશે નહીં"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"આ બધા નોટિફિકેશન નાના કરવામાં આવશે"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"તમે સામાન્ય રીતે આ નોટીફિકેશનને છોડી દો છો. \nતેમને બતાવવાનું ચાલુ રાખીએ?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"આ નોટિફિકેશન બતાવવાનું ચાલુ રાખીએ?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"નોટિફિકેશન બંધ કરો"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"બતાવવાનું ચાલુ રાખો"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"નાનું કરો"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"આ ઍપમાંથી નોટિફિકેશન બતાવવાનું ચાલુ રાખીએ?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"આ નોટિફિકેશન બંધ કરી શકશો નહીં"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"આ ઍપ કૅમેરાનો ઉપયોગ કરી રહી છે."</string>
     <string name="appops_microphone" msgid="741508267659494555">"આ ઍપ માઇક્રોફોનનો ઉપયોગ કરી રહી છે."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"આ ઍપ તમારી સ્ક્રીન પરની અન્ય ઍપની ઉપર પ્રદર્શિત થઈ રહી છે."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"ચાર્જ થાય ત્યારે ટકાવારી બતાવો (ડિફોલ્ટ)"</item>
     <item msgid="3327323682209964956">"આ આઇકન બતાવશો નહીં"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"ઓછી પ્રાધાન્યતાનું નોટિફિકેશન આઇકન બતાવો"</string>
     <string name="other" msgid="4060683095962566764">"અન્ય"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"સ્પ્લિટ-સ્ક્રીન વિભાજક"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"ડાબી પૂર્ણ સ્ક્રીન"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"ઍપ ઇન્સ્ટૉલ કર્યા વિના ખુલી જાય છે."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"ઍપ ઇન્સ્ટૉલ કર્યા વિના ખુલી જાય છે. વધુ જાણવા માટે ટૅપ કરો."</string>
     <string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"વેબ પર જાઓ"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"બ્રાઉઝર પર જાઓ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"મોબાઇલ ડેટા"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"વાઇ-ફાઇ બંધ છે"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"સેટિંગ"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"સમજાઈ ગયું"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> ઍપ તમારા <xliff:g id="TYPES_LIST">%2$s</xliff:g>નો ઉપયોગ કરી રહી છે."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"ઍપ્લિકેશન તમારા <xliff:g id="TYPES_LIST">%s</xliff:g>નો ઉપયોગ કરી રહી છે."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"ઍપ ખોલો"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"રદ કરો"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ઓકે"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"સેટિંગ"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"છેલ્લી <xliff:g id="TIME">%3$d</xliff:g> મિનિટથી <xliff:g id="APP">%1$s</xliff:g> ઍપ તમારા <xliff:g id="TYPE">%2$s</xliff:g>નો ઉપયોગ કરી રહી છે"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> ઍપ તમારા <xliff:g id="TYPE">%2$s</xliff:g>નો ઉપયોગ કરી રહી છે"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> અ‍ૅપ તમારા <xliff:g id="TYPES_LIST">%2$s</xliff:g>નો ઉપયોગ કરી રહી છે"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"કૅમેરા"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"સ્થાન"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"માઇક્રોફોન"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index e6004f3..c1cb317 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"स्क्रीनशॉट दोबारा लेने की कोशिश करें"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"मेमोरी कम होने की वजह से स्क्रीनशॉट सेव नहीं किया जा सका"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ऐप्लिकेशन या आपका संगठन स्क्रीनशॉट लेने की अनुमति नहीं देता"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"स्क्रीन रिकॉर्डिंग"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"स्क्रीन रिकॉर्ड सेशन के लिए जारी सूचना"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"रिकॉर्डिंग शुरू करें"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"वॉइसओवर रिकॉर्ड करें"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"टैप दिखाएं"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"रोकें"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"रोकें"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"फिर से शुरू करें"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"रद्द करें"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"शेयर करें"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"मिटाएं"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"स्क्रीन रिकॉर्डिंग रद्द कर दी गई"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"स्क्रीन रिकॉर्डिंग सेव की गई, देखने के लिए टैप करें"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"स्क्रीन रिकॉर्डिंग मिटा दी गई"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"स्क्रीन रिकॉर्डिंग मिटाने में गड़बड़ी हुई"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"मंज़ूरी नहीं मिल सकी"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फ़ाइल स्थानांतरण विकल्प"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"मीडिया प्लेयर के रूप में माउंट करें (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"कैमरे के रूप में माउंट करें (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"सूचना"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"अब आपको ये सूचनाएं दिखाई नहीं देंगी"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"इन सूचनाओं को छोटा कर दिया जाएगा"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"अाप अक्सर इन सूचनाओं को खारिज कर देते हैं. \nआगे भी इन्हें देखना जारी रखना चाहते हैं?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"ये सूचनाएं दिखाना जारी रखें?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"सूचनाएं दिखाना बंद करें"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"दिखाना जारी रखें"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"सूचनाएं छोटी करें"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"इस ऐप्लिकेशन से जुड़ी सूचनाएं दिखाना जारी रखें?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"ये सूचनाएं दिखाया जाना बंद नहीं किया जा सकता"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"यह ऐप्लिकेशन कैमरे का इस्तेमाल कर रहा है."</string>
     <string name="appops_microphone" msgid="741508267659494555">"यह ऐप्लिकेशन माइक्रोफ़ोन का इस्तेमाल कर रहा है."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"यह ऐप्लिकेशन आपकी स्क्रीन पर इस्तेमाल हो रहे दूसरे ऐप्लिकेशन के ऊपर दिखाया जा रहा है."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"चार्ज होते समय प्रतिशत दिखाएं (डिफ़ॉल्ट)"</item>
     <item msgid="3327323682209964956">"इस आइकॉन को ना दिखाएं"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"कम प्राथमिकता वाली सूचना के आइकॉन दिखाएं"</string>
     <string name="other" msgid="4060683095962566764">"अन्य"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"विभाजित स्क्रीन विभाजक"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"बाईं स्क्रीन को पूर्ण स्क्रीन बनाएं"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"ऐप्लिकेशन इंस्टॉल किए बिना ही खुल गया है."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"ऐप्लिकेशन इंस्टॉल किए बिना ही खुल गया है. ज़्यादा जानने के लिए टैप करें."</string>
     <string name="app_info" msgid="6856026610594615344">"ऐप की जानकारी"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"वेब पर जाएं"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ब्राउज़र पर जाएं"</string>
     <string name="mobile_data" msgid="7094582042819250762">"मोबाइल डेटा"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"वाई-फ़ाई बंद है"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"सेटिंग"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"ठीक है"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> आपकी <xliff:g id="TYPES_LIST">%2$s</xliff:g> का इस्तेमाल कर रहा है."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"ऐप्लिकेशन आपकी <xliff:g id="TYPES_LIST">%s</xliff:g> का इस्तेमाल कर रहे हैं."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"ऐप खोलें"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"रद्द करें"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ठीक है"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"सेटिंग"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"पिछले <xliff:g id="TIME">%3$d</xliff:g> मि. से <xliff:g id="APP">%1$s</xliff:g> आपकी <xliff:g id="TYPE">%2$s</xliff:g> का इस्तेमाल कर रहा है"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> आपकी <xliff:g id="TYPE">%2$s</xliff:g> का इस्तेमाल कर रहे हैं"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> आपकी <xliff:g id="TYPES_LIST">%2$s</xliff:g> का इस्तेमाल कर रहा है"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"कैमरा"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"जगह"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"माइक्रोफ़ोन"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 777a9ff..901e2fe 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Pokušajte ponovo napraviti snimku zaslona"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Zaslon nije snimljen zbog ograničenog prostora za pohranu"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikacija ili vaša organizacija ne dopuštaju snimanje zaslona"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Snimanje zaslona"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Tekuća obavijest za sesiju snimanja zaslona"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Započni snimanje"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Snimi glasovni zapis"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Prikaži dodire"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Zaustavi"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pauza"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Nastavi"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Odustani"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Dijeli"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Izbriši"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Snimanje zaslona otkazano"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Snimanje zaslona spremljeno je, dodirnite da biste ga pregledali"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Snimanje zaslona izbrisano"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Pogreška prilikom brisanja snimanja zaslona"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Dohvaćanje dopuštenja nije uspjelo"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa datoteka"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Učitaj kao media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Učitaj kao fotoaparat (PTP)"</string>
@@ -585,14 +601,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Obavijesti"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Te vam se obavijesti više neće prikazivati"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Te će se obavijesti minimizirati"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"Ove obavijesti prikazivat će se tiho"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Ove obavijesti imat će zvučni signal"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Obično odbacujete te obavijesti. \nŽelite li da se nastave prikazivati?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Želite li da se obavijesti nastave prikazivati?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Zaustavi obavijesti"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Nastavi prikazivati"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimiziraj"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Prikaži tiho"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Prikaži uz zvučni signal"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Želite li da se obavijesti te aplikacije nastave prikazivati?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Te se obavijesti ne mogu isključiti"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"putem aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Ova aplikacija upotrebljava kameru."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Ova aplikacija upotrebljava mikrofon."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Ova se aplikacija prikazuje preko drugih aplikacija na zaslonu."</string>
@@ -809,7 +828,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Aplikacija je otvorena bez instaliranja."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Aplikacija je otvorena bez instaliranja. Dodirnite da biste saznali više."</string>
     <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Prijeđi na web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Otvori preglednik"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilni podaci"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je isključen"</string>
@@ -841,4 +860,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Postavke"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Shvaćam"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Izdvoji mem. SysUI-a"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> upotrebljava <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplikacije upotrebljavaju <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Otvori aplikaciju"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Odustani"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"U redu"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Postavke"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> upotrebljava <xliff:g id="TYPE">%2$s</xliff:g> unatrag <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Aplikacije <xliff:g id="APPS">%1$s</xliff:g> upotrebljavaju <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> upotrebljava <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"fotoaparat"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"lokaciju"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 16db000..7a5e026 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Próbálja meg újra elkészíteni a képernyőképet"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Nem menthet képernyőképet, mert kevés a tárhely"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Az alkalmazás vagy az Ön szervezete nem engedélyezi képernyőkép készítését"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Képernyőrögzítés"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Folyamatban lévő értesítés képernyőrögzítési munkamenethez"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Rögzítés indítása"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Hang rögzítése"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Koppintások megjelenítése"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Leállítás"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Szünet"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Folytatás"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Mégse"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Megosztás"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Törlés"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"A képernyő rögzítése megszakítva"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Képernyőfelvétel mentve, koppintson a megtekintéshez"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"A képernyőről készült felvétel törölve"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Hiba történt a képernyőről készült felvétel törlésekor"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Nincs engedély"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-fájlátvitel beállításai"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Csatlakoztatás médialejátszóként (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Csatlakoztatás kameraként (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Értesítések"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Többé nem jelennek meg ezek az értesítések"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Ezek az értesítések kis méretben jelennek meg"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Általában elveti ezeket az értesítéseket.\nSzeretné, hogy továbbra is megjelenjenek?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Továbbra is megjelenjenek ezek az értesítések?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Értesítések letiltása"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Megjelenítés továbbra is"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Kis méret"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Továbbra is megjelenjenek az alkalmazás értesítései?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ezeket az értesítéseket nem lehet kikapcsolni"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Ez az alkalmazás használja a kamerát."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Ez az alkalmazás használja a mikrofont."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Ez az alkalmazás a képernyőn lévő egyéb alkalmazások előtt jelenik meg."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Százalékos érték töltés közben látható (alapértelmezett)"</item>
     <item msgid="3327323682209964956">"Ne jelenjen meg ez az ikon"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Alacsony prioritású értesítési ikonok mutatása"</string>
     <string name="other" msgid="4060683095962566764">"Egyéb"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Elválasztó az osztott nézetben"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Bal oldali teljes képernyőre"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Az alkalmazás telepítés nélkül lett megnyitva."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Az alkalmazás telepítés nélkül lett megnyitva. Ha további információra van szüksége, koppintson ide."</string>
     <string name="app_info" msgid="6856026610594615344">"Alkalmazásinformáció"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Tovább az internetre"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Ugrás a böngészőbe"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobiladatok"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"A Wi-Fi ki van kapcsolva"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Beállítások"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Értem"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"SysUI-memória-kiírás"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"A(z) <xliff:g id="APP">%1$s</xliff:g> használja a következőket: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Több alkalmazás használja a következőket: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Megnyitás"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Mégse"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Beállítás"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"A(z) <xliff:g id="APP">%1$s</xliff:g> az elmúlt <xliff:g id="TIME">%3$d</xliff:g> percben használta a következőt: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"A(z) <xliff:g id="APPS">%1$s</xliff:g> használja a következőt: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"A(z) <xliff:g id="APP">%1$s</xliff:g> használja a következőt: <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"helyadatok"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index c1ee1d7..da36e62 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Փորձեք նորից"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Չհաջողվեց պահել սքրինշոթը անբավարար հիշողության պատճառով"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում սքրինշոթի ստացումը"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Էկրանի տեսագրում"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Էկրանի տեսագրման աշխատաշրջանի ընթացիկ ծանուցում"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Սկսել տեսագրումը"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Ձայնագրել ուղեկցող ձայները"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Ցույց տալ հպումները"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Կանգնեցնել"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Դադարեցնել"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Վերսկսել"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Չեղարկել"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Կիսվել"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Ջնջել"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Էկրանի տեսագրումը չեղարկվեց"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Էկրանի տեսագրությունը պահվեց։ Հպեք՝ դիտելու համար:"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Էկրանի տեսագրությունը ջնջվեց"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Չհաջողվեց ջնջել տեսագրությունը"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Չհաջողվեց ստանալ անհրաժեշտ թույլտվությունները"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ֆայլերի փոխանցման ընտրանքներ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Միացնել որպես մեդիա նվագարկիչ (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Միացնել որպես ֆոտոխցիկ (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Ծանուցումներ"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Դուք այլևս չեք ստանա այս ծանուցումները"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Այս ծանուցումները կծալվեն:"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Դուք սովորաբար փակում եք այս ծանուցումները: \nՇարունակե՞լ ցուցադրել դրանք:"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Ցուցադրե՞լ այս ծանուցումները։"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Չցուցադրել ծանուցումներ"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Ցուցադրել"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Ծալել"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Ցուցադրե՞լ ծանուցումներ այս հավելվածից։"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Այս ծանուցումները հնարավոր չէ անջատել"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Այս հավելվածն օգտագործում է տեսախցիկը:"</string>
     <string name="appops_microphone" msgid="741508267659494555">"Այս հավելվածն օգտագործում է խոսափողը:"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Այս հավելվածը ցուցադրվում է մյուս հավելվածների վրայից:"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Ցույց տալ տոկոսը լիցքավորելու ժամանակ (կանխադրված է)"</item>
     <item msgid="3327323682209964956">"Ցույց չտալ այս պատկերակը"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Ցուցադրել ցածր առաջնահերթության ծանուցումների պատկերակները"</string>
     <string name="other" msgid="4060683095962566764">"Այլ"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Տրոհված էկրանի բաժանիչ"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Ձախ էկրանը՝ լիաէկրան"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Հավելվածը բացվել է առանց տեղադրման։"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Հավելվածը բացվել է առանց տեղադրման։ Հպեք՝ ավելին իմանալու համար։"</string>
     <string name="app_info" msgid="6856026610594615344">"Հավելվածի տվյալներ"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Բացեք համացանցում"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Անցնել դիտարկիչ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Բջջային ինտերնետ"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi-ն անջատված է"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Կարգավորումներ"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Եղավ"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> հավելվածն օգտագործում է ձեր <xliff:g id="TYPES_LIST">%2$s</xliff:g>:"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Հավելվածներն օգտագործում են ձեր <xliff:g id="TYPES_LIST">%s</xliff:g>:"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Բացել հավելվածը"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Չեղարկել"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Փակել"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Պարամետրեր"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> հավելվածն օգտագործում է ձեր <xliff:g id="TYPE">%2$s</xliff:g> վերջին <xliff:g id="TIME">%3$d</xliff:g> րոպեի ընթացքում"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> հավելվածներն օգտագործում են ձեր <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> հավելվածն օգտագործում է ձեր <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"տեսախցիկը"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"վայրը"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"խոսափողը"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 1cd4d30..bb0a725 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Coba ambil screenshot lagi"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Tidak dapat menyimpan screenshot karena ruang penyimpanan terbatas"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Mengambil screenshot tidak diizinkan oleh aplikasi atau organisasi"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Rekaman Layar"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Notifikasi yang sedang berjalan untuk sesi rekaman layar"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Mulai Merekam"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Rekam voiceover"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Tampilkan sentuhan"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Stop"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Jeda"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Lanjutkan"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Batal"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Bagikan"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Hapus"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Rekaman layar dibatalkan"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Rekaman layar disimpan, tap untuk melihat"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Rekaman layar dihapus"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Error saat menghapus rekaman layar"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Gagal mendapatkan izin"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opsi transfer file USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Pasang sebagai pemutar media (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Pasang sebagai kamera (PTP)"</string>
@@ -287,7 +303,7 @@
     <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Lokasi Nonaktif"</string>
     <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Perangkat media"</string>
     <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
-    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Telepon urgen saja"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Panggilan Darurat Saja"</string>
     <string name="quick_settings_settings_label" msgid="5326556592578065401">"Setelan"</string>
     <string name="quick_settings_time_label" msgid="4635969182239736408">"Waktu"</string>
     <string name="quick_settings_user_label" msgid="5238995632130897840">"Saya"</string>
@@ -582,14 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifikasi"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Anda tidak akan melihat notifikasi ini lagi"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Notifikasi ini akan diperkecil"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"Notifikasi ini akan ditampilkan tanpa suara"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Notifikasi ini akan mengingatkan Anda"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Anda biasanya menutup notifikasi ini. \nTerus tampilkan?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Terus tampilkan notifikasi ini?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Hentikan notifikasi"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Terus tampilkan"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Perkecil"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Tampilkan tanpa suara"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Tampilkan dan ingatkan"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Terus tampilkan notifikasi dari aplikasi ini?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Notifikasi ini tidak dapat dinonaktifkan"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"melalui <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Aplikasi ini sedang menggunakan kamera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Aplikasi ini sedang menggunakan mikrofon."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Aplikasi ini ditampilkan di atas aplikasi lain di layar."</string>
@@ -804,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Aplikasi dapat dibuka tanpa perlu diinstal."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Aplikasi dapat dibuka tanpa perlu diinstal. Tap untuk mempelajari lebih lanjut."</string>
     <string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Buka di web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Buka browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Data seluler"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi nonaktif"</string>
@@ -836,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Setelan"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Hapus Heap SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> menggunakan <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplikasi menggunakan <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Buka apl"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Batal"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Oke"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Setelan"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> menggunakan <xliff:g id="TYPE">%2$s</xliff:g> selama <xliff:g id="TIME">%3$d</xliff:g> menit terakhir"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> menggunakan <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> menggunakan <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"lokasi"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 92d86ae..3d01b94 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Prófaðu að taka skjámynd aftur"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Ekki tókst að vista skjámynd vegna takmarkaðs geymslupláss"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Forritið eða fyrirtækið þitt leyfir ekki skjámyndatöku"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Skjáupptaka"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Áframhaldandi tilkynning fyrir skjáupptökulotu"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Hefja upptöku"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Taka upp talsetningu"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Sýna snertingar"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Stöðva"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Hlé"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Halda áfram"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Hætta við"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Deila"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Eyða"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Hætt við skjáupptöku"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Skjáupptaka vistuð, ýttu til að skoða"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Skjáupptöku eytt"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Villa við að eyða skjáupptöku"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Ekki tókst að fá heimildir"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Valkostir USB-skráaflutnings"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Tengja sem efnisspilara (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Tengja sem myndavél (PTP)"</string>
@@ -582,14 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Tilkynningar"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Þú munt ekki sjá þessar tilkynningar aftur"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Þessar tilkynningar verða faldar"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Þú hunsar yfirleitt þessar tilkynningar. \nViltu halda áfram að fá þær?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Sýna áfram þessar tilkynningar?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Stöðva tilkynningar"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Sýna áfram"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minnka"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Sýna áfram tilkynningar frá þessu forriti?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ekki er hægt að slökkva á þessum tilkynningum"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"með <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Þetta forrit er að nota myndavélina."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Þetta forrit er að nota hljóðnemann."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Þetta forrit er að birta efni yfir öðrum forritum á skjánum þínum."</string>
@@ -804,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Forrit opnað án þess að vera uppsett."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Forrit opnað án þess að vera uppsett. Ýttu til að fá frekari upplýsingar."</string>
     <string name="app_info" msgid="6856026610594615344">"Forritsupplýsingar"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Fara á vefinn"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Opna vafra"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Farsímagögn"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Slökkt á Wi-Fi"</string>
@@ -836,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Stillingar"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Ég skil"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Vista SysUI-gögn"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> er að nota <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Forrit eru að nota <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Opna forr."</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Hætta við"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Í lagi"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Stillingar"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> hefur verið að nota <xliff:g id="TYPE">%2$s</xliff:g> í <xliff:g id="TIME">%3$d</xliff:g> mín."</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> er að nota <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> er að nota <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"myndavél"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"staðsetning"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"hljóðnemi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 3cac6c9..b1f9230 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Riprova ad acquisire lo screenshot"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Impossibile salvare lo screenshot a causa dello spazio di archiviazione limitato"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"L\'acquisizione di screenshot non è consentita dall\'app o dall\'organizzazione"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Registrazione dello schermo"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Notifica costante per una sessione di registrazione dello schermo"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Avvia registrazione"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Registra voce fuori campo"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Mostra tocchi"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Interrompi"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pausa"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Riprendi"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Annulla"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Condividi"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"CANC"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Registrazione dello schermo annullata"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Registrazione dello schermo salvata. Tocca per visualizzarla."</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Registrazione dello schermo eliminata"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Errore durante l\'eliminazione della registrazione dello schermo"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Impossibile ottenere le autorizzazioni"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opzioni trasferimento file USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Monta come lettore multimediale (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Monta come videocamera (PTP)"</string>
@@ -259,7 +275,7 @@
     <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"Ora lo schermo è bloccato nell\'orientamento orizzontale."</string>
     <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"Ora lo schermo è bloccato nell\'orientamento verticale."</string>
     <string name="dessert_case" msgid="1295161776223959221">"Vetrina di dolci"</string>
-    <string name="start_dreams" msgid="5640361424498338327">"Screensaver"</string>
+    <string name="start_dreams" msgid="5640361424498338327">"Salvaschermo"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
     <string name="quick_settings_header_onboarding_text" msgid="8030309023792936283">"Tocca e tieni premuta ciascuna icona per visualizzare altre opzioni"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Non disturbare"</string>
@@ -582,14 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notifiche"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Non vedrai più queste notifiche"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Le notifiche verranno ridotte a icona"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"Queste notifiche verranno mostrate in modalità silenziosa"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Queste notifiche ti avviseranno"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"In genere ignori queste notifiche. \nVuoi continuare a riceverle?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Continuare a ricevere queste notifiche?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Interrompi la ricezione di notifiche"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Continua a mostrare"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Riduci a icona"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Mostra silenziosamente"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Mostra e avvisa"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuare a ricevere notifiche da questa app?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Queste notifiche non possono essere disattivate"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"tramite <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Questa app sta utilizzando la fotocamera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Questa app sta utilizzando il microfono."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Questa app è visualizzata sopra altre app sullo schermo."</string>
@@ -804,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"App aperta senza essere stata installata."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"App aperta senza essere stata installata. Tocca per avere ulteriori informazioni."</string>
     <string name="app_info" msgid="6856026610594615344">"Informazioni app"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Vai sul Web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Vai al browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Dati mobili"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi disattivato"</string>
@@ -836,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Impostazioni"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Esegui dump heap SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"L\'app <xliff:g id="APP">%1$s</xliff:g> sta usando <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Le app stanno usando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Apri app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Annulla"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Impostazioni"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"L\'app <xliff:g id="APP">%1$s</xliff:g> sta usando <xliff:g id="TYPE">%2$s</xliff:g> da <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Le app <xliff:g id="APPS">%1$s</xliff:g> stanno usando <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"L\'app <xliff:g id="APP">%1$s</xliff:g> sta usando <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"Fotocamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"luogo"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"un microfono"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index a65b917..70ab947 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"יש לנסות שוב לבצע צילום מסך"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"לא היה מספיק מקום לשמור את צילום המסך"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"האפליקציה או הארגון שלך אינם מתירים ליצור צילומי מסך"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"הקלטת מסך"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"התראה מתמשכת לסשן הקלטת מסך"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"הפעלת ההקלטה"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"‏הקלטת voiceover"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"הצגת הקשות"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"עצירה"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"השהיה"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"המשך"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"ביטול"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"שיתוף"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"מחיקה"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"הקלטת המסך בוטלה"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"הקלטת המסך נשמרה, יש להקיש כדי להציג"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"הקלטת המסך נמחקה"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"שגיאה במחיקת הקלטת המסך"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"קבלת ההרשאות נכשלה"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏אפשרויות העברת קבצים ב-USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏טען כנגן מדיה (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"‏טען כמצלמה (PTP)"</string>
@@ -243,7 +259,7 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"‏מחפש GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"‏מיקום מוגדר על ידי GPS"</string>
     <string name="accessibility_location_active" msgid="2427290146138169014">"בקשות מיקום פעילות"</string>
-    <string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההודעות."</string>
+    <string name="accessibility_clear_all" msgid="5235938559247164925">"הסרת כל ההתראות."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="notification_group_overflow_indicator_ambient" msgid="879560382990377886">"<xliff:g id="NOTIFICATION_TITLE">%1$s</xliff:g>, +<xliff:g id="OVERFLOW">%2$s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
@@ -588,15 +604,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"התראות"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"ההודעות האלה לא יוצגו לך יותר"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"ההודעות האלה ימוזערו"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"הודעות אלה יוצגו ללא צליל"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"הודעות אלה יישלחו כהתראה"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"הודעות אלה בדרך כלל נדחות על ידיך. \nלהמשיך להציג אותן?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"שנמשיך להציג לך את ההודעות האלה?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"לא, אל תמשיכו"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"כן, המשיכו"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"מזעור"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"הצגה ללא צליל"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"הצגה ושליחת התראה"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"שנמשיך להציג לך הודעות מהאפליקציה הזאת?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"לא ניתן לכבות את ההודעות האלה"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"האפליקציה הזו משתמשת במצלמה."</string>
     <string name="appops_microphone" msgid="741508267659494555">"האפליקציה הזו משתמשת במיקרופון."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"האפליקציה הזו מוצגת מעל אפליקציות אחרות במסך."</string>
@@ -735,8 +753,7 @@
     <item msgid="2139628951880142927">"הצג באחוזים בזמן טעינה (ברירת מחדל)"</item>
     <item msgid="3327323682209964956">"אל תציג את הסמל הזה"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"הצגת סמלי התראות בעדיפות נמוכה"</string>
     <string name="other" msgid="4060683095962566764">"אחר"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"מחלק מסך מפוצל"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"מסך שמאלי מלא"</string>
@@ -816,7 +833,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"האפליקציה נפתחת בלי התקנה."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"האפליקציה נפתחת בלי התקנה. אפשר להקיש כדי לקבל מידע נוסף."</string>
     <string name="app_info" msgid="6856026610594615344">"פרטי אפליקציה"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"התחבר לאינטרנט"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"מעבר אל הדפדפן"</string>
     <string name="mobile_data" msgid="7094582042819250762">"נתונים סלולריים"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> ‏— <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"‏Wi-Fi כבוי"</string>
@@ -848,4 +865,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"הגדרות"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"הבנתי"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"‏ערימת Dump SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> משתמשת ב<xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"אפליקציות משתמשות ב<xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"לאפליקציה"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"ביטול"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"אישור"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"הגדרות"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> משתמשת ב<xliff:g id="TYPE">%2$s</xliff:g> ב-<xliff:g id="TIME">%3$d</xliff:g> הדקות האחרונות"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> משתמשות ב<xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> משתמשת ב<xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"מצלמה"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"מיקום"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"מיקרופון"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 6617fdd..bd5fb37 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"スクリーンショットを撮り直してください"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"空き容量が足りないため、スクリーンショットを保存できません"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"スクリーンショットの作成はアプリまたは組織で許可されていません"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"画面の録画"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"画面の録画セッション中の通知"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"録画を開始"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"ナレーションの録音"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"タップの表示"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"停止"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"一時停止"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"再開"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"キャンセル"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"共有"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"削除"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"画面の録画をキャンセルしました"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"画面の録画を保存しました。タップで表示できます"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"画面の録画を削除しました"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"画面の録画の削除中にエラーが発生しました"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"権限を取得できませんでした"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USBファイル転送オプション"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"メディアプレーヤー(MTP)としてマウント"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"カメラ(PTP)としてマウント"</string>
@@ -198,9 +214,9 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"機内モードをONにしました。"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="2960643943620637020">"サイレント"</string>
     <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3357131899365865386">"アラームのみ"</string>
-    <string name="accessibility_quick_settings_dnd" msgid="6607873236717185815">"マナーモード"</string>
-    <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"マナーモードを OFF にしました。"</string>
-    <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"マナーモードを ON にしました。"</string>
+    <string name="accessibility_quick_settings_dnd" msgid="6607873236717185815">"サイレント モード"</string>
+    <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"サイレント モードを OFF にしました。"</string>
+    <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"サイレント モードを ON にしました。"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="6341675755803320038">"Bluetooth"</string>
     <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"BluetoothがOFFです。"</string>
     <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"BluetoothがONです。"</string>
@@ -262,7 +278,7 @@
     <string name="start_dreams" msgid="5640361424498338327">"スクリーン セーバー"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"イーサネット"</string>
     <string name="quick_settings_header_onboarding_text" msgid="8030309023792936283">"アイコンを押し続けると、その他の項目が表示されます"</string>
-    <string name="quick_settings_dnd_label" msgid="8735855737575028208">"マナーモード"</string>
+    <string name="quick_settings_dnd_label" msgid="8735855737575028208">"サイレント モード"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"優先する通知のみ"</string>
     <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"アラームのみ"</string>
     <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"サイレント"</string>
@@ -415,7 +431,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"次回から表示しない"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"すべて消去"</string>
     <string name="manage_notifications_text" msgid="2386728145475108753">"管理"</string>
-    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"マナーモードにより通知は一時停止中です"</string>
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"サイレント モードにより通知は一時停止中です"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"今すぐ開始"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"通知はありません"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"プロファイルが監視されている可能性があります"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"今後、この通知は表示されません"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"通知を最小化します"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"通常、この通知はスワイプして非表示にしています。\n今後も表示しますか?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"この通知を今後も表示しますか?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"通知を表示しない"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"今後も表示する"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"最小化"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"このアプリからの通知を今後も表示しますか?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"この通知を OFF にすることはできません"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"このアプリはカメラを使用しています。"</string>
     <string name="appops_microphone" msgid="741508267659494555">"このアプリはマイクを使用しています。"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"このアプリは画面上で他のアプリの上に重ねて表示されます。"</string>
@@ -668,9 +690,9 @@
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"カレンダー"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"音量調節を表示"</string>
-    <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"マナーモード"</string>
+    <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"サイレント モード"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"音量ボタンのショートカット"</string>
-    <string name="volume_up_silent" msgid="7141255269783588286">"音量上げボタンでマナーモードを OFF にする"</string>
+    <string name="volume_up_silent" msgid="7141255269783588286">"音量上げボタンでサイレント モードを OFF にする"</string>
     <string name="battery" msgid="7498329822413202973">"電池"</string>
     <string name="clock" msgid="7416090374234785905">"時計"</string>
     <string name="headset" msgid="4534219457597457353">"ヘッドセット"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"変更時に割合を表示(デフォルト)"</item>
     <item msgid="3327323682209964956">"このアイコンを表示しない"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"優先度の低い通知アイコンを表示"</string>
     <string name="other" msgid="4060683095962566764">"その他"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"分割画面の分割線"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"左全画面"</string>
@@ -806,15 +827,15 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"アプリをインストールせずに開きました。"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"アプリをインストールせずに開きました。詳細を見るにはタップしてください。"</string>
     <string name="app_info" msgid="6856026610594615344">"アプリ情報"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ウェブページを開く"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ブラウザに移動"</string>
     <string name="mobile_data" msgid="7094582042819250762">"モバイルデータ"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi は OFF です"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Bluetooth は OFF です"</string>
-    <string name="dnd_is_off" msgid="6167780215212497572">"マナーモードは OFF です"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="862559028345233052">"マナーモードが自動ルール(<xliff:g id="ID_1">%s</xliff:g>)によって ON になりました。"</string>
-    <string name="qs_dnd_prompt_app" msgid="7978037419334156034">"マナーモードがアプリ(<xliff:g id="ID_1">%s</xliff:g>)によって ON になりました。"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="2599343675391111951">"マナーモードが自動ルールまたはアプリによって ON になりました。"</string>
+    <string name="dnd_is_off" msgid="6167780215212497572">"サイレント モードは OFF です"</string>
+    <string name="qs_dnd_prompt_auto_rule" msgid="862559028345233052">"サイレント モードが自動ルール(<xliff:g id="ID_1">%s</xliff:g>)によって ON になりました。"</string>
+    <string name="qs_dnd_prompt_app" msgid="7978037419334156034">"サイレント モードがアプリ(<xliff:g id="ID_1">%s</xliff:g>)によって ON になりました。"</string>
+    <string name="qs_dnd_prompt_auto_rule_app" msgid="2599343675391111951">"サイレント モードが自動ルールまたはアプリによって ON になりました。"</string>
     <string name="qs_dnd_until" msgid="3469471136280079874">"終了時間: <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"設定を維持"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"設定を変更"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"設定"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"SysUI ヒープのダンプ"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g>は<xliff:g id="TYPES_LIST">%2$s</xliff:g>を使用しています。"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"アプリは<xliff:g id="TYPES_LIST">%s</xliff:g>を使用しています。"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"アプリを開く"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"キャンセル"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"設定"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g>は過去 <xliff:g id="TIME">%3$d</xliff:g> 分間に<xliff:g id="TYPE">%2$s</xliff:g>を使用しています"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g>は<xliff:g id="TYPE">%2$s</xliff:g>を使用しています"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g>は<xliff:g id="TYPES_LIST">%2$s</xliff:g>を使用しています"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"カメラ"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"現在地情報"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"マイク"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 359e689..5e2454c 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"ხელახლა ცადეთ ეკრანის ანაბეჭდის გაკეთება"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა შეზღუდული მეხსიერების გამო"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ეკრანის ანაბეჭდების შექმნა არ არის ნებადართული აპის ან თქვენი ორგანიზაციის მიერ"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"ეკრანის ჩაწერა"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"უწყვეტი შეტყობინება ეკრანის ჩაწერის სესიისთვის"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"ჩაწერის დაწყება"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"ხმის ჩაწერა"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"შეხებების ჩვენება"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"შეწყვეტა"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"პაუზა"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"გაგრძელება"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"გაუქმება"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"გაზიარება"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"წაშლა"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"ეკრანის ჩაწერა გაუქმდა"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"ეკრანის ჩანაწერი შენახულია, შეეხეთ სანახავად"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"ეკრანის ჩანაწერი წაიშალა"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"ეკრანის ჩანაწერის წაშლისას წარმოიშვა შეცდომა"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"ნებართვების მიღება ვერ მოხერხდა"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ფაილის ტრანსფერის პარამეტრები"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"მედია-საკრავად (MTP) ჩართვა"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"მიუერთეთ როგორც კამერა (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"შეტყობინებები"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"ამ შეტყობინებებს აღარ დაინახავთ"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"შეტყობინებები ჩაიკეცება"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"როგორც წესი, თქვენ ასეთ შეტყობინებებს ხურავთ. \nგსურთ მათი ჩვენების გაგრძელება?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"გაგრძელდეს ამ შეტყობინებათა ჩვენება?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"შეტყობინებების შეწყვეტა"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"ჩვენების გაგრძელება"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"ჩაკეცვა"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"გაგრძელდეს შეტყობინებათა ჩვენება ამ აპიდან?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"ამ შეტყობინებათა გამორთვა ვერ მოხერხდება"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"ეს აპი იყენებს კამერას."</string>
     <string name="appops_microphone" msgid="741508267659494555">"ეს აპი იყენებს მიკროფონს."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"ეს აპი თქვენს ეკრანზე ფარავს სხვა აპებს."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"პროცენტულობის დატენვისას ჩვენება (ნაგულისხმევი)"</item>
     <item msgid="3327323682209964956">"აღარ მაჩვენო ეს ხატულა"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"დაბალი პრიორიტეტის მქონე შეტყობინებების ხატულების ჩვენება"</string>
     <string name="other" msgid="4060683095962566764">"სხვა"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"გაყოფილი ეკრანის რეჟიმის გამყოფი"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"მარცხენა ნაწილის სრულ ეკრანზე გაშლა"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"აპი გაიხსნა ინსტალაციის გარეშე."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"აპი გაიხსნა ინსტალაციის გარეშე. შეეხეთ მეტის გასაგებად."</string>
     <string name="app_info" msgid="6856026610594615344">"აპის შესახებ"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ვებზე გადასვლა"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ბრაუზერზე გადასვლა"</string>
     <string name="mobile_data" msgid="7094582042819250762">"მობილური ინტერნეტი"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi გამორთულია"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"პარამეტრები"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"გასაგებია"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"SysUI გროვის გამოტანა"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g>-ის მიერ გამოიყენება თქვენი <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"აპლიკაციების მიერ გამოიყენება თქვენი <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"აპის გახსნა"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"გაუქმება"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"კარგი"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"პარამეტრები"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g>-ის მიერ გამოიყენება თქვენი <xliff:g id="TYPE">%2$s</xliff:g> ბოლო <xliff:g id="TIME">%3$d</xliff:g> წუთის განმავლობაში"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g>-ის მიერ გამოიყენება თქვენი <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g>-ის მიერ გამოიყენება თქვენი <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"კამერა"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"მდებარეობა"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"მიკროფონი"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 6598bf0..f990be8 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Қайта скриншот жасап көріңіз"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Жадтағы шектеулі бос орынға байланысты скриншот сақталмайды"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Қолданба немесе ұйым скриншоттар түсіруге рұқсат етпейді"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Экранды бейнеге жазу"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Экранды бейнеге жазудың ағымдағы хабарландыруы"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Жазуды бастау"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Кадр сыртындағы дыбысты жазу"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Түрту әрекеттерін көрсету"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Тоқтату"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Тоқтата тұру"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Жалғастыру"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Бас тарту"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Бөлісу"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Жою"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Экранды бейнеге жазудан бас тартылды"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Экран бейне жазбасы сақталды, көру үшін түртіңіз"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Экран бейне жазбасы жойылды"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Экран бейне жазбасын жою кезінде қате кетті"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Рұқсаттар алынбады"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB файлын жіберу опциялары"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа ойнатқыш (MTP) ретінде қосыңыз"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Камера ретінде (PTP) қосыңыз"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Хабарландырулар"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Хабарландырулар бұдан былай көрсетілмейді"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Хабарландырулар жасырылады"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Әдетте хабарландыруларды көрмейсіз. \nОлар көрсетілсін бе?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Хабарландырулар көрсетілсін бе?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Хабарландыруларға тыйым салу"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Көрсету"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Жасыру"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Осы қолданбаның хабарландырулары көрсетілсін бе?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Хабарландыруларды өшіру мүмкін емес"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Бұл қолданба камераны пайдалануда."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Бұл қолданба микрофонды пайдалануда."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Бұл қолданба экранда басқа қолданбалардың үстінен көрсетіліп тұр."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Зарядтау кезінде пайызды көрсету (әдепкі)"</item>
     <item msgid="3327323682209964956">"Бұл белгішені көрсетпеу"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Маңызды емес хабарландыру белгішелерін көрсету"</string>
     <string name="other" msgid="4060683095962566764">"Басқа"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Бөлінген экран бөлгіші"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Сол жағын толық экранға шығару"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Қолданба орнатылмай-ақ ашылды."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Қолданба орнатылмай-ақ ашылды. Толығырақ мәлімет алу үшін түртіңіз."</string>
     <string name="app_info" msgid="6856026610594615344">"Қолданба ақпараты"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Вебке өту"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Браузерге өту"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобильдік деректер"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi өшірулі"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Параметрлер"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Түсінікті"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> қолданбасында <xliff:g id="TYPES_LIST">%2$s</xliff:g> пайдалануда."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Қолданбаларда <xliff:g id="TYPES_LIST">%s</xliff:g> пайдаланылуда."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Ашу"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Бас тарту"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Жарайды"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Параметр"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> қолданбасында <xliff:g id="TIME">%3$d</xliff:g> минут бойы <xliff:g id="TYPE">%2$s</xliff:g> пайдаланылуда"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> қолданбасында <xliff:g id="TYPE">%2$s</xliff:g> пайдаланылуда"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> қолданбасында <xliff:g id="TYPES_LIST">%2$s</xliff:g> пайдаланылуда"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"камера"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"геодерек"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"микрофон"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 8545ad6..6c584ad 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"សាកល្បង​ថតរូបថត​អេក្រង់​ម្តងទៀត"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"មិនអាច​រក្សាទុក​រូបថតអេក្រង់​បានទេ ​ដោយសារ​ទំហំផ្ទុក​មានកម្រិតទាប"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ការថត​រូបអេក្រង់​មិនត្រូវ​បាន​អនុញ្ញាត​ដោយ​កម្មវិធី​នេះ ឬ​ស្ថាប័ន​របស់អ្នក"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"ការថត​សកម្មភាព​អេក្រង់"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"ការជូនដំណឹង​ដែល​កំពុង​ដំណើរការ​សម្រាប់​រយៈពេលប្រើ​ការថត​សកម្មភាព​អេក្រង់"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"ចាប់​ផ្តើមថត"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"ថត​ការបញ្ចូល​សំឡេង"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"បង្ហាញការចុច"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"ឈប់"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"ផ្អាក"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"បន្ត"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"បោះបង់"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"ចែករំលែក"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"លុប"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"បាន​បោះបង់​ការថត​សកម្មភាព​អេក្រង់"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"បានរក្សាទុក​ការថត​សកម្មភាព​អេក្រង់។ សូមចុច​ដើម្បី​មើល"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"បានលុប​ការថត​សកម្មភាព​អេក្រង់"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"មានបញ្ហា​ក្នុងការ​លុបការថត​សកម្មភាព​អេក្រង់"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"មិនអាច​ទទួលបាន​ការអនុញ្ញាត​ទេ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"ជម្រើស​ផ្ទេរ​ឯកសារ​តាម​យូអេសប៊ី"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ភ្ជាប់​ជា​កម្មវិធី​ចាក់​មេឌៀ (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ភ្ជាប់​ជា​ម៉ាស៊ីន​ថត (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ការ​ជូនដំណឹង"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"អ្នក​នឹង​មិនឃើញ​ការជូនដំណឹង​ទាំងនេះ​ទៀតទេ"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"ការជូនដំណឹង​ទាំងនេះ​នឹងត្រូវបាន​បង្រួម"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"ជាធម្មតា​អ្នក​ច្រានចោល​ការ​ជូន​ដំណឹង​ទាំង​នេះ។ \nបន្ត​បង្ហាញ​ពួកវា​ទៀត​ដែរ​ទេ?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"បន្ត​បង្ហាញ​ការជូនដំណឹង​ទាំងនេះ?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"បញ្ឈប់​ការជូនដំណឹង"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"បន្ត​បង្ហាញ"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"បង្រួម"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"បន្ត​បង្ហាញ​ការជូនដំណឹង​ពីកម្មវិធីនេះ?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"​មិនអាច​បិទការជូនដំណឹង​ទាំងនេះបានទេ"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"កម្មវិធីនេះ​កំពុងប្រើ​កាមេរ៉ា។"</string>
     <string name="appops_microphone" msgid="741508267659494555">"កម្មវិធីនេះ​កំពុងប្រើ​មីក្រូហ្វូន។"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"កម្មវិធីនេះ​កំពុងបង្ហាញ​ពីលើកម្មវិធី​ផ្សេងទៀត​នៅលើអេក្រង់​របស់អ្នក។"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"បង្ហាញភាគរយនៅពេលសាកថ្ម (លំនាំដើម)"</item>
     <item msgid="3327323682209964956">"កុំបង្ហាញរូបតំណាងនេះ"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"បង្ហាញ​រូប​ការជូនដំណឹង​ដែលមានអាទិភាពទាប"</string>
     <string name="other" msgid="4060683095962566764">"ផ្សេងៗ"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"កម្មវិធីចែកអេក្រង់បំបែក"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"អេក្រង់ពេញខាងឆ្វេង"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"កម្មវិធីត្រូវ​បាន​បើក​ដោយ​មិនចាំបាច់ដំឡើង។"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"កម្មវិធីត្រូវ​បាន​បើក​ដោយ​មិនចាំបាច់ដំឡើង។ ចុច​ដើម្បី​ស្វែងយល់បន្ថែម។"</string>
     <string name="app_info" msgid="6856026610594615344">"ព័ត៌មាន​កម្មវិធី"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ចូលទៅកាន់បណ្តាញ"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ចូល​ទៅ​កម្មវិធី​រុករក​តាម​អ៊ីនធឺណិត"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ទិន្នន័យ​ទូរសព្ទចល័ត"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi បាន​បិទ"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"ការកំណត់"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"យល់ហើយ"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"ចម្លង SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> កំពុងប្រើ <xliff:g id="TYPES_LIST">%2$s</xliff:g> របស់អ្នក។"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"កម្មវិធី​កំពុងប្រើ <xliff:g id="TYPES_LIST">%s</xliff:g> របស់អ្នក។"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"បើក​កម្មវិធី"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"បោះបង់"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"យល់ព្រម"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"ការកំណត់"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> កំពុង​ប្រើ <xliff:g id="TYPE">%2$s</xliff:g> របស់អ្នករយៈពេល <xliff:g id="TIME">%3$d</xliff:g> នាទីចុងក្រោយ"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> កំពុង​ប្រើ <xliff:g id="TYPE">%2$s</xliff:g> របស់អ្នក"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> កំពុង​ប្រើ <xliff:g id="TYPES_LIST">%2$s</xliff:g> របស់អ្នក"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"កាមេរ៉ា"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"ទីតាំង"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"មីក្រូហ្វូន"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index ccbb31e..9269026 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ಪುನಃ ತೆಗೆದುಕೊಳ್ಳಲು ಪ್ರಯತ್ನಿಸಿ"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳದ ಕಾರಣದಿಂದಾಗಿ ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ಸಂಸ್ಥೆಯು ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ಗಳನ್ನು ತೆಗೆಯುವುದನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೆಶನ್‌ಗಾಗಿ ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಅಧಿಸೂಚನೆ"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"ರೆಕಾರ್ಡಿಂಗ್ ಆರಂಭಿಸಿ"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"voiceover ಅನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"ಟ್ಯಾಪ್‌ಗಳನ್ನು ತೋರಿಸಿ"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"ನಿಲ್ಲಿಸಿ"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"ವಿರಾಮಗೊಳಿಸಿ"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"ಮುಂದುವರಿಸಿ"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"ರದ್ದುಮಾಡಿ"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"ಹಂಚಿಕೊಳ್ಳಿ"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"ಅಳಿಸಿ"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಅನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಅನ್ನು ಉಳಿಸಲಾಗಿದೆ, ವೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಅಳಿಸಲಾಗಿದೆ"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಅಳಿಸುವಾಗ ದೋಷ ಕಂಡುಬಂದಿದೆ"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"ಅನುಮತಿಗಳನ್ನು ಪಡೆಯುವಲ್ಲಿ ವಿಫಲವಾಗಿದೆ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ಫೈಲ್ ವರ್ಗಾವಣೆ ಆಯ್ಕೆಗಳು"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ಮೀಡಿಯಾ ಪ್ಲೇಯರ್ ರೂಪದಲ್ಲಿ ಅಳವಡಿಸಿ (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ಕ್ಯಾಮರಾ ರೂಪದಲ್ಲಿ ಅಳವಡಿಸಿ (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ಅಧಿಸೂಚನೆಗಳು"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"ನೀವು ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಇನ್ನು ಮುಂದೆ ನೋಡುವುದಿಲ್ಲ"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಕಿರಿದುಗೊಳಿಸಲಾಗುತ್ತದೆ"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"ನೀವು ಸಾಮಾನ್ಯವಾಗಿ ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ವಜಾಗೊಳಿಸಿದ್ದೀರಿ. \nಅವುಗಳನ್ನು ತೋರಿಸುತ್ತಲೇ ಇರಬೇಕೆ?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸುತ್ತಲೇ ಇರಬೇಕೆ?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"ಅಧಿಸೂಚನೆಗಳನ್ನು ನಿಲ್ಲಿಸಿ"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"ತೋರಿಸುತ್ತಲಿರಿ"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"ಕಿರಿದುಗೊಳಿಸಿ"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"ಈ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೋರಿಸುತ್ತಲೇ ಇರಬೇಕೆ?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"ಈ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆಫ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುತ್ತಿದೆ."</string>
     <string name="appops_microphone" msgid="741508267659494555">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಮೈಕ್ರೊಫೋನ್ ಅನ್ನು ಬಳಸುತ್ತಿದೆ."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ಇತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಮೇಲಿಂದ ಪ್ರದರ್ಶಿಸುತ್ತಿದೆ."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"ಚಾರ್ಜ್‌ ಮಾಡುವಾಗ ಪ್ರತಿಶತವನ್ನು ತೋರಿಸು (ಡಿಫಾಲ್ಟ್‌)"</item>
     <item msgid="3327323682209964956">"ಈ ಐಕಾನ್ ತೋರಿಸಬೇಡ"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"ಕಡಿಮೆ-ಆದ್ಯತೆ ಸೂಚನೆಯ ಐಕಾನ್‌ಗಳನ್ನು ತೋರಿಸಿ"</string>
     <string name="other" msgid="4060683095962566764">"ಇತರ"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"ಸ್ಪ್ಲಿಟ್-ಪರದೆ ಡಿವೈಡರ್"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"ಎಡ ಪೂರ್ಣ ಪರದೆ"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡದೆ ಆ್ಯಪ್‌ ತೆರೆಯಲಾಗಿದೆ."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"ಇನ್‌ಸ್ಟಾಲ್‌ ಮಾಡದೆ ಆ್ಯಪ್‌ ತೆರೆಯಲಾಗಿದೆ. ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
     <string name="app_info" msgid="6856026610594615344">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ವೆಬ್‌ಗೆ ಹೋಗಿ"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ಬ್ರೌಸರ್‌ಗೆ ಹೋಗಿ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ಮೊಬೈಲ್ ಡೇಟಾ"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"ವೈ-ಫೈ ಆಫ್ ಆಗಿದೆ"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"ಅರ್ಥವಾಯಿತು"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"SysUI ಹೀಪ್ ಡಂಪ್ ಮಾಡಿ"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"ನಿಮ್ಮ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ಅನ್ನು <xliff:g id="APP">%1$s</xliff:g> ಬಳಸುತ್ತಿದೆ."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"ನಿಮ್ಮ <xliff:g id="TYPES_LIST">%s</xliff:g> ಅನ್ನು ಆ್ಯಪ್‌ಗಳು ಬಳಸುತ್ತಿವೆ."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"ಆ್ಯಪ್ ತೆರೆ"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"ರದ್ದುಮಾಡಿ"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ಸರಿ"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"ಕೊನೆಯ <xliff:g id="TIME">%3$d</xliff:g> ನಿಮಿಷಕ್ಕಾಗಿ ನಿಮ್ಮ <xliff:g id="TYPE">%2$s</xliff:g> ಅನ್ನು <xliff:g id="APP">%1$s</xliff:g> ಬಳಸುತ್ತಿದೆ"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"ನಿಮ್ಮ <xliff:g id="TYPE">%2$s</xliff:g> ಅನ್ನು <xliff:g id="APPS">%1$s</xliff:g> ಬಳಸುತ್ತಿದೆ"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"ನಿಮ್ಮ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ಅನ್ನು <xliff:g id="APP">%1$s</xliff:g> ಬಳಸುತ್ತಿದೆ"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"ಕ್ಯಾಮರಾ"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"ಸ್ಥಳ"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"ಮೈಕ್ರೋಫೋನ್‌"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 716e2f2..b6dda32 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"스크린샷을 다시 찍어 보세요."</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"저장용량이 부족하여 스크린샷을 저장할 수 없습니다"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"앱이나 조직에서 스크린샷 촬영을 허용하지 않습니다."</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"화면 녹화"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"화면 녹화 세션에 관한 지속적인 알림"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"녹화 시작"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"음성 해설 녹음"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"탭한 항목 표시"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"중지"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"일시중지"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"재개"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"취소"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"공유"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"삭제"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"화면 녹화가 취소되었습니다."</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"화면 녹화본이 저장되었습니다. 확인하려면 탭하세요."</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"화면 녹화가 삭제되었습니다."</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"화면 녹화는 삭제하는 중에 오류가 발생했습니다."</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"권한을 확보하지 못했습니다."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 파일 전송 옵션"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"미디어 플레이어로 마운트(MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"카메라로 마운트(PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"알림"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"더 이상 다음의 알림을 받지 않습니다"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"다음 알림이 최소화됩니다."</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"보통 이 알림을 닫았습니다. \n알림을 계속 표시하시겠습니까?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"이 알림을 계속 표시하시겠습니까?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"알림 중지"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"계속 표시하기"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"최소화"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"이 앱의 알림을 계속 표시하시겠습니까?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"이 알림은 끌 수 없습니다"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"앱이 카메라를 사용 중입니다."</string>
     <string name="appops_microphone" msgid="741508267659494555">"앱이 마이크를 사용 중입니다."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"앱이 화면의 다른 앱 위에 표시되고 있습니다."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"충전할 때 퍼센트 표시(기본값)"</item>
     <item msgid="3327323682209964956">"이 아이콘 표시 안함"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"우선순위가 낮은 알림 아이콘 표시"</string>
     <string name="other" msgid="4060683095962566764">"기타"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"화면 분할기"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"왼쪽 화면 전체화면"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"설치 없이 앱이 실행되었습니다."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"설치 없이 앱이 실행되었습니다. 탭하여 자세히 알아보세요."</string>
     <string name="app_info" msgid="6856026610594615344">"앱 정보"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"웹으로 이동"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"브라우저로 이동"</string>
     <string name="mobile_data" msgid="7094582042819250762">"모바일 데이터"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g>, <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi가 사용 중지됨"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"설정"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"확인"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g>이(가) <xliff:g id="TYPES_LIST">%2$s</xliff:g>을(를) 사용 중입니다."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"애플리케이션이 <xliff:g id="TYPES_LIST">%s</xliff:g>을(를) 사용 중입니다."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"앱 열기"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"취소"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"확인"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"설정"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g>이(가) 지난 <xliff:g id="TIME">%3$d</xliff:g>분 동안 <xliff:g id="TYPE">%2$s</xliff:g>을(를) 사용 중입니다."</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g>이(가) <xliff:g id="TYPE">%2$s</xliff:g>을(를) 사용 중입니다."</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g>이(가) <xliff:g id="TYPES_LIST">%2$s</xliff:g>을(를) 사용 중입니다."</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"카메라"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"위치"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"마이크"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 2f49cdb..f4dbcbd 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Скриншотту кайра тартып көрүңүз"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Сактагычта бош орун аз болгондуктан скриншот сакталбай жатат"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Скриншот тартууга колдонмо же ишканаңыз тыюу салган."</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Экранды жаздыруу"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Экранды жаздыруу сеансы боюнча учурдагы билдирме"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Жаздырып баштоо"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Үн коштоону жаздыруу"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Басылган жерди көрсөтүү"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Токтотуу"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Тындыруу"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Улантуу"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Жокко чыгаруу"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Бөлүшүү"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Ооба"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Экранды жаздыруу жокко чыгарылды"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Экранды жаздыруу сакталды, көрүү үчүн таптап коюңуз"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Экранды жаздыруу өчүрүлдү"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Экранды жаздырууну өчүрүүдө ката кетти"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Уруксаттар алынбай калды"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB менен файл өткөрүү мүмкүнчүлүктөрү"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа ойноткуч катары кошуу (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Камера катары кошуу (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Билдирмелер"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Мындан ары бул эскертмелер сизге көрсөтүлбөйт"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Бул эскертмелер кичирейтилет"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Адатта мындай эскертмелерди өткөрүп жибересиз. \nАлар көрсөтүлө берсинби?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Бул эскертмелер көрсөтүлө берсинби?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Эскертмелерди токтотуу"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Көрсөтүлө берсин"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Кичирейтүү"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Бул колдонмонун эскертмелери көрсөтүлө берсинби?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Бул эскертмелерди өчүрүүгө болбойт"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Бул колдонмо камераны колдонууда."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Бул колдонмо микрофонду колдонууда."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Бул колдонмо экрандагы башка терезелердин үстүнөн көрсөтүлүүдө."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Кубаттоо учурунда пайызы көрсөтүлсүн (демейки)"</item>
     <item msgid="3327323682209964956">"Бул сөлөкөт көрсөтүлбөсүн"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Анча маанилүү эмес билдирменин сүрөтчөлөрүн көрсөтүү"</string>
     <string name="other" msgid="4060683095962566764">"Башка"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Экранды бөлгүч"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Сол жактагы экранды толук экран режимине өткөрүү"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Колдонмо орнотулбастан ачылды."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Колдонмо орнотулбастан ачылды. Толугураак маалымат алуу үчүн таптап коюңуз."</string>
     <string name="app_info" msgid="6856026610594615344">"Колдонмо тууралуу"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Интернетке өтүү"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Серепчиге өтүү"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобилдик Интернет"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi өчүк"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Жөндөөлөр"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Түшүндүм"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> төмөнкүлөрдү колдонуп жатат: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Колдонмолор төмөнкүлөрдү пайдаланып жатышат: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Колдн ачуу"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Жок"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Макул"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Жөндөөлөр"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> төмөнкүлөрдү <xliff:g id="TIME">%3$d</xliff:g> мүн. бери колдонуп жатат: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> төмөнкүлөрдү колдонуп жатышат: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> төмөнкүлөрдү колдонуп жатат: <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"камера"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"жайгашкан жер"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"микрофон"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index bb0c6f6..df858f0 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -34,4 +34,5 @@
     <bool name="quick_settings_wide">true</bool>
     <dimen name="qs_detail_margin_top">0dp</dimen>
     <dimen name="qs_paged_tile_layout_padding_bottom">0dp</dimen>
+    <dimen name="ongoing_appops_top_chip_margin">2dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index dd874d5..2a508b3 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"ກະລຸນາລອງຖ່າຍຮູບໜ້າຈໍອີກຄັ້ງ"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້ເນື່ອງຈາກພື້ນທີ່ຈັດເກັບຂໍ້ມູນມີຈຳກັດ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ແອັບ ຫຼື ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ຖ່າຍຮູບໜ້າຈໍ"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"ການບັນທຶກໜ້າຈໍ"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"ການແຈ້ງເຕືອນສຳລັບເຊດຊັນການບັນທຶກໜ້າຈໍໃດໜຶ່ງ"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"ເລີ່ມການບັນທຶກ"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"ບັນທຶກສຽງພາກ"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"ສະແດງການແຕະ"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"ຢຸດ"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"ຢຸດຊົ່ວຄາວ"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"ສືບຕໍ່"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"ຍົກເລີກ"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"ແບ່ງປັນ"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"ລຶບ"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"ຍົກເລີກການບັນທຶກໜ້າຈໍແລ້ວ"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"ຈັດເກັບການບັນທຶກໜ້າຈໍ, ແຕະເພື່ອເບິ່ງ"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"ລຶບການບັນທຶກໜ້າຈໍອອກແລ້ວ"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"ເກີດຄວາມຜິດພາດໃນການລຶບການບັນທຶກໜ້າຈໍ"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"ໂຫຼດສິດອະນຸຍາດບໍ່ສຳເລັດ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ໂຕເລືອກການຍ້າຍໄຟລ໌"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ເຊື່ອມຕໍ່ເປັນ media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ເຊື່ອມຕໍ່ເປັນກ້ອງຖ່າຍຮູບ (PTP)"</string>
@@ -582,15 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ການແຈ້ງເຕືອນ"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"ທ່ານຈະບໍ່ໄດ້ຮັບການແຈ້ງເຕືອນເຫຼົ່ານີ້ອີກຕໍ່ໄປ"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"ການແຈ້ງເຕືອນເຫຼົ່ານີ້ຈະຖືກຫຍໍ້ໄວ້"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"ການແຈ້ງເຕືອນເຫຼົ່ານີ້ຈະສະແດງແບບງຽບໆ"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"ການແຈ້ງເຕືອນເຫຼົ່ານີ້ຈະເຕືອນທ່ານ"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"ໂດຍປົກກະຕິທ່ານປິດການແຈ້ງເຕືອນເຫຼົ່ານີ້ໄວ້. \nສືບຕໍ່ສະແດງພວກມັນບໍ?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"ສະແດງການແຈ້ງເຕືອນເຫຼົ່ານີ້ຕໍ່ໄປບໍ?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"ຢຸດການແຈ້ງເຕືອນ"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"ສະແດງຕໍ່ໄປ"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"ຫຍໍ້"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"ສະແດງແບບງຽບໆ"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"ສະແດງ ແລະ ເຕືອນ"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"ສະແດງການແຈ້ງເຕືອນຈາກແອັບນີ້ຕໍ່ໄປບໍ?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"ບໍ່ສາມາດປິດການແຈ້ງເຕືອນເຫຼົ່ານີ້ໄດ້"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"ແອັບນີ້ກຳລັງໃຊ້ກ້ອງຢູ່."</string>
     <string name="appops_microphone" msgid="741508267659494555">"ແອັບນີ້ກຳລັງໃຊ້ໄມໂຄຣໂຟນຢູ່."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"ແອັບນີ້ກຳລັງສະແດງຜົນບັງແອັບອື່ນຢູ່ໜ້າຈໍຂອງທ່ານ."</string>
@@ -725,8 +743,7 @@
     <item msgid="2139628951880142927">"ສະແດງເປີເຊັນເມື່ອກຳລັງສາກໄຟ (ຄ່າເລີ່ມຕົ້ນ)"</item>
     <item msgid="3327323682209964956">"ຢ່າສະແດງໄອຄອນນີ້"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"ສະແດງໄອຄອນການແຈ້ງເຕືອນຄວາມສຳຄັນຕ່ຳ"</string>
     <string name="other" msgid="4060683095962566764">"ອື່ນໆ"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"ຕົວຂັ້ນການແບ່ງໜ້າຈໍ"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"ເຕັມໜ້າຈໍຊ້າຍ"</string>
@@ -806,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"ເປີດແອັບໂດຍບໍ່ມີການຕິດຕັ້ງແລ້ວ."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"ເປີດແອັບໂດຍບໍ່ມີການຕິດຕັ້ງແລ້ວ. ແຕະເພື່ອສຶກສາເພີ່ມເຕີມ."</string>
     <string name="app_info" msgid="6856026610594615344">"ຂໍ້ມູນແອັບ"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ໄປທີ່ເວັບ"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ໄປທີ່ໂປຣແກຣມທ່ອງເວັບ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ອິນເຕີເນັດມືຖື"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ປິດຢູ່"</string>
@@ -838,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"ການຕັ້ງຄ່າ"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"ເຂົ້າໃຈແລ້ວ"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> ກຳລັງໃຊ້ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ຂອງທ່ານ."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"ແອັບພລິເຄຊັນກຳລັງໃຊ້ <xliff:g id="TYPES_LIST">%s</xliff:g> ຂອງທ່ານ."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"ເປີດແອັບ"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"ຍົກເລີກ"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ຕົກລົງ"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"ການຕັ້ງຄ່າ"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> ກຳລັງໃຊ້ <xliff:g id="TYPE">%2$s</xliff:g> ຂອງທ່ານ <xliff:g id="TIME">%3$d</xliff:g> ນທ ທີ່ຜ່ານມາ"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> ກຳລັງໃຊ້ <xliff:g id="TYPE">%2$s</xliff:g> ຂອງທ່ານ"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> ກຳລັງໃຊ້ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ຂອງທ່ານ"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"ກ້ອງຖ່າຍຮູບ"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"ສະຖານທີ່"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"ໄມໂຄຣໂຟນ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 68e64d3..0792bbb 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Pabandykite padaryti ekrano kopiją dar kartą"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Negalima išsaugoti ekrano kopijos dėl ribotos saugyklos vietos"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Jūsų organizacijoje arba naudojant šią programą neleidžiama daryti ekrano kopijų"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Ekrano įrašymas"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Šiuo metu rodomas ekrano įrašymo sesijos pranešimas"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Pradėti įrašymą"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Įrašyti balsą už kadro"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Rodyti palietimus"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Sustabdyti"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pristabdyti"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Tęsti"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Atšaukti"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Bendrinti"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Ištrinti"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Ekrano įrašymas atšauktas"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Ekrano įrašas išsaugotas, palieskite ir peržiūrėkite"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Ekrano įrašas ištrintas"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Ištrinant ekrano įrašą įvyko klaida"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Nepavyko gauti leidimų"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB failo perdavimo parinktys"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos leistuvę (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Įmontuoti kaip fotoaparatą (PTP)"</string>
@@ -588,14 +604,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Pranešimai"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Nebematysite šių pranešimų"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Šie pranešimai bus sumažinti"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Paprastai šių pranešimų atsisakote. \nToliau juos rodyti?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Toliau rodyti šiuos pranešimus?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Sustabdyti pranešimus"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Toliau rodyti"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Sumažinti"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Toliau rodyti iš šios programos gautus pranešimus?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Šių pranešimų negalima išjungti"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"naudojant „<xliff:g id="APP_NAME">%1$s</xliff:g>“"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Ši programa naudoja fotoaparatą."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Ši programa naudoja mikrofoną."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Ši programa rodoma ekrane virš kitų programų."</string>
@@ -814,7 +837,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Programa atidaryta jos neįdiegus."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Programa atidaryta jos neįdiegus. Palieskite, kad sužinotumėte daugiau."</string>
     <string name="app_info" msgid="6856026610594615344">"Programos informacija"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Eiti į žiniatinklį"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Eiti į naršyklę"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilieji duomenys"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g>–<xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"„Wi-Fi“ išjungtas"</string>
@@ -846,4 +869,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Nustatymai"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Supratau"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Pat. „SysUI“ krūvą"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"Programa „<xliff:g id="APP">%1$s</xliff:g>“ naudoja: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Programos naudoja: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Atid. pr."</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Atšaukti"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Gerai"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Nustatymai"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"Programa „<xliff:g id="APP">%1$s</xliff:g>“ pastar. <xliff:g id="TIME">%3$d</xliff:g> min. naudoja: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Programos (<xliff:g id="APPS">%1$s</xliff:g>) naudoja: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"Programa „<xliff:g id="APP">%1$s</xliff:g>“ naudoja: <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"fotoaparatą"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"vietovę"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofoną"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index eb5e92c..14a859c 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Mēģiniet izveidot jaunu ekrānuzņēmumu."</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Nevar saglabāt ekrānuzņēmumu, jo krātuvē nepietiek vietas."</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Lietotne vai jūsu organizācija neatļauj veikt ekrānuzņēmumus."</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Notiek ekrāna ierakstīšana"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Aktīvs paziņojums par ekrāna ierakstīšanas sesiju"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Sākt ierakstīšanu"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Ierakstīt balsi"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Rādīt pieskārienus"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Pārtraukt"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Apturēt"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Atsākt"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Atcelt"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Kopīgot"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Dzēst"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Ekrāna ierakstīšana ir atcelta."</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Ekrāna ieraksts ir saglabāts. Pieskarieties, lai to skatītu."</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Ekrāna ieraksts ir izdzēsts."</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Dzēšot ekrāna ierakstu, radās kļūda."</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Neizdevās iegūt atļaujas."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB failu pārsūtīšanas opcijas"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Pievienot kā multivides atskaņotāju (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Pievienot kā kameru (PTP)"</string>
@@ -585,15 +601,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Paziņojumi"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Jūs vairs neredzēsiet šos paziņojumus."</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Šie paziņojumi tiks minimizēti"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Parasti jūs noraidāt šādus paziņojumus. \nVai turpināt tos rādīt?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Vai turpināt rādīt šos paziņojumus?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Apturēt paziņojumu rādīšanu"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Turpināt rādīt"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimizēt"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Vai turpināt rādīt paziņojumus no šīs lietotnes?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Šos paziņojumus nevar izslēgt."</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Šajā lietotnē tiek izmantota kamera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Šajā lietotnē tiek izmantots mikrofons."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Šī lietotne tiek rādīta ekrānā pāri citām lietotnēm."</string>
@@ -730,8 +752,7 @@
     <item msgid="2139628951880142927">"Rādīt procentuālo vērtību uzlādes laikā (noklusējums)"</item>
     <item msgid="3327323682209964956">"Nerādīt šo ikonu"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Rādīt zemas prioritātes paziņojumu ikonas"</string>
     <string name="other" msgid="4060683095962566764">"Citi"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Ekrāna sadalītājs"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Kreisā daļa pa visu ekrānu"</string>
@@ -811,7 +832,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Lai atvērtu šo lietotni, tā nav jāinstalē."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Lai atvērtu šo lietotni, tā nav jāinstalē. Pieskarieties, lai uzzinātu vairāk."</string>
     <string name="app_info" msgid="6856026610594615344">"Lietotnes informācija"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Pāriet uz tīmekli"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Atvērt pārlūku"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilie dati"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ir izslēgts"</string>
@@ -843,4 +864,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Iestatījumi"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Labi"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"Lietotne <xliff:g id="APP">%1$s</xliff:g> izmanto funkcijas <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Lietojumprogrammas izmanto šādas funkcijas: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Atvērt lietotni"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Atcelt"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Labi"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Iestatījumi"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"Lietotne <xliff:g id="APP">%1$s</xliff:g> pēdējās <xliff:g id="TIME">%3$d</xliff:g> min izmanto funkciju <xliff:g id="TYPE">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Lietotnes <xliff:g id="APPS">%1$s</xliff:g> izmanto funkciju <xliff:g id="TYPE">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"Lietotne <xliff:g id="APP">%1$s</xliff:g> izmanto funkcijas <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"atrašanās vieta"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofons"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 9c42805..cc937e9 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Повторно обидете се да направите слика од екранот"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Сликата од екранот не може да се зачува поради ограничена меморија"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Апликацијата или вашата организација не дозволува снимање слики од екранот"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Снимање на екранот"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Тековно известување за сесија за снимање на екранот"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Започни со снимање"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Снимај коментар"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Прикажувај допири"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Сопри"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Паузирај"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Продолжи"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Откажи"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Сподели"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Избриши"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Снимањето екран е откажано"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Снимката од екранот е зачувана, допрете за да ја видите"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Снимката од екранот е избришана"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Грешка при бришењето на снимката од екранот"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Не успеаја да се добијат дозволи"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Пренос на датотека со USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Монтирај како мултимедијален плеер (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Монтирај како фотоапарат (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Известувања"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Веќе нема да ги гледате овие известувања"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Овие известувања ќе се минимизираат"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Обично ги отфрлате известувањава. \nДа продолжат да се прикажуваат?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Дали да продолжат да се прикажуваат известувањава?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Запри ги известувањата"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Продолжи да ги прикажуваш"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Минимизирај"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Дали да продолжат да се прикажуваат известувања од апликацијава?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Известувањава не може да се исклучат"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Апликацијава ја користи камерата."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Апликацијава го користи микрофонот."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Апликацијава се прикажува врз други апликации на вашиот екран."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Прикажи процент кога се полни (стандардно)"</item>
     <item msgid="3327323682209964956">"Не прикажувај ја иконава"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Прикажувај икони за известувања со низок приоритет"</string>
     <string name="other" msgid="4060683095962566764">"Друго"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Разделник на поделен екран"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Левиот на цел екран"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Апликацијата беше отворена без да се инсталира."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Апликацијата беше отворена без да се инсталира. Допрете за да дознаете повеќе."</string>
     <string name="app_info" msgid="6856026610594615344">"Информации за апликација"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Одете на интернет"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Одете на прелистувач"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобилен интернет"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi е исклучено"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Поставки"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Сфатив"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Извади SysUI-слика"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> користи <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Апликациите користат <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Отвори апликација"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Откажи"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Во ред"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Поставки"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> користи <xliff:g id="TYPE">%2$s</xliff:g> во последните <xliff:g id="TIME">%3$d</xliff:g> мин."</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> користат <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> користи <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"камера"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"локација"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"микрофон"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 62196ea..b88fbd6 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"സ്‌ക്രീൻഷോട്ട് എടുക്കാൻ വീണ്ടും ശ്രമിക്കുക"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"സ്‌റ്റോറേജ് ഇടം പരിമിതമായതിനാൽ സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കാനാകുന്നില്ല"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"സ്ക്രീൻഷോട്ടുകൾ എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"സ്ക്രീൻ റെക്കോർഡിംഗ്"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"ഒരു സ്ക്രീൻ റെക്കോർഡിംഗ് സെഷനായി നിലവിലുള്ള അറിയിപ്പ്"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"റെക്കോര്‍ഡിംഗ് ആരംഭിക്കുക"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"വോയ്‌സ് ഓവർ റെക്കോർഡ് ചെയ്യുക"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"ടാപ്പുകൾ കാണിക്കുക"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"നിർത്തുക"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"താൽക്കാലികമായി നിർത്തുക"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"പുനരാരംഭിക്കുക"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"റദ്ദാക്കുക"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"പങ്കിടുക"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"ഇല്ലാതാക്കുക"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"സ്ക്രീൻ റെക്കോർഡിംഗ് റദ്ദാക്കി"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"സ്ക്രീൻ റെക്കോർഡിംഗ് സംരക്ഷിച്ചു, കാണാൻ ടാപ്പ് ചെയ്യുക"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"സ്ക്രീൻ റെക്കോർഡിംഗ് ഇല്ലാതാക്കി"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"സ്ക്രീൻ റെക്കോർഡിംഗ് ഇല്ലാതാക്കുന്നതിൽ പിശക്"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"അനുമതികൾ ലഭിച്ചില്ല"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ഫയൽ കൈമാറൽ ഓപ്‌ഷനുകൾ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ഒരു മീഡിയ പ്ലേയറായി (MTP) മൗണ്ടുചെയ്യുക"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ഒരു ക്യാമറയായി (PTP) മൗണ്ടുചെയ്യുക"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"അറിയിപ്പുകൾ"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"നിങ്ങൾ ഇനി ഈ അറിയിപ്പുകൾ കാണില്ല"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"ഈ അറിയിപ്പുകൾ ചെറുതാക്കപ്പെടും"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"സാധാരണയായി നിങ്ങൾ ഈ അറിയിപ്പുകൾ നിരാകരിക്കുന്നു. \nഅവ തുടർന്നും കാണിക്കണോ?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"ഈ അറിയിപ്പുകൾ തുടർന്നും കാണിക്കണോ?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"അറിയിപ്പുകൾ നിർത്തുക"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"തുടർന്നും കാണിക്കുക"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"ചെറുതാക്കുക‍"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"ഈ ആപ്പിൽ നിന്നുള്ള അറിയിപ്പുകൾ തുടർന്നും കാണിക്കണോ?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"ഈ അറിയിപ്പുകൾ ഓഫാക്കാനാവില്ല"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"ഈ ആപ്പ് ക്യാമറ ഉപയോഗിക്കുന്നുണ്ട്."</string>
     <string name="appops_microphone" msgid="741508267659494555">"ഈ ആപ്പ് മൈക്രോഫോൺ ഉപയോഗിക്കുന്നു."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"ഈ ആപ്പ് നിങ്ങളുടെ സ്‌ക്രീനിലെ മറ്റ് ആപ്പുകൾക്ക് മുകളിൽ പ്രദർശിപ്പിക്കുന്നു."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"ചാർജ്ജുചെയ്യുമ്പോൾ ശതമാനം കാണിക്കുക (ഡിഫോൾട്ട്)"</item>
     <item msgid="3327323682209964956">"ഈ ഐക്കൺ കാണിക്കരുത്"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"പ്രാധാന്യം കുറഞ്ഞ അറിയിപ്പ് ചിഹ്‌നങ്ങൾ"</string>
     <string name="other" msgid="4060683095962566764">"മറ്റുള്ളവ"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"സ്പ്ലിറ്റ്-സ്ക്രീൻ ഡിവൈഡർ"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"ഇടത് പൂർണ്ണ സ്ക്രീൻ"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"ഇൻസ്‌റ്റാൾ ചെയ്യാതെ ആപ്പ് തുറന്നു."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"ഇൻസ്‌റ്റാൾ ചെയ്യാതെ ആപ്പ് തുറന്നു. കൂടുതലറിയാൻ ടാപ്പ് ചെയ്യുക."</string>
     <string name="app_info" msgid="6856026610594615344">"ആപ്പ് വിവരം"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"വെബിൽ പോവുക"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ബ്രൗസറിലേക്ക് പോവുക"</string>
     <string name="mobile_data" msgid="7094582042819250762">"മൊബൈൽ ഡാറ്റ"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"വൈഫൈ ഓഫാണ്"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"ക്രമീകരണം"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"മനസ്സിലായി"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"SysUI ഹീപ്പ് ഡമ്പ് ചെയ്യുക"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> നിങ്ങളുടെ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ഉപയോഗിക്കുന്നു."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"ആപ്പുകൾ നിങ്ങളുടെ <xliff:g id="TYPES_LIST">%s</xliff:g> ഉപയോഗിക്കുന്നു."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"ആപ്പ് തുറക്കുക"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"റദ്ദാക്കുക"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ശരി"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"ക്രമീകരണം"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"കഴിഞ്ഞ <xliff:g id="TIME">%3$d</xliff:g> മിനിറ്റായി <xliff:g id="APP">%1$s</xliff:g> നിങ്ങളുടെ <xliff:g id="TYPE">%2$s</xliff:g> ഉപയോഗിക്കുന്നു"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> നിങ്ങളുടെ <xliff:g id="TYPE">%2$s</xliff:g> ഉപയോഗിക്കുന്നു"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g>നിങ്ങളുടെ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ഉപയോഗിക്കുന്നു"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"ക്യാമറ"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"ലൊക്കേഷന്‍"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"മൈക്രോഫോൺ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 223f492..7033766 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Дэлгэцийн зургийг дахин дарж үзнэ үү"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Сангийн багтаамж бага байгаа тул дэлгэцээс дарсан зургийг хадгалах боломжгүй байна"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Таны апп, байгууллагад дэлгэцийн зураг авахыг зөвшөөрдөггүй"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Дэлгэцийн бичлэг"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Дэлгэц бичих горимын үргэлжилж буй мэдэгдэл"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Бичлэгийг эхлүүлэх"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Дуу оруулалтыг бичих"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Товшилтыг харуулах"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Зогсоох"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Түр зогсоох"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Үргэлжлүүлэх"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Цуцлах"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Хуваалцах"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Устгах"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Дэлгэцийн бичлэгийг цуцалсан"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Дэлгэцийн бичлэгийг хадгалсан. Харахын тулд товшино уу"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Дэлгэцийн бичлэгийг устгасан"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Дэлгэцийн бичлэгийг устгахад алдаа гарлаа"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Зөвшөөрөл авч чадсангүй"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB файл шилжүүлэх сонголт"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа тоглуулагч(MTP) болгон залгах"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Камер болгон(PTP) залгах"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Мэдэгдэл"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Та эдгээр мэдэгдлийг цаашид харахгүй"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Энэ мэдэгдлийг багасгана"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Та эдгээр мэдэгдлийг ихэвчлэн хаадаг. \nЭдгээрийг харуулсан хэвээр байх уу?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Эдгээр мэдэгдлийг харуулсан хэвээр байх уу?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Мэдэгдлийг зогсоох"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Харуулсан хэвээр байх"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Багасгах"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Энэ аппаас мэдэгдэл харуулсан хэвээр байх уу?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Эдгээр мэдэгдлийг унтраах боломжгүй"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Энэ апп камерыг ашиглаж байна."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Энэ апп микрофоныг ашиглаж байна."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Энэ аппыг таны дэлгэцэд бусад аппын дээр харуулж байна."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Цэнэглэх үед хувийг тогтмол харуулах (өгөгдмөл)"</item>
     <item msgid="3327323682209964956">"Энэ дүрс тэмдгийг бүү үзүүл"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Бага ач холбогдолтой мэдэгдлийн дүрс тэмдгийг харуулах"</string>
     <string name="other" msgid="4060683095962566764">"Бусад"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"\"Дэлгэц хуваах\" хуваагч"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Зүүн талын бүтэн дэлгэц"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Аппыг суулгахгүйгээр нээсэн."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Аппыг суулгахгүйгээр нээсэн. Нэмэлт мэдээлэл авахын тулд товшино уу."</string>
     <string name="app_info" msgid="6856026610594615344">"Апп-н мэдээлэл"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Вэбэд очих"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Хөтчид очих"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобайл дата"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi унтраалттай байна"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Тохиргоо"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Ойлголоо"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> таны <xliff:g id="TYPES_LIST">%2$s</xliff:g>-г ашиглаж байна."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Аппууд таны <xliff:g id="TYPES_LIST">%s</xliff:g>-г ашиглаж байна."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Аппыг нээх"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Болих"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"За"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Тохиргоо"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> таны <xliff:g id="TYPE">%2$s</xliff:g>-г сүүлийн <xliff:g id="TIME">%3$d</xliff:g> минутын турш ашиглаж байна"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> таны <xliff:g id="TYPE">%2$s</xliff:g>-г ашиглаж байна"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> таны <xliff:g id="TYPES_LIST">%2$s</xliff:g>-г ашиглаж байна"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"камер"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"байршил"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"микрофон"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index da37acbf..159926a 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"स्क्रीनशॉट पुन्हा घेण्याचा प्रयत्न करा"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"मर्यादित स्टोरेज जागेमुळे स्क्रीनशॉट सेव्ह करू शकत नाही"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"अ‍ॅप किंवा आपल्या संस्थेद्वारे स्क्रीनशॉट घेण्याची अनुमती नाही"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"स्क्रीन रेकॉर्डिंग"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"स्क्रीन रेकॉर्ड सत्रासाठी सुरू असलेली सूचना"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"रेकॉर्डिंग सुरू करा"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"व्हॉइसओव्हर रेकॉर्ड करा"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"टॅप दाखवा"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"थांबवा"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"थांबवा"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"पुन्हा सुरू करा"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"रद्द करा"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"शेअर करा"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"हटवा"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"स्क्रीन रेकॉर्डिंग रद्द केले"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"स्क्रीन रेकॉर्डिंग सेव्ह केली, पाहण्यासाठी टॅप करा"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"स्क्रीन रेकॉर्डिंग हटवले"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"स्क्रीन रेकॉर्डिंग हटवताना एरर आली"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"परवानग्या मिळवता आल्या नाहीत"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फाईल स्थानांतरण पर्याय"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"मीडिया प्लेअर म्हणून माउंट करा (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"कॅमेरा म्हणून माउंट करा (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"सूचना"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"आता तुम्हाला या सूचना दिसणार नाहीत"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"या सूचना लहान केल्या जातील"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"तुम्ही या सूचना सामान्यतः डिसमिस करता. \nते दाखवत राहायचे?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"या सूचना दाखवणे सुरू ठेवायचे?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"सूचना थांबवा"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"दाखवणे सुरू ठेवा"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"लहान करा"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"या अ‍ॅपकडील सूचना दाखवणे सुरू ठेवायचे?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"या सूचना बंद करता येत नाहीत"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"हे अॅप कॅमेरा वापरत आहे."</string>
     <string name="appops_microphone" msgid="741508267659494555">"हे अॅप मायक्रोफोन वापरत आहे."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"हे अॅप स्क्रीनवरील इतर अॅप्स वर प्रदर्शित होत आहे."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"चार्ज करताना टक्केवारी दर्शवा (डीफॉल्ट)"</item>
     <item msgid="3327323682209964956">"हे आयकन दाखवू नका"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"कमी प्राधान्य सूचना आयकन दर्शवा"</string>
     <string name="other" msgid="4060683095962566764">"अन्य"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"विभाजित-स्क्रीन विभाजक"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"डावी फुल स्क्रीन"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"इंस्टॉल केल्याशिवाय अॅप उघडले."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"इंस्टॉल केल्याशिवाय अॅप उघडले. अधिक जाणून घेण्यासाठी टॅप करा."</string>
     <string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"वेबवर जा"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ब्राउझरवर जा"</string>
     <string name="mobile_data" msgid="7094582042819250762">"मोबाइल डेटा"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"वाय-फाय बंद आहे"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"सेटिंग्ज"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"समजले"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"SysUI हीप डंप करा"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> तुमचे <xliff:g id="TYPES_LIST">%2$s</xliff:g> वापरत आहे."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"अॅप्लिकेशन्स तुमचे <xliff:g id="TYPES_LIST">%s</xliff:g> वापरत आहे."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"अ‍ॅप उघडा"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"रद्द करा"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ओके"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"सेटिंग्ज"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"शेवटच्या <xliff:g id="TIME">%3$d</xliff:g> मिनिटासाठी <xliff:g id="APP">%1$s</xliff:g> तुमचे <xliff:g id="TYPE">%2$s</xliff:g> वापरत आहे"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> तुमचे <xliff:g id="TYPE">%2$s</xliff:g> वापरत आहे"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> तुमचे <xliff:g id="TYPES_LIST">%2$s</xliff:g> वापरत आहे"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"कॅमेरा"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"स्थान"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"मायक्रोफोन"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index cb4dd14..dbaccac 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Cuba ambil tangkapan skrin sekali lagi"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Tidak dapat menyimpan tangkapan skrin kerana ruang storan terhad"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Pengambilan tangkapan skrin tidak dibenarkan oleh apl atau organisasi anda"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Rakaman Skrin"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Pemberitahuan breterusan untuk sesi rakaman skrin"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Mula Merakam"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Rakam suara latar"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Tunjukkan ketikan"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Berhenti"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Jeda"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Sambung semula"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Batal"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Kongsi"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Padam"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Rakaman skrin dibatalkan"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Rakaman skrin disimpan, ketik untuk melihat"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Rakaman skrin dipadamkan"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Ralat semasa memadamkan rakaman skrin"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Gagal mendapatkan kebenaran"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Pilihan pemindahan fail USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Lekapkan sebagai pemain media (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Lekapkan sebagai kamera (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Pemberitahuan"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Anda tidak akan melihat pemberitahuan ini lagi"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Pemberitahuan ini akan diminimumkan"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Biasanya anda mengetepikan pemberitahuan ini. \nTerus tunjukkan pemberitahuan?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Terus tunjukkan pemberitahuan ini?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Hentikan pemberitahuan"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Terus tunjukkan"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimumkan"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Terus tunjukkan pemberitahuan daripada apl ini?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Pemberitahuan ini tidak boleh dimatikan"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Apl ini sedang menggunakan kamera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Apl ini sedang menggunakan mikrofon."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Apl ini dipaparkan di atas apl lain pada skrin anda."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Tunjukkan peratusan semasa mengecas (lalai)"</item>
     <item msgid="3327323682209964956">"Jangan tunjukkan ikon ini"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Tunjukkan ikon pemberitahuan keutamaan rendah"</string>
     <string name="other" msgid="4060683095962566764">"Lain-lain"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Pembahagi skrin pisah"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Skrin penuh kiri"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Apl dibuka tanpa dipasang."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Apl dibuka tanpa dipasang. Ketik untuk mengetahui lebih lanjut."</string>
     <string name="app_info" msgid="6856026610594615344">"Maklumat apl"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Pergi ke web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Pergi ke penyemak imbas"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Data mudah alih"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi dimatikan"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Tetapan"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Longgok Tmbunn SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> sedang menggunakan <xliff:g id="TYPES_LIST">%2$s</xliff:g> anda."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplikasi sedang menggunakan <xliff:g id="TYPES_LIST">%s</xliff:g> anda."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Buka apl"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Batal"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Okey"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Tetapan"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> sedang menggunakan <xliff:g id="TYPE">%2$s</xliff:g> anda selama <xliff:g id="TIME">%3$d</xliff:g> min yang lalu"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> sedang menggunakan <xliff:g id="TYPE">%2$s</xliff:g> anda"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> sedang menggunakan <xliff:g id="TYPES_LIST">%2$s</xliff:g> anda"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"lokasi"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 777d96e..2a1bf77 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"မျက်နှာပြင်ပုံကို ထပ်ရိုက်ကြည့်ပါ"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"သိုလှောင်ခန်းနေရာ အကန့်အသတ်ရှိသောကြောင့် ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းဆည်း၍မရပါ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ဖန်သားပြင်ဓာတ်ပုံရိုက်ကူးခြင်းကို ဤအက်ပ် သို့မဟုတ် သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"ဖန်သားပြင် ရိုက်ကူးမှု"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"စတင် ရိုက်ကူးရန်"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"နောက်ခံစကားပြော ကူးယူရန်"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"တို့ခြင်းများကို ပြရန်"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"ရပ်ရန်"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"ခဏရပ်ရန်"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"ဆက်လုပ်ရန်"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"မလုပ်တော့"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"မျှဝေရန်"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"ဖျက်ရန်"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"ဖန်သားပြင် ရိုက်ကူးမှု ပယ်ဖျက်လိုက်ပါပြီ"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"ဖန်သားပြင် ရိုက်ကူးမှု သိမ်းထားသည်၊ ကြည့်ရန် တို့ပါ"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"ဖန်သားပြင် ရိုက်ကူးမှု ဖျက်ပြီးပါပြီ"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"ဖန်သားပြင် ရိုက်ကူးမှု ဖျက်ရာတွင် အမှားအယွင်းရှိနေသည်"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"ခွင့်ပြုချက် မရယူနိုင်ပါ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ဖိုင်ပြောင်း ရွေးမှုများ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"မီဒီယာပလေရာအနေဖြင့် တပ်ဆင်ရန် (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ကင်မရာအနေဖြင့် တပ်ဆင်ရန် (PTP)"</string>
@@ -582,15 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"အကြောင်းကြားချက်များ"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"ဤအကြောင်းကြားချက်များကို မြင်ရတော့မည် မဟုတ်ပါ"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"ဤအကြောင်းကြားချက်များကို ချုံ့ထားပါမည်"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"ဤအကြောင်းကြားချက်များကို တိတ်တဆိတ် ပြပါမည်"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"ဤအကြောင်းကြားချက်များက သင့်ကို သတိပေးပါမည်"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"သင်သည် အများအားဖြင့် ဤအကြောင်းကြားချက်များကို ပယ်လေ့ရှိပါသည်။ \n၎င်းတို့ကို ဆက်လက်ပြသလိုပါသလား။"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"ဤအကြောင်းကြားချက်များကို ဆက်ပြလိုပါသလား။"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"အကြောင်းကြားချက်များကို ရပ်ရန်"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"ဆက်ပြရန်"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"ချုံ့ရန်"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"တိတ်တဆိတ် ပြရန်"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"ပြပြီး သတိပေးရန်"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"ဤအက်ပ်ထံမှ အကြောင်းကြားချက်များကို ဆက်ပြလိုပါသလား။"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"ဤအကြောင်းကြားချက်များကို ပိတ်၍မရပါ"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"ဤအက်ပ်က ကင်မရာကို အသုံးပြုနေသည်။"</string>
     <string name="appops_microphone" msgid="741508267659494555">"ဤအက်ပ်က မိုက်ခရိုဖုန်းကို အသုံးပြုနေသည်။"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"ဤအက်ပ်က ဖန်သားမျက်နှာပြင်ပေါ်ရှိ အခြားအက်ပ်များ အပေါ်မှ ထပ်ပြီး ပြသနေပါသည်။"</string>
@@ -725,8 +743,7 @@
     <item msgid="2139628951880142927">"အားသွင်းနေစဉ်တွင် ရာခိုင်နှုန်းကိုပြပါ (ပုံသေ)"</item>
     <item msgid="3327323682209964956">"ဤသင်္ကေတပုံကို မပြပါနှင့်"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"အရေးမကြီးသော အကြောင်းကြားချက် သင်္ကေတများ ပြရန်"</string>
     <string name="other" msgid="4060683095962566764">"အခြား"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"မျက်နှာပြင်ခွဲခြမ်း ပိုင်းခြားပေးသည့်စနစ်"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"ဘယ်ဘက် မျက်နှာပြင်အပြည့်"</string>
@@ -806,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"အက်ပ်ကိုမထည့်သွင်းဘဲ ဖွင့်ထားသည်။"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"အက်ပ်ကိုမထည့်သွင်းဘဲ ဖွင့်ထားသည်။ ပိုမိုလေ့လာရန် တို့ပါ။"</string>
     <string name="app_info" msgid="6856026610594615344">"အက်ပ်အချက်အလက်"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ဝဘ်သို့ သွားရန်"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ဘရောင်ဇာသို့ သွားပါ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"မိုဘိုင်းဒေတာ"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> —<xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ကို ပိတ်ထားသည်"</string>
@@ -838,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"ဆက်တင်များ"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"ရပါပြီ"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> က သင်၏ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ကို အသုံးပြုနေသည်။"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"အပလီကေးရှင်းများက သင်၏ <xliff:g id="TYPES_LIST">%s</xliff:g> ကို အသုံးပြုနေသည်။"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"ဖွင့်ရန်"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"မလုပ်တော့"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Okay"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"ဆက်တင်များ"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> သည် ပြီးခဲ့သော <xliff:g id="TIME">%3$d</xliff:g> မိနစ်က သင်၏ <xliff:g id="TYPE">%2$s</xliff:g> ကို အသုံးပြုနေသည်"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> တို့က သင်၏ <xliff:g id="TYPE">%2$s</xliff:g> ကို အသုံးပြုနေသည်"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> က သင်၏ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ကို အသုံးပြုနေသည်"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"ကင်မရာ"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"တည်နေရာ"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"မိုက်ခရိုဖုန်း"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 9b27df5..4014957 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Prøv å ta skjermdump på nytt"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Kan ikke lagre skjermdumpen på grunn av begrenset lagringsplass"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Appen eller organisasjonen din tillater ikke at du tar skjermdumper"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Skjermopptak"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Vedvarende varsel for et skjermopptak"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Start opptak"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Ta opp et kommentarspor"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Vis trykk"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Stopp"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Sett på pause"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Gjenoppta"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Avbryt"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Del"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Slett"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Skjermopptak er avbrutt"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Skjermopptaket er lagret. Trykk for å se det"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Skjermopptaket er slettet"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Feil ved sletting av skjermopptaket"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Kunne ikke få tillatelser"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Altern. for USB-filoverføring"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Sett inn som mediespiller (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Sett inn som kamera (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Varsler"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Du ser ikke disse varslene lenger"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Disse varslene minimeres"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Du avviser vanligvis disse varslene. \nVil du fortsette å vise dem?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Vil du fortsette å vise disse varslene?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Stopp varsler"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Fortsett å vise"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimer"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Vil du fortsette å vise varsler fra denne appen?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Du kan ikke slå av disse varslene"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Denne appen bruker kameraet."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Denne appen bruker mikrofonen."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Denne appen vises over andre apper på skjermen."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Vis prosentandel under lading (standard)"</item>
     <item msgid="3327323682209964956">"Ikke vis dette ikonet"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Vis ikoner for varsler med lav prioritet"</string>
     <string name="other" msgid="4060683095962566764">"Annet"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Skilleelement for delt skjerm"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Utvid den venstre delen av skjermen til hele skjermen"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Appen ble åpnet uten at den ble installert."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Appen ble åpnet uten at den ble installert. Trykk for å finne ut mer."</string>
     <string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Gå til nettstedet"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Gå til nettleser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobildata"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi er av"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Innstillinger"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Greit"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI-heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> bruker <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Apper bruker <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Åpne appen"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Avbryt"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Ok"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Innst."</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> har brukt <xliff:g id="TYPE">%2$s</xliff:g> de siste <xliff:g id="TIME">%3$d</xliff:g> minuttene"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> bruker <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> bruker <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"posisjon"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 5119e5b..67e4223 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"स्क्रिनसट फेरि लिएर हेर्नुहोस्"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"भण्डारण ठाउँ सीमित भएका कारण स्क्रिनसट सुरक्षित गर्न सकिएन"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"उक्त अनुप्रयोग वा तपाईंको संगठनले स्क्रिनसटहरू लिन दिँदैन"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"स्क्रिनको रेकर्डिङ"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"कुनै स्क्रिन रेकर्ड गर्ने सत्रका लागि चलिरहेको सूचना"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"रेकर्डिङ सुरु गर्नुहोस्"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"भ्वाइसओवर रेकर्ड गर्नुहोस्"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"ट्यापहरू देखाउनुहोस्"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"रोक्नुहोस्"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"पज गर्नुहोस्"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"जारी राख्नुहोस्"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"रद्द गर्नुहोस्"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"आदान प्रदान गर्नुहोस्"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"मेट्नुहोस्"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"स्क्रिन रेकर्ड गर्ने कार्य रद्द गरियो"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"स्क्रिन रेकर्डिङ सुरक्षित गरियो, हेर्न ट्याप गर्नुहोस्‌"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"स्क्रिनको रेकर्डिङ मेटाइयो"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"स्क्रिनको रेकर्डिङ मेट्ने क्रममा त्रुटि"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"अनुमति प्राप्त गर्न सकिएन"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फाइल सार्ने विकल्पहरू"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"मिडिया प्लेयर(MTP)को रूपमा माउन्ट गर्नुहोस्"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"क्यामेराको रूपमा माउन्ट गर्नुहोस् (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"सूचनाहरू"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"तपाईं अब उप्रान्त यी सूचनाहरू देख्नु हुने छैन"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"यी सूचनाहरू सानो बनाइने छ"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"तपाईं सामान्यतया यी सूचनाहरूलाई खारेज गर्ने गर्नुहुन्छ। \nतिनलाई देखाइरहने हो?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"यी सूचनाहरू देखाउने क्रम जारी राख्ने हो?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"सूचनाहरू देखाउन छाड्नुहोस्"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"देखाउने क्रम जारी राख्नुहोस्"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"सानो बनाउनुहोस्"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"यो अनुप्रयोगका सूचनाहरू देखाउने क्रम जारी राख्ने हो?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"यी सूचनाहरूलाई निष्क्रिय पार्न सकिँदैन"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"यो अनुप्रयोगले क्यामेराको प्रयोग गर्दै छ।"</string>
     <string name="appops_microphone" msgid="741508267659494555">"यो अनुप्रयोगले माइक्रोफोनको प्रयोग गर्दै छ।"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्दै छ।"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"चार्ज गर्दा प्रतिशत देखाउनुहोस् (पूर्वनिर्धारित)"</item>
     <item msgid="3327323682209964956">"यो आइकन नदेखाउनुहोस्"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"कम प्राथमिकताका सूचना आइकनहरू देखाउनुहोस्"</string>
     <string name="other" msgid="4060683095962566764">"अन्य"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"विभाजित-स्क्रिन छुट्याउने"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"बायाँ भाग पूर्ण स्क्रिन"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"स्थापना नगरिकनै अनुप्रयोग खोलियो।"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"स्थापना नगरिकनै अनुप्रयोग खोलियो। थप जान्न ट्याप गर्नुहोस्।"</string>
     <string name="app_info" msgid="6856026610594615344">"अनुप्रयोगका बारे जानकारी"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"वेबमा जानुहोस्"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ब्राउजरमा जानुहोस्"</string>
     <string name="mobile_data" msgid="7094582042819250762">"मोबाइल डेटा"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi‑Fi निष्क्रिय छ"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"सेटिङहरू"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"बुझेँ"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> ले तपाईंको <xliff:g id="TYPES_LIST">%2$s</xliff:g> प्रयोग गर्दै छ।"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"अनुप्रयोगहरूले तपाईंको <xliff:g id="TYPES_LIST">%s</xliff:g> प्रयोग गर्दै छन्‌।"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"अनुप्रयोग खोल्नुहोस्"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"रद्द गर्नु…"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ठिक छ"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"सेटिङहरू"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> ले विगत <xliff:g id="TIME">%3$d</xliff:g> मिनेट देखि तपाईंको <xliff:g id="TYPE">%2$s</xliff:g> प्रयोग गर्दै छन्‌"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> ले तपाईंको <xliff:g id="TYPE">%2$s</xliff:g> प्रयोग गर्दै छन्‌"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> ले तपाईंको <xliff:g id="TYPES_LIST">%2$s</xliff:g> प्रयोग गर्दै छ"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"क्यामेरा"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"स्थान"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"माइक्रोफोन"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 448a36e..30ccad8 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Probeer opnieuw een screenshot te maken"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Kan screenshot niet opslaan vanwege beperkte opslagruimte"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Het maken van screenshots wordt niet toegestaan door de app of je organisatie"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Schermopname"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Doorlopende melding voor een schermopname-sessie"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Opname starten"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Voice-over opnemen"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Tikken weergeven"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Stoppen"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pauzeren"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Hervatten"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Annuleren"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Delen"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Verwijderen"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Schermopname geannuleerd"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Schermopname opgeslagen, tik om te bekijken"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Schermopname verwijderd"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Fout bij verwijderen van schermopname"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Kan machtigingen niet ophalen"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opties voor USB-bestandsoverdracht"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Koppelen als mediaspeler (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Koppelen als camera (PTP)"</string>
@@ -582,15 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Meldingen"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Deze meldingen worden niet meer weergegeven"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Deze meldingen worden geminimaliseerd"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"Deze meldingen worden zonder geluid weergegeven"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Deze meldingen stellen je op de hoogte"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Meestal sluit je deze meldingen. \nWil je ze blijven weergeven?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Deze meldingen blijven weergeven?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Meldingen stoppen"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Blijven weergeven"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimaliseren"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Zonder geluid weergeven"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Weergeven en melden"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Meldingen van deze app blijven weergeven?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Deze meldingen kunnen niet worden uitgeschakeld"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Deze app gebruikt de camera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Deze app gebruikt de microfoon."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Deze app wordt over andere apps op je scherm heen weergegeven."</string>
@@ -725,8 +743,7 @@
     <item msgid="2139628951880142927">"Percentage weergeven tijdens opladen (standaard)"</item>
     <item msgid="3327323682209964956">"Dit pictogram niet weergeven"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Pictogrammen voor meldingen met lage prioriteit weergeven"</string>
     <string name="other" msgid="4060683095962566764">"Overig"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Scheiding voor gesplitst scherm"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Linkerscherm op volledig scherm"</string>
@@ -806,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"App geopend zonder dat deze is geïnstalleerd."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"App geopend zonder dat deze is geïnstalleerd. Tik voor meer informatie."</string>
     <string name="app_info" msgid="6856026610594615344">"App-info"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Ga naar internet"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Ga naar browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobiele data"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wifi is uitgeschakeld"</string>
@@ -838,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Instellingen"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> gebruikt je <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Apps gebruiken je <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"App openen"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Annuleren"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Instellingen"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> gebruikt je <xliff:g id="TYPE">%2$s</xliff:g> gedurende de afgelopen <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> gebruiken je <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> gebruikt je <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"camera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"locatie"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"microfoon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index a9441fa..1768c69a 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"ପୁଣିଥରେ ସ୍କ୍ରୀନ୍‌ଶଟ୍ ନେବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"ସୀମିତ ଷ୍ଟୋରେଜ୍‍ ସ୍ପେସ୍‍ ହେତୁ ସ୍କ୍ରୀନଶଟ୍‍ ସେଭ୍‍ ହୋଇପାରିବ ନାହିଁ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ଆପ୍‍ କିମ୍ବା ସଂସ୍ଥା ଦ୍ୱାରା ସ୍କ୍ରୀନଶଟ୍‍ ନେବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"ସ୍କ୍ରିନ୍‍ ରେକର୍ଡିଂ"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"ଏକ ସ୍କ୍ରି‍ନ୍‍ ରେକର୍ଡ୍‍ ସେସନ୍‍ ପାଇଁ ଚାଲୁଥିବା ବିଜ୍ଞପ୍ତି"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"ରେକର୍ଡିଂ ଆରମ୍ଭ କରନ୍ତୁ"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"ଭଏସ୍‍‍‍‍‍‍‍‍‍ଓଭର୍‍ ରେକର୍ଡ କରନ୍ତୁ"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"ଟାପ୍‌ ଦେଖାନ୍ତୁ"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"ବନ୍ଦ କରନ୍ତୁ"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"ବିରତି କରନ୍ତୁ"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"ବାତିଲ୍‌ କରନ୍ତୁ"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"ସେୟାର୍‍ କରନ୍ତୁ"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"ଡିଲିଟ୍ କରନ୍ତୁ"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"ସ୍କ୍ରିନ୍‍ ରେକର୍ଡିଂ ବାତିଲ୍‌ କରିଦିଆଯାଇଛି"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"ସ୍କ୍ରିନ୍‍ ରେକର୍ଡିଂ ସେଭ୍‍ ହୋଇଛି, ଦେଖିବାକୁ ଟାପ୍‍ କରନ୍ତୁ"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"ସ୍କ୍ରିନ୍‍ ରେକର୍ଡିଂ ଡିଲିଟ୍‍ କରିଦିଆଯାଇଛି"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"ସ୍କ୍ରିନ୍‍ ରେକର୍ଡିଂ ଡିଲିଟ୍‍ କରିବାରେ ତ୍ରୁଟି"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"ଅନୁମତି ପାଇବାରେ ଅସଫଳ ହେଲା।"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ଫାଇଲ୍‌ ଟ୍ରାନ୍ସଫର୍‌ର ବିକଳ୍ପ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ଏକ ମିଡିଆ ପ୍ଲେୟାର୍‍ (MTP) ଭାବରେ ଭର୍ତ୍ତି କରନ୍ତୁ"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ଏକ କ୍ୟାମେରା (PTP) ଭାବରେ ଭର୍ତ୍ତି କରନ୍ତୁ"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ବିଜ୍ଞପ୍ତି"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଆପଣ ଆଉ ଦେଖିବାକୁ ପାଇବେନାହିଁ।"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ମିନିମାଇଜ୍ ହୋଇଯିବ"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"ସାଧାରଣତଃ ଆପଣ ଏହି ବିଜ୍ଞପ୍ତିକୁ ଖାରଜ କରିଦିଅନ୍ତି। \n ସେଗୁଡ଼ିକୁ ଦେଖାଇବା ଜାରି ରଖିବେ?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଦେଖାଇବା ଜାରି ରଖିବେ?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"ବିଜ୍ଞପ୍ତିକୁ ଦେଖାଇବା ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"ଦେଖାଇବା ଜାରି ରଖନ୍ତୁ"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"ଛୋଟ କରନ୍ତୁ"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"ଏହି ଆପ୍‌ରୁ ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକୁ ଦେଖାଇବା ଜାରି ରଖିବେ?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"ଏହି ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ବନ୍ଦ କରିହେବ ନାହିଁ"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"ଏହି ଆପ୍ କ୍ୟାମେରା ବ୍ୟବହାର କରୁଛି।"</string>
     <string name="appops_microphone" msgid="741508267659494555">"ଏହି ଆପ୍, ମାଇକ୍ରୋଫୋନ୍‍ ବ୍ୟବହାର କରୁଛି।"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"ଏହି ଆପ୍, ଆପଣଙ୍କର ସ୍କ୍ରୀନ୍ ଉପରେ ଥିବା ଅନ୍ୟ ଆପ୍ ଉପରେ ପ୍ରଦର୍ଶିତ ହେଉଛି।"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"ଚାର୍ଜ କରାଯିବାବେଳେ ଶତକଡ଼ା ଦେଖାନ୍ତୁ (ଡିଫଲ୍ଟ)"</item>
     <item msgid="3327323682209964956">"ଏହି ଆଇକନ୍‍ ଦେଖାନ୍ତୁ ନାହିଁ"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"କମ୍‍-ଅଗ୍ରାଧିକାର ବିଜ୍ଞପ୍ତି ଆଇକନ୍‍ ଦେଖାନ୍ତୁ"</string>
     <string name="other" msgid="4060683095962566764">"ଅନ୍ୟାନ୍ୟ"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"ସ୍ପ୍ଲିଟ୍‍-ସ୍କ୍ରୀନ ବିଭାଜକ"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"ବାମ ପଟକୁ ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍‍ କରନ୍ତୁ"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"ଇନ୍‍ଷ୍ଟଲ୍‍ ନହୋଇ ଆପ୍‍ ଖୋଲିଛି।"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"ଇନ୍‍ଷ୍ଟଲ୍‍ ନହୋଇ ଆପ୍‍ ଖୋଲିଛି। ଅଧିକ ଜାଣିବା ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ।"</string>
     <string name="app_info" msgid="6856026610594615344">"ଆପ୍‍ ସୂଚନା"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ୱେବକୁ ଯାଆନ୍ତୁ"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ବ୍ରାଉଜର୍‌କୁ ଯାଆନ୍ତୁ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ମୋବାଇଲ୍‌ ଡାଟା"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"ୱାଇ-ଫାଇ ଅଫ୍‍ ଅଛି"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"ସେଟିଙ୍ଗ"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"ବୁଝିଲି"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"SysUI ହିପ୍ ଡମ୍ପ୍ କରନ୍ତୁ"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> ଆପଣଙ୍କ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ବ୍ୟବହାର କରୁଛନ୍ତି।"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"ଆପ୍ଲିକେସନ୍‍ଗୁଡିକ ଆପଣଙ୍କ <xliff:g id="TYPES_LIST">%s</xliff:g> ବ୍ୟବହାର କରୁଛନ୍ତି।"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"ଆପ୍‌ ଖୋଲନ୍ତୁ"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"ବାତିଲ୍‌"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ଠିକ୍ ଅଛି"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"ସେଟିଂସ୍‍"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> ବିଗତ <xliff:g id="TIME">%3$d</xliff:g> ମିନିଟ୍‍ ହେବ ଆପଣଙ୍କ <xliff:g id="TYPE">%2$s</xliff:g> ବ୍ୟବହାର କରୁଛନ୍ତି।"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> ଆପଣଙ୍କ <xliff:g id="TYPE">%2$s</xliff:g> ବ୍ୟବହାର କରୁଛନ୍ତି"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> ଆପଣଙ୍କ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ବ୍ୟବହାର କରୁଛନ୍ତି"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"କ୍ୟାମେରା"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"ଲୋକେସନ୍‍"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"ମାଇକ୍ରୋଫୋନ୍"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 57971eb..dbcd43c 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੁਬਾਰਾ ਲੈ ਕੇ ਦੇਖੋ"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਹੋਣ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਹੈ"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"ਕਿਸੇ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਸੈਸ਼ਨ ਲਈ ਚੱਲ ਰਹੀ ਸੂਚਨਾ"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"ਰਿਕਾਰਡਿੰਗ ਸ਼ੁਰੂ ਕਰੋ"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"ਅਵਾਜ਼ ਰਿਕਾਰਡ ਕਰੋ"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"ਟੈਪਾਂ ਦਿਖਾਓ"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"ਬੰਦ ਕਰੋ"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"ਰੋਕੋ"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"ਰੱਦ ਕਰੋ"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"ਸਾਂਝਾ ਕਰੋ"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"ਮਿਟਾਓ"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"ਸਕ੍ਰੀਨ ਦੀ ਰਿਕਾਰਡਿੰਗ ਰੱਦ ਕੀਤੀ ਗਈ"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਰੱਖਿਅਤ ਕੀਤੀ ਗਈ, ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਨੂੰ ਮਿਟਾਇਆ ਗਿਆ"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਨੂੰ ਮਿਟਾਉਣ ਦੌਰਾਨ ਗੜਬੜ ਹੋਈ"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"ਇਜਾਜ਼ਤਾਂ ਪ੍ਰਾਪਤ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਚੋਣਾਂ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ਇੱਕ ਮੀਡੀਆ ਪਲੇਅਰ (MTP) ਦੇ ਤੌਰ ਤੇ ਮਾਊਂਟ ਕਰੋ"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ਇੱਕ ਕੈਮਰੇ (PTP) ਦੇ ਤੌਰ ਤੇ ਮਾਊਂਟ ਕਰੋ"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ਸੂਚਨਾਵਾਂ"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"ਤੁਹਾਨੂੰ ਹੁਣ ਇਹ ਸੂਚਨਾਵਾਂ ਦਿਖਾਈ ਨਹੀਂ ਦੇਣਗੀਆਂ"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਛੋਟਾ ਕੀਤਾ ਜਾਵੇਗਾ"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"ਤੁਸੀਂ ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਆਮ ਤੌਰ \'ਤੇ ਖਾਰਜ ਕਰਦੇ ਹੋ। \nਕੀ ਇਹਨਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"ਕੀ ਇਨ੍ਹਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"ਸੂਚਨਾਵਾਂ ਬੰਦ ਕਰੋ"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖੋ"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"ਛੋਟਾ ਕਰੋ"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"ਕੀ ਇਸ ਐਪ ਤੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਦਿਖਾਉਣਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"ਇਨ੍ਹਾਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬੰਦ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"ਇਹ ਐਪ ਕੈਮਰੇ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ।"</string>
     <string name="appops_microphone" msgid="741508267659494555">"ਇਹ ਐਪ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ।"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"ਇਹ ਐਪ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਹੋਰਾਂ ਐਪਾਂ ਉੱਪਰ ਦਿਖਾਈ ਜਾ ਰਹੀ ਹੈ।"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"ਚਾਰਜਿੰਗ ਦੌਰਾਨ ਪ੍ਰਤੀਸ਼ਤਤਾ ਦਿਖਾਓ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
     <item msgid="3327323682209964956">"ਇਸ ਪ੍ਰਤੀਕ ਨੂੰ ਨਾ ਦਿਖਾਓ"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"ਘੱਟ ਤਰਜੀਹ ਵਾਲੇ ਸੂਚਨਾ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਦਿਖਾਓ"</string>
     <string name="other" msgid="4060683095962566764">"ਹੋਰ"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਡਿਵਾਈਡਰ"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"ਖੱਬੇ ਪੂਰੀ ਸਕ੍ਰੀਨ"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"ਸਥਾਪਤ ਕੀਤੇ ਬਿਨਾਂ ਐਪ ਖੋਲ੍ਹੀ ਗਈ।"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"ਸਥਾਪਤ ਕੀਤੇ ਬਿਨਾਂ ਐਪ ਖੋਲ੍ਹੀ ਗਈ। ਹੋਰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ਵੈੱਬ \'ਤੇ ਜਾਓ"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ਬ੍ਰਾਊਜ਼ਰ \'ਤੇ ਜਾਓ"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ਮੋਬਾਈਲ ਡਾਟਾ"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"ਵਾਈ-ਫਾਈ ਬੰਦ ਹੈ"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"ਸਮਝ ਲਿਆ"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"SysUI ਹੀਪ ਡੰਪ ਕਰੋ"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ।"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"ਐਪਲੀਕੇਸ਼ਨਾਂ ਤੁਹਾਡੇ <xliff:g id="TYPES_LIST">%s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ।"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"ਐਪ ਖੋਲ੍ਹੋ"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"ਰੱਦ ਕਰੋ"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ਠੀਕ ਹੈ"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> ਪਿਛਲੇ <xliff:g id="TIME">%3$d</xliff:g> ਮਿੰਟ ਤੋਂ ਤੁਹਾਡੇ <xliff:g id="TYPE">%2$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="TYPE">%2$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"ਕੈਮਰਾ"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"ਟਿਕਾਣਾ"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 2510aba..f9c1c79 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Spróbuj jeszcze raz wykonać zrzut ekranu"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Nie można zapisać zrzutu ekranu, bo brakuje miejsca w pamięci"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Nie możesz wykonać zrzutu ekranu, bo nie zezwala na to aplikacja lub Twoja organizacja."</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Rejestrowanie zawartości ekranu"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Stałe powiadomienie o sesji rejestrowania zawartości ekranu"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Rozpocznij rejestrowanie"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Nagraj tekst lektora"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Pokaż dotknięcia"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Zatrzymaj"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Wstrzymaj"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Wznów"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Anuluj"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Udostępnij"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Usuń"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Anulowano rejestrowanie zawartości ekranu"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Zapisano nagranie zawartości ekranu – kliknij, by je obejrzeć"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Usunięto nagranie zawartości ekranu"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Błąd podczas usuwania nagrania zawartości ekranu"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Nie udało się uzyskać uprawnień"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB – opcje przesyłania plików"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Podłącz jako odtwarzacz multimedialny (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Podłącz jako aparat (PTP)"</string>
@@ -588,15 +604,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Powiadomienia"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Te powiadomienia nie będą już wyświetlane"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Te powiadomienia zostaną zminimalizowane"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Zwykle odrzucasz te powiadomienia. \nNadal je pokazywać?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Nadal pokazywać te powiadomienia?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Zablokuj powiadomienia"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Pokazuj nadal"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimalizuj"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Nadal pokazywać powiadomienia z tej aplikacji?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Tych powiadomień nie można wyłączyć"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Ta aplikacja używa aparatu."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Ta aplikacja używa mikrofonu."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Ta aplikacja wyświetla się nad innymi aplikacjami na ekranie."</string>
@@ -735,8 +757,7 @@
     <item msgid="2139628951880142927">"Pokazuj procent podczas ładowania (domyślnie)"</item>
     <item msgid="3327323682209964956">"Nie pokazuj tej ikony"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Pokazuj ikony powiadomień o niskim priorytecie"</string>
     <string name="other" msgid="4060683095962566764">"Inne"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Linia dzielenia ekranu"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Lewa część ekranu na pełnym ekranie"</string>
@@ -816,7 +837,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Aplikacja została otwarta bez zainstalowania."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Aplikacja została otwarta bez zainstalowania. Kliknij, by dowiedzieć się więcej."</string>
     <string name="app_info" msgid="6856026610594615344">"O aplikacji"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Wejdź na stronę internetową"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Otwórz przeglądarkę"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Komórkowa transmisja danych"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi jest wyłączone"</string>
@@ -848,4 +869,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Ustawienia"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Zrzut stosu SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"Aplikacja <xliff:g id="APP">%1$s</xliff:g> używa: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplikacje używają: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Otwórz"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Anuluj"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Ustawienia"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"Aplikacja <xliff:g id="APP">%1$s</xliff:g> używa: <xliff:g id="TYPE">%2$s</xliff:g> od <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Aplikacje <xliff:g id="APPS">%1$s</xliff:g> używają: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"Aplikacja <xliff:g id="APP">%1$s</xliff:g> używa: <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"aparat"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"lokalizacja"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 507c6b0..cd469e5 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Tente fazer a captura de tela novamente"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"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="173674476457581486">"O app ou a organização não permitem capturas de tela"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Gravação de tela"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Notificação contínua para uma sessão de gravação de tela"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Iniciar gravação"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Gravar narração"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Mostrar toques"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Parar"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pausar"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Retomar"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Cancelar"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Compartilhar"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Excluir"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Gravação de tela cancelada"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Gravação de tela salva, toque para ver"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Gravação de tela excluída"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Erro ao excluir a gravação de tela"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Não foi possível acessar as permissões"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Conectar como media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como uma câmera (PTP)"</string>
@@ -582,14 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificações"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Você deixará de ver essas notificações"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Essas notificações serão minimizadas"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Geralmente você dispensa essas notificações. \nQuer que elas continuem a ser exibidas?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Continuar mostrando essas notificações?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Bloquear notificações"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Continuar mostrando"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimizar"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuar mostrando notificações desse app?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Não é possível desativar essas notificações"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"pelo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Este app está usando a câmera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Este app está usando o microfone."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Este app está sobreposto a outros apps na sua tela."</string>
@@ -804,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"O app é aberto sem precisar ser instalado."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"O app é aberto sem precisar ser instalado. Toque para saber mais."</string>
     <string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Acessar a Web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Abrir o navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Dados móveis"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"O Wi-Fi está desativado"</string>
@@ -836,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Configurações"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Ok"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Despejar pilha SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"O app <xliff:g id="APP">%1$s</xliff:g> está usando <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplicativos estão usando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Abrir app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Cancelar"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Ok"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Config."</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"O app <xliff:g id="APP">%1$s</xliff:g> está usando <xliff:g id="TYPE">%2$s</xliff:g> há <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Os apps <xliff:g id="APPS">%1$s</xliff:g> estão usando <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"O app <xliff:g id="APP">%1$s</xliff:g> está usando <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"câmera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"localização"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"microfone"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index f3c993f..8006f33 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -70,10 +70,26 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Experimente voltar a efetuar a captura de ecrã."</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"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="173674476457581486">"A aplicação ou a sua entidade não permitem tirar capturas de ecrã"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Gravação de ecrã"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Notificação persistente de uma sessão de gravação de ecrã"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Iniciar gravação"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Gravar voz-off"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Mostrar toques"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Parar"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Colocar em pausa"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Retomar"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Cancelar"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Partilhar"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Eliminar"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Gravação de ecrã cancelada."</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Gravação de ecrã guardada. Toque para ver."</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Gravação de ecrã eliminada."</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Erro ao eliminar a gravação de ecrã."</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Falha ao obter as autorizações."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções de transm. de fich. USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Montar como leitor de multimédia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como câmara (PTP)"</string>
-    <string name="installer_cd_button_title" msgid="2312667578562201583">"Inst. aplic. Transf. Ficheiros do Android para Mac"</string>
+    <string name="installer_cd_button_title" msgid="2312667578562201583">"Inst. app Transf. Ficheiros do Android para Mac"</string>
     <string name="accessibility_back" msgid="567011538994429120">"Anterior"</string>
     <string name="accessibility_home" msgid="8217216074895377641">"Página inicial"</string>
     <string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
@@ -457,7 +473,7 @@
     <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"O seu perfil pessoal está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"O seu dispositivo é gerido pelo <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"A <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> utiliza o <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> para gerir o seu dispositivo."</string>
-    <string name="monitoring_description_do_body" msgid="3639594537660975895">"O administ. pode monitorizar e gerir definições, acesso empresarial, aplic. e dados associados ao dispositivo, bem como inf. de localiz. do disp."</string>
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"O administ. pode monitorizar e gerir definições, acesso empresarial, app e dados associados ao dispositivo, bem como inf. de localiz. do disp."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saiba mais"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
@@ -582,14 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificações"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Nunca mais verá estas notificações."</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Estas notificações serão minimizadas."</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Normalmente, ignora estas notificações. \nPretende continuar a mostrá-las?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Pretende continuar a ver estas notificações?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Parar notificações"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Continuar a mostrar"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimizar"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Pretende continuar a ver notificações desta aplicação?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Não é possível desativar estas notificações."</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"através da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Esta aplicação está a utilizar a câmara."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Esta aplicação está a utilizar o microfone."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Esta aplicação está a sobrepor-se a outras aplicações no ecrã."</string>
@@ -804,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"A aplicação é aberta sem ser instalada."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"A aplicação é aberta sem ser instalada. Toque para saber mais."</string>
     <string name="app_info" msgid="6856026610594615344">"Info. da aplicação"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Aceder à Web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Ir para o navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Dados móveis"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi desativado"</string>
@@ -836,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Definições"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Compreendi"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Cp ár. di. da. SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"A aplicação <xliff:g id="APP">%1$s</xliff:g> está a utilizar o(a) <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"As aplicações estão a utilizar o(a) <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Abrir aplicação"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Cancelar"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Definições"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"A aplicação <xliff:g id="APP">%1$s</xliff:g> está a utilizar o(a) <xliff:g id="TYPE">%2$s</xliff:g> há <xliff:g id="TIME">%3$d</xliff:g> min."</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"As aplicações <xliff:g id="APPS">%1$s</xliff:g> estão a utilizar o(a) <xliff:g id="TYPE">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"A aplicação <xliff:g id="APP">%1$s</xliff:g> está a utilizar o(a) <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"câmara"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"localização"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"microfone"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 507c6b0..cd469e5 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Tente fazer a captura de tela novamente"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"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="173674476457581486">"O app ou a organização não permitem capturas de tela"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Gravação de tela"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Notificação contínua para uma sessão de gravação de tela"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Iniciar gravação"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Gravar narração"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Mostrar toques"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Parar"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pausar"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Retomar"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Cancelar"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Compartilhar"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Excluir"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Gravação de tela cancelada"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Gravação de tela salva, toque para ver"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Gravação de tela excluída"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Erro ao excluir a gravação de tela"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Não foi possível acessar as permissões"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Conectar como media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como uma câmera (PTP)"</string>
@@ -582,14 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificações"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Você deixará de ver essas notificações"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Essas notificações serão minimizadas"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Geralmente você dispensa essas notificações. \nQuer que elas continuem a ser exibidas?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Continuar mostrando essas notificações?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Bloquear notificações"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Continuar mostrando"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimizar"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Continuar mostrando notificações desse app?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Não é possível desativar essas notificações"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"pelo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Este app está usando a câmera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Este app está usando o microfone."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Este app está sobreposto a outros apps na sua tela."</string>
@@ -804,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"O app é aberto sem precisar ser instalado."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"O app é aberto sem precisar ser instalado. Toque para saber mais."</string>
     <string name="app_info" msgid="6856026610594615344">"Informações do app"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Acessar a Web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Abrir o navegador"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Dados móveis"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"O Wi-Fi está desativado"</string>
@@ -836,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Configurações"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Ok"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Despejar pilha SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"O app <xliff:g id="APP">%1$s</xliff:g> está usando <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplicativos estão usando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Abrir app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Cancelar"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Ok"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Config."</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"O app <xliff:g id="APP">%1$s</xliff:g> está usando <xliff:g id="TYPE">%2$s</xliff:g> há <xliff:g id="TIME">%3$d</xliff:g> min"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Os apps <xliff:g id="APPS">%1$s</xliff:g> estão usando <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"O app <xliff:g id="APP">%1$s</xliff:g> está usando <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"câmera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"localização"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"microfone"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 53d8277..43a0825 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Încercați să faceți din nou o captură de ecran"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Captura de ecran nu poate fi salvată din cauza spațiului de stocare limitat"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Crearea capturilor de ecran nu este permisă de aplicație sau de organizația dvs."</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Se înregistrează ecranul"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Notificare în curs pentru o sesiune de înregistrare a ecranului"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Începeți înregistrarea"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Înregistrați vocal"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Afișați atingerile"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Opriți"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Întrerupeți"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Reluați"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Anulați"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Trimiteți"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Ștergeți"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Înregistrarea ecranului a fost anulată"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Înregistrarea ecranului a fost salvată. Atingeți pentru vizualizare"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Înregistrarea ecranului a fost ștearsă."</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Eroare la ștergerea înregistrării ecranului"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Nu s-au obținut permisiunile"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opțiuni pentru transferul de fișiere prin USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Montați ca player media (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montați drept cameră foto (PTP)"</string>
@@ -585,15 +601,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificări"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Nu veți mai vedea aceste notificări"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Aceste notificări vor fi minimizate"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"De regulă respingeți aceste notificări. \nDoriți să fie afișate în continuare?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Doriți să continuați afișarea acestor notificări?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Opriți notificările"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Continuați afișarea"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimizați"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Doriți să continuați afișarea notificărilor de la această aplicație?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Aceste notificări nu pot fi dezactivate"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Această aplicație folosește camera foto."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Această aplicație folosește microfonul."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Această aplicație se afișează pe alte aplicații de pe ecran."</string>
@@ -730,8 +752,7 @@
     <item msgid="2139628951880142927">"Afișează procentajul când se încarcă (prestabilit)"</item>
     <item msgid="3327323682209964956">"Nu afișa această pictogramă"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Afișați pictogramele de notificare cu prioritate redusă"</string>
     <string name="other" msgid="4060683095962566764">"Altele"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Separator pentru ecranul împărțit"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Partea stângă pe ecran complet"</string>
@@ -811,7 +832,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Aplicația a fost deschisă fără a fi instalată."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Aplicația a fost deschisă fără a fi instalată. Atingeți pentru a afla mai multe."</string>
     <string name="app_info" msgid="6856026610594615344">"Informații despre aplicație"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Accesați pe web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Accesați browserul"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Date mobile"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Conexiunea Wi-Fi este dezactivată"</string>
@@ -843,4 +864,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Setări"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Date SysUI memorie"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> folosește <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplicațiile folosesc <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Deschideți aplicația"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Anulați"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Setări"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> folosește <xliff:g id="TYPE">%2$s</xliff:g> de <xliff:g id="TIME">%3$d</xliff:g> minute"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> folosesc <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> folosește <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"cameră foto"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"locație"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"microfon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index b180f87..fb74332 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Попробуйте сделать скриншот снова."</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Не удалось сохранить скриншот: недостаточно места."</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Не удалось сделать скриншот: нет разрешения от приложения или организации."</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Запись видео с экрана"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Текущее уведомление для записи видео с экрана"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Начать запись"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Записать закадровую речь"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Показывать нажатия"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Остановить"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Приостановить"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Возобновить"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Отмена"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Поделиться"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Удалить"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Запись видео с экрана отменена"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Запись видео с экрана сохранена. Чтобы открыть ее, нажмите на уведомление."</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Запись видео с экрана удалена"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Не удалось удалить запись видео с экрана"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Не удалось получить необходимые разрешения"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Параметры передачи через USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Подключить как мультимедийный проигрыватель (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Установить как камеру (PTP)"</string>
@@ -588,15 +604,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Уведомления"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Эти уведомления отключены."</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Эти уведомления будут свернуты."</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Обычно вы скрываете эти уведомления.\nПоказывать их?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Показывать эти уведомления?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Отключить уведомления"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Показывать"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Свернуть"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Показывать уведомления от этого приложения?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Эти уведомления нельзя отключить."</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Это приложение использует камеру."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Это приложение использует микрофон."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Это приложение располагается поверх других приложений."</string>
@@ -735,8 +757,7 @@
     <item msgid="2139628951880142927">"Показывать процент во время зарядки (по умолчанию)"</item>
     <item msgid="3327323682209964956">"Не показывать этот значок"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Показывать значки уведомлений с низким приоритетом"</string>
     <string name="other" msgid="4060683095962566764">"Другое"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Разделитель экрана"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Левый во весь экран"</string>
@@ -816,7 +837,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Приложение готово к работе, установка не требуется."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Приложение готово к работе, установка не требуется. Нажмите, чтобы узнать больше."</string>
     <string name="app_info" msgid="6856026610594615344">"О приложении"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Перейти в браузер"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Перейти в браузер"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Моб. Интернет"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Модуль Wi-Fi отключен"</string>
@@ -848,4 +869,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Открыть настройки"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"ОК"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Передача SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"В приложении \"<xliff:g id="APP">%1$s</xliff:g>\" используется <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"В приложениях используется <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Открыть"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Отмена"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ОК"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Настройки"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"В приложении \"<xliff:g id="APP">%1$s</xliff:g>\" уже <xliff:g id="TIME">%3$d</xliff:g> мин. используется <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"В нескольких приложениях (<xliff:g id="APPS">%1$s</xliff:g>) используется <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"В приложении \"<xliff:g id="APP">%1$s</xliff:g>\" используется <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"камера"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"местоположение"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"микрофон"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 0eae821..3efd747 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"තිර රුව නැවත ගැනීමට උත්සාහ කරන්න"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"සීමිත ගබඩා ඉඩ නිසා තිර රුව සුරැකිය නොහැකිය"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"තිර රූ ගැනීමට යෙදුම හෝ ඔබගේ සංවිධානය ඉඩ නොදේ"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"තිර පටිගත කිරීම"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"තිර පටිගත කිරීමේ සැසියක් සඳහා කෙරෙන දැනුම් දීම"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"පටිගත කිරීම ආරම්භ කරන්න"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"පසුබිම් කථනය පටිගත කරන්න"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"තට්ටු කිරීම් පෙන්වන්න"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"නතර කරන්න"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"විරාම කරන්න"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"නැවත අරඹන්න"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"අවලංගු කරන්න"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"බෙදා ගන්න"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"මකන්න"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"තිර පටිගත කිරීම අවලංගු කරන ලදී"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"තිර පටිගත කිරීම සුරකින ලදී, බැලීමට තට්ටු කරන්න"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"තිර පටිගත කිරීම මකන ලදී"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"තිර පටිගත කිරීම මැකීමේ දෝෂයකි"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"අවසර ලබා ගැනීමට අසමත් විය"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ගොනු හුවමාරු විකල්ප"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"මධ්‍ය ධාවකයක් (MTP) ලෙස සවි කරන්න"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"කැමරාවක් (PTP) ලෙස සවි කරන්න"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"දැනුම් දීම්"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"ඔබට තවදුරටත් මෙම දැනුම්දීම් නොදකිනු ඇත"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"මෙම දැනුම්දීම් කුඩා කරනු ලැබේ"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"ඔබ සාමාන්‍යයෙන් මෙවැනි දැනුම්දීම් ඉවත දමයි. \nඒවා දිගටම පෙන්වන්නද?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"මෙම දැනුම්දීම් පෙන්වමින් තබන්නද?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"දැනුම්දීම් නවත්වන්න"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"පෙන්වමින් තබන්න"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"කුඩා කරන්න"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"මෙම යෙදුම වෙතින් දැනුම්දීම් පෙන්වමින් තබන්නද?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"මෙම දැනුම්දීම් ක්‍රියාවිරහිත කළ නොහැකිය"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"මෙම යෙදුම කැමරාව භාවිතා කරයි."</string>
     <string name="appops_microphone" msgid="741508267659494555">"මෙම යෙදුම මයික්‍රෆෝනය භාවිතා කරයි."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"මෙම යෙදුම් ඔබගේ තිරය මත අනෙකුත් යෙදුම්වලට උඩින් සංදර්ශනය වේ."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"ආරෝපණය වන විට ප්‍රතිශතය පෙන්වන්න (පෙරනිමි)"</item>
     <item msgid="3327323682209964956">"මෙම නිරූපකය නොපෙන්වන්න"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"අඩු ප්‍රමුඛතා දැනුම්දීම් අයිකන පෙන්වන්න"</string>
     <string name="other" msgid="4060683095962566764">"වෙනත්"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"බෙදුම්-තිර වෙන්කරණය"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"වම් පූර්ණ තිරය"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"ස්ථාපනය නොකර යෙදුම විවෘත කර ඇත."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"ස්ථාපනය නොකර යෙදුම විවෘත කර ඇත. තව දැන ගැනීමට තට්ටු කරන්න."</string>
     <string name="app_info" msgid="6856026610594615344">"යෙදුම් තොරතුරු"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"වෙබය වෙත යන්න"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"බ්‍රවුසරය වෙත යන්න"</string>
     <string name="mobile_data" msgid="7094582042819250762">"ජංගම දත්ත"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ක්‍රියා විරහිතයි"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"සැකසීම්"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"තේරුණා"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> ඔබේ <xliff:g id="TYPES_LIST">%2$s</xliff:g> භාවිත කරමින් සිටී."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"යෙදුම් ඔබේ <xliff:g id="TYPES_LIST">%s</xliff:g> භාවිත කරමින් සිටී."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"යෙදුම විවෘත කරන්න"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"අවලංගු කරන්න"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"හරි"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"සැකසීම්"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> අවසන් මිනි <xliff:g id="TIME">%3$d</xliff:g> සඳහා ඔබේ <xliff:g id="TYPE">%2$s</xliff:g> භාවිත කරමින් සිටී"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> ඔබේ <xliff:g id="TYPE">%2$s</xliff:g> භාවිත කරමින් සිටී"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> ඔබේ <xliff:g id="TYPES_LIST">%2$s</xliff:g> භාවිත කරමින් සිටී"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"කැමරාව"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"ස්ථානය"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"මයික්‍රෝෆෝනය"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 6c6ad14..e11acd6 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Skúste snímku urobiť znova"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Snímka obrazovky sa nedá uložiť z dôvodu nedostatku miesta v úložisku"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Záznam obrazovky"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Zobrazuje sa upozornenie týkajúce sa relácie záznamu obrazovky"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Spustiť zaznamenávanie"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Hlasový vstup počas záznamu"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Zobrazovať klepnutia"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Ukončiť"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pozastaviť"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Obnoviť"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Zrušiť"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Zdieľať"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Odstrániť"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Záznam obrazovky bol zrušený"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Záznam obrazovky bol uložený, zobrazíte ho klepnutím"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Záznam obrazovky bol odstránený"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Pri odstraňovaní záznamu obrazovky sa vyskytla chyba"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Nepodarilo sa získať povolenia"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosu súborov USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Pripojiť ako prehrávač médií (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Pripojiť ako fotoaparát (PTP)"</string>
@@ -198,9 +214,9 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Režim v lietadle je zapnutý."</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="2960643943620637020">"úplné ticho"</string>
     <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3357131899365865386">"iba budíky"</string>
-    <string name="accessibility_quick_settings_dnd" msgid="6607873236717185815">"Nerušiť"</string>
-    <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Stav Nerušiť je vypnutý."</string>
-    <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Stav Nerušiť je zapnutý."</string>
+    <string name="accessibility_quick_settings_dnd" msgid="6607873236717185815">"Režim bez vyrušení"</string>
+    <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Režim bez vyrušení je vypnutý."</string>
+    <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Režim bez vyrušení je zapnutý."</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="6341675755803320038">"Bluetooth"</string>
     <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"Rozhranie Bluetooth je vypnuté."</string>
     <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"Rozhranie Bluetooth je zapnuté."</string>
@@ -264,7 +280,7 @@
     <string name="start_dreams" msgid="5640361424498338327">"Šetrič obrazovky"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
     <string name="quick_settings_header_onboarding_text" msgid="8030309023792936283">"Pridržaním ikon zobrazíte ďalšie možnosti"</string>
-    <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Nerušiť"</string>
+    <string name="quick_settings_dnd_label" msgid="8735855737575028208">"Režim bez vyrušení"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Iba prioritné"</string>
     <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"Iba budíky"</string>
     <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"Úplné ticho"</string>
@@ -421,7 +437,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Nabudúce nezobrazovať"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"Vymazať všetko"</string>
     <string name="manage_notifications_text" msgid="2386728145475108753">"Spravovať"</string>
-    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Upozornenia sú pozastavené režimom Nerušiť"</string>
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Upozornenia sú pozastavené režimom bez vyrušení"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Spustiť"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Žiadne upozornenia"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"Profil môže byť monitorovaný"</string>
@@ -588,15 +604,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Upozornenia"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Tieto upozornenia sa už nebudú zobrazovať"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Tieto upozornenia budú minimalizované"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"Tieto upozornenia sa budú zobrazovať potichu"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Tieto upozornenia vás upozornia"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Tieto upozornenia zvyčajne odmietate. \nChcete ich naďalej zobrazovať?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Majú sa tieto upozornenia naďalej zobrazovať?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Prestať zobrazovať upozornenia"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Naďalej zobrazovať"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimalizovať"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Zobraziť potichu"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Zobraziť a upozorniť"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Majú sa upozornenia z tejto aplikácie naďalej zobrazovať?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Tieto upozornenia sa nedajú vypnúť"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Táto aplikácia používa fotoaparát."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Táto aplikácia používa mikrofón."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Táto aplikácia sa zobrazuje cez ďalšie aplikácie na obrazovke."</string>
@@ -678,9 +696,9 @@
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"Kalendár"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"Zobrazovať s ovládacími prvkami hlasitosti"</string>
-    <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Nerušiť"</string>
+    <string name="volume_and_do_not_disturb" msgid="3373784330208603030">"Režim bez vyrušení"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"Skratka tlačidiel hlasitosti"</string>
-    <string name="volume_up_silent" msgid="7141255269783588286">"Pri zvýšení hlasitosti ukončiť režim Nerušiť"</string>
+    <string name="volume_up_silent" msgid="7141255269783588286">"Pri zvýšení hlasitosti ukončiť režim bez vyrušení"</string>
     <string name="battery" msgid="7498329822413202973">"Batéria"</string>
     <string name="clock" msgid="7416090374234785905">"Hodiny"</string>
     <string name="headset" msgid="4534219457597457353">"Náhlavná súprava"</string>
@@ -735,8 +753,7 @@
     <item msgid="2139628951880142927">"Zobrazovať percentá počas nabíjania (predvolené)"</item>
     <item msgid="3327323682209964956">"Nezobrazovať túto ikonu"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Zobraziť ikony upozornení s nízkou prioritou"</string>
     <string name="other" msgid="4060683095962566764">"Ďalšie"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Rozdeľovač obrazovky"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Ľavá – na celú obrazovku"</string>
@@ -816,15 +833,15 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Aplikácia bola otvorená bez inštalácie."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Aplikácia bola otvorená bez inštalácie. Klepnutím zobrazíte ďalšie informácie."</string>
     <string name="app_info" msgid="6856026610594615344">"Info o aplikácii"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Prejsť na internet"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Otvoriť prehliadač"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilné dáta"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Pripojenie Wi‑Fi je vypnuté"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"Rozhranie Bluetooth je vypnuté"</string>
-    <string name="dnd_is_off" msgid="6167780215212497572">"Nastavenie Nerušiť je vypnuté"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="862559028345233052">"Režim Nerušiť bol zapnutý automatickým pravidlom (<xliff:g id="ID_1">%s</xliff:g>)."</string>
-    <string name="qs_dnd_prompt_app" msgid="7978037419334156034">"Režim Nerušiť bol zapnutý aplikáciou (<xliff:g id="ID_1">%s</xliff:g>)."</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="2599343675391111951">"Režim Nerušiť bol zapnutý automatickým pravidlom alebo aplikáciou."</string>
+    <string name="dnd_is_off" msgid="6167780215212497572">"Režim bez vyrušení je vypnutý"</string>
+    <string name="qs_dnd_prompt_auto_rule" msgid="862559028345233052">"Režim bez vyrušení bol zapnutý automatickým pravidlom (<xliff:g id="ID_1">%s</xliff:g>)."</string>
+    <string name="qs_dnd_prompt_app" msgid="7978037419334156034">"Režim bez vyrušení bol zapnutý aplikáciou (<xliff:g id="ID_1">%s</xliff:g>)."</string>
+    <string name="qs_dnd_prompt_auto_rule_app" msgid="2599343675391111951">"Režim bez vyrušení bol zapnutý automatickým pravidlom alebo aplikáciou."</string>
     <string name="qs_dnd_until" msgid="3469471136280079874">"Do <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Ponechať"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Nahradiť"</string>
@@ -848,4 +865,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Nastavenia"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Dobre"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Výpis haldy SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> používa zoznam <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplikácie používajú zoznam <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Otvoriť"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Zrušiť"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Nastavenia"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> používa typ <xliff:g id="TYPE">%2$s</xliff:g> posl. <xliff:g id="TIME">%3$d</xliff:g> min."</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Aplikácie <xliff:g id="APPS">%1$s</xliff:g> používajú typ <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> používa zoznam <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"fotoaparát"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"poloha"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofón"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index f94ee60..b050497 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Poskusite znova ustvariti posnetek zaslona"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Shranjevanje posnetka zaslona ni mogoče zaradi omejenega prostora za shranjevanje"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikacija ali vaša organizacija ne dovoljuje posnetkov zaslona"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Snemanje zaslona"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Nenehno obveščanje o seji snemanja zaslona"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Začni snemanje"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Snemanje spremnega govora"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Prikaz dotikov"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Ustavi"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Začasno ustavi"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Nadaljuj"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Prekliči"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Deli"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Izbriši"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Snemanje zaslona je preklicano"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Videoposnetek zaslona je shranjen, dotaknite se za ogled"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Videoposnetek zaslona je izbrisan"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Napaka pri brisanju videoposnetka zaslona"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Dovoljenj ni bilo mogoče pridobiti"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosa datotek prek USB-ja"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Vpni kot predvajalnik (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Vpni kot fotoaparat (PTP)"</string>
@@ -588,15 +604,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Obvestila"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Ta obvestila ne bodo več prikazana"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Ta obvestila bodo minimirana"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Ta obvestila običajno opustite. \nAli želite, da se še naprej prikazujejo?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Želite, da so ta obvestila še naprej prikazana?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Ustavi prikazovanje obvestil"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Prikazuj še naprej"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimiraj"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Želite, da so obvestila te aplikacije še naprej prikazana?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Teh obvestil ni mogoče izklopiti"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Ta aplikacija uporablja fotoaparat."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Ta aplikacija uporablja mikrofon."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Ta aplikacija prekriva druge aplikacije na zaslonu."</string>
@@ -735,8 +757,7 @@
     <item msgid="2139628951880142927">"Prikaži odstotek med polnjenjem (privzeto)"</item>
     <item msgid="3327323682209964956">"Ne prikaži te ikone"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Pokaži ikone obvestil z nizko stopnjo prednosti"</string>
     <string name="other" msgid="4060683095962566764">"Drugo"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Razdelilnik zaslonov"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Levi v celozaslonski način"</string>
@@ -816,7 +837,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Aplikacija je odprta brez namestitve."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Aplikacija je odprta brez namestitve. Dotaknite se, če želite izvedeti več."</string>
     <string name="app_info" msgid="6856026610594615344">"Podatki o aplikaciji"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Pojdi v splet"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Odpri brskalnik"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilni podatki"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi je izklopljen"</string>
@@ -848,4 +869,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Nastavitve"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"V redu"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Izvoz kopice SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> uporablja <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplikacije uporabljajo <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Odpri apl."</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Prekliči"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"V redu"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Nastavitve"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> uporablja <xliff:g id="TYPE">%2$s</xliff:g> zadnjih toliko minut: <xliff:g id="TIME">%3$d</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Aplikacije <xliff:g id="APPS">%1$s</xliff:g> uporabljajo <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> uporablja <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"fotoaparat"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"lokacijo"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 7869cd9..146e91c 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Provo ta nxjerrësh përsëri pamjen e ekranit"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"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="173674476457581486">"Nxjerrja e pamjeve të ekranit nuk lejohet nga aplikacioni ose organizata jote."</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Regjistrimi i ekranit"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Njoftim i vazhdueshëm për një seancë regjistrimi të ekranit"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Nis regjistrimin"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Regjistro zërin e mikrofonit"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Shfaq trokitjet"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Ndalo"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Ndërprit"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Vazhdo"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Anulo"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Ndaj"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Fshi"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Regjistrimi i ekranit u anulua"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Regjistrimi i ekranit u ruajt, trokit për ta parë"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Regjistrimi i ekranit u fshi"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Gabim gjatë fshirjes së regjistrimit të ekranit"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Marrja e lejeve dështoi"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opsionet e transferimit të dosjeve të USB-së"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Lidh si një lexues \"media\" (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montoje si kamerë (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Njoftime"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Nuk do t\'i shikosh më këto njoftime"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Këto njoftime do të minimizohen"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Këto njoftime ti zakonisht i largon. \nDëshiron të vazhdosh t\'i shfaqësh ato?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Do të vazhdosh t\'i shfaqësh këto njoftime?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Ndalo njoftimet"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Vazhdo të shfaqësh"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimizo"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Do të vazhdosh t\'i shfaqësh njoftimet nga ky aplikacion?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Këto njoftime nuk mund të çaktivizohen"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Ky aplikacion po përdor kamerën."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Ky aplikacion po përdor mikrofonin."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Ky aplikacion po shfaqet mbi aplikacionet e tjera në ekran."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Shfaq përqindjen gjatë ngarkimit (e parazgjedhur)"</item>
     <item msgid="3327323682209964956">"Mos e shfaq këtë ikonë"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Shfaq ikonat e njoftimeve me përparësi të ulët"</string>
     <string name="other" msgid="4060683095962566764">"Të tjera"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Ndarësi i ekranit të ndarë"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Ekrani i plotë majtas"</string>
@@ -797,7 +818,7 @@
     <string name="tuner_app" msgid="3507057938640108777">"Aplikacioni <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Sinjalizimet"</string>
     <string name="notification_channel_battery" msgid="5786118169182888462">"Bateria"</string>
-    <string name="notification_channel_screenshot" msgid="6314080179230000938">"Pamjet e ekranit"</string>
+    <string name="notification_channel_screenshot" msgid="6314080179230000938">"Pamje ekrani"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Mesazhe të përgjithshme"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Hapësira ruajtëse"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Sugjerimet"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Aplikacioni u hap pa u instaluar."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Aplikacioni u hap pa u instaluar. Trokit për të mësuar më shumë."</string>
     <string name="app_info" msgid="6856026610594615344">"Informacioni mbi aplikacionin"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Shko në ueb"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Shko te shfletuesi"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Të dhënat celulare"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi është joaktiv"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Cilësimet"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"E kuptova"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Hidh grumbullin SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> po përdor <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Aplikacionet po përdorin <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Hap aplikacionin"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Anulo"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Në rregull"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Cilësimet"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> po përdor <xliff:g id="TYPE">%2$s</xliff:g> për <xliff:g id="TIME">%3$d</xliff:g> minutat e fundit"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> po përdor <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> po përdor <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamerën"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"vendndodhjen"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofonin"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 420056e..a838a0b 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Пробајте да поново направите снимак екрана"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Чување снимка екрана није успело због ограниченог меморијског простора"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Апликација или организација не дозвољавају прављење снимака екрана"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Снимање екрана"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Обавештење о сесији снимања екрана је активно"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Започни снимање"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Сними пренос гласа"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Приказуј додире"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Заустави"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Паузирај"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Настави"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Откажи"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Дели"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Избриши"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Снимање екрана је отказано"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Снимак екрана је сачуван, додирните да бисте прегледали"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Снимак екрана је избрисан"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Дошло је до проблема при брисању снимка екрана"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Преузимање дозвола није успело"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Опције USB преноса датотека"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Прикључи као медија плејер (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Прикључи као камеру (PTP)"</string>
@@ -585,15 +601,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Обавештења"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Више нећете видети ова обавештења"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Ова обавештења ће се умањити"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Обично одбацујете ова обавештења. \nЖелите ли да се и даље приказују?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Желите ли да се ова обавештења и даље приказују?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Престани да приказујеш обавештења"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Настави да приказујеш"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Умањи"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Желите ли да се обавештења из ове апликације и даље приказују?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Не можете да искључите ова обавештења"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Ова апликација користи камеру."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Ова апликација користи микрофон."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Ова апликација се приказује преко других апликација на екрану."</string>
@@ -730,8 +752,7 @@
     <item msgid="2139628951880142927">"Прикажи проценат током пуњења (подразумевано)"</item>
     <item msgid="3327323682209964956">"Не приказуј ову икону"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Прикажи иконе обавештења ниског приоритета"</string>
     <string name="other" msgid="4060683095962566764">"Друго"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Разделник подељеног екрана"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Режим целог екрана за леви екран"</string>
@@ -811,7 +832,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Апликација се отворила без инсталирања."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Апликација се отворила без инсталирања. Додирните да бисте сазнали више."</string>
     <string name="app_info" msgid="6856026610594615344">"Информације о апликацији"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Иди на веб"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Иди на прегледач"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобилни подаци"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi је искључен"</string>
@@ -843,4 +864,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Подешавања"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Важи"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Издвоји SysUI мем."</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> користи <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Апликације користе <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Отвори"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Откажи"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Потврди"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Подешавања"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> током неколико последњих минута (<xliff:g id="TIME">%3$d</xliff:g>) користи <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> користе <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> користи <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"камеру"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"локацију"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"микрофон"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 238cc9b..7c4e88a 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Testa att ta en skärmdump igen"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Det går inte att spara skärmdumpen eftersom lagringsutrymmet inte räcker"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Appen eller organisationen tillåter inte att du tar skärmdumpar"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Skärminspelning"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Avisering om att skärminspelning pågår"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Börja spela in"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Spela in med mikrofondubbning"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Visa tryck"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Stoppa"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pausa"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Återuppta"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Avbryt"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Dela"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Radera"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Skärminspelningen har avbrutits"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Skärminspelningen har sparats, tryck här om du vill titta på den"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Skärminspelningen har raderats"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Det gick inte att radera skärminspelningen"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Behörighet saknas"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Överföringsalternativ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Montera som mediaspelare (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montera som kamera (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Aviseringar"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"De här aviseringarna visas inte längre"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Dessa aviseringar minimeras"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Du brukar avvisa de här aviseringarna. \nVill du fortsätta att visa dem?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Vill du fortsätta visa de här aviseringarna?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Stoppa aviseringar"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Fortsätt visa"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Minimera"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Vill du fortsätta visa aviseringar för den här appen?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"De här aviseringarna kan inte inaktiveras"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Kameran används av appen."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Mikrofonen används av appen."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Appen visas över andra appar på skärmen."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Visa procent under laddning (standard)"</item>
     <item msgid="3327323682209964956">"Visa inte den här ikonen"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Visa ikoner för aviseringar med låg prioritet"</string>
     <string name="other" msgid="4060683095962566764">"Annat"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Avdelare för delad skärm"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Helskärm på vänster skärm"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Appen öppnades utan installation."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Appen öppnades utan installation. Tryck om du vill veta mer."</string>
     <string name="app_info" msgid="6856026610594615344">"Info om appen"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Öppna webbplatsen"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Öppna webbläsaren"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobildata"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi är inaktiverat"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Inställningar"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dumpa SysUI-heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="TYPES_LIST">%2$s</xliff:g> används av <xliff:g id="APP">%1$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"<xliff:g id="TYPES_LIST">%s</xliff:g> används av appar."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Öppna app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Avbryt"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Inställn."</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="TYPE">%2$s</xliff:g> har använts av <xliff:g id="APP">%1$s</xliff:g> under de senaste <xliff:g id="TIME">%3$d</xliff:g> minuterna"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="TYPE">%2$s</xliff:g> används av <xliff:g id="APPS">%1$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="TYPES_LIST">%2$s</xliff:g> används av <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"plats"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 54e8544..fbc1022 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Jaribu kupiga picha ya skrini tena"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Imeshindwa kuhifadhi picha ya skrini kwa sababu nafasi haitoshi"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Programu au shirika lako halikuruhusu kupiga picha za skrini"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Kurekodi Skrini"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Arifa inayoendelea ya kipindi cha kurekodi skrini"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Anza Kurekodi"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Rekodi sauti"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Onyesha unapogusa"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Acha"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Sitisha"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Endelea"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Ghairi"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Shiriki"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Futa"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Imeghairi mchakato wa kurekodi skrini"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Imehifadhi rekodi ya skrini, gusa ili uangalie"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Imefuta rekodi ya skrini"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Hitilafu imetokea wakati wa kufuta rekodi ya skrini"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Imeshindwa kupata ruhusa"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Machaguo ya uhamisho wa faili la USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Angika kama kichezaji cha maudhui (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Angika kama kamera (PTP)"</string>
@@ -582,14 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Arifa"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Hutaona tena arifa hizi"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Arifa hizi zitapunguzwa"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Wewe huondoa arifa hizi. \nUngependa kuzionyesha?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Ungependa kuendelea kuonyesha arifa hizi?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Acha kuonyesha arifa"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Endelea kuonyesha"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Punguza"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Ungependa kuendelea kuonyesha arifa kutoka programu hii?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Huwezi kuzima arifa hizi"</string>
-    <string name="notification_delegate_header" msgid="9167022191405284627">"kupitia <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="appops_camera" msgid="8100147441602585776">"Programu hii inatumia kamera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Programu hii inatumia maikrofoni."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Programu hii inachomoza kwenye programu zingine zilizo katika skrini yako."</string>
@@ -804,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Programu inafunguka bila kusakinishwa."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Programu inafunguka bila kusakinishwa. Gusa ili upate maelezo zaidi."</string>
     <string name="app_info" msgid="6856026610594615344">"Maelezo ya programu"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Nenda kwenye wavuti"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Tumia kivinjari"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Data ya simu"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g><xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi imezimwa"</string>
@@ -836,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Mipangilio"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Nimeelewa"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> inatumia <xliff:g id="TYPES_LIST">%2$s</xliff:g> yako."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Programu zinatumia <xliff:g id="TYPES_LIST">%s</xliff:g> yako."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Fungua programu"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Ghairi"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Sawa"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Mipangilio"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> imekuwa ikitumia <xliff:g id="TYPE">%2$s</xliff:g> yako kwa dakika <xliff:g id="TIME">%3$d</xliff:g> zilizopita"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> zinatumia <xliff:g id="TYPE">%2$s</xliff:g> yako"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> inatumia <xliff:g id="TYPES_LIST">%2$s</xliff:g> yako"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"mahali"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"maikrofoni"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index becd903..8ba895b 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"ஸ்கிரீன் ஷாட்டை மீண்டும் எடுக்க முயலவும்"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ஸ்கிரீன் ஷாட்டுகளை எடுப்பதை, பயன்பாடு அல்லது உங்கள் நிறுவனம் அனுமதிக்கவில்லை"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"திரை ரெக்கார்டிங்"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"திரை ரெக்கார்டிங் அமர்விற்கான தொடர் அறிவிப்பு"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"ரெக்கார்டிங்கைத் தொடங்கு"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"வாய்ஸ் ஓவரை ரெக்கார்டு செய்"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"தட்டல்களைக் காட்டு"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"நிறுத்து"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"இடைநிறுத்து"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"மீண்டும் தொடங்கு"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"ரத்துசெய்"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"பகிர்"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"நீக்கு"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"திரை ரெக்கார்டிங் ரத்துசெய்யப்பட்டது"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"திரை ரெக்கார்டிங் சேமிக்கப்பட்டது, பார்க்கத் தட்டவும்"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"திரை ரெக்கார்டிங் நீக்கப்பட்டது"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"திரை ரெக்கார்டிங்கை நீக்குவதில் பிழை"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"அனுமதிகளைப் பெற இயலவில்லை"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB கோப்பு இடமாற்ற விருப்பங்கள்"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"(MTP) மீடியா பிளேயராக ஏற்று"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"(PTP) கேமராவாக ஏற்று"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"அறிவிப்புகள்"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"இந்த அறிவிப்புகளை இனி பார்க்கமாட்டீர்கள்"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"இந்த அறிவிப்புகள் சிறிதாக்கப்படும்"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"வழக்கமாக, இந்த அறிவிப்புகளை நிராகரிக்கிறீர்கள். \nதொடர்ந்து இவற்றைக் காட்டலாமா?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"இந்த அறிவிப்புகளைத் தொடர்ந்து காட்டவா?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"அறிவிப்புகளை நிறுத்து"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"அறிவிப்புகளைத் தொடர்ந்து காட்டு"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"சிறிதாக்கு"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"இந்தப் பயன்பாட்டின் அறிவிப்புகளைத் தொடர்ந்து காட்டவா?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"இந்த அறிவிப்புகளை ஆஃப் செய்ய முடியாது"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"இந்த ஆப்ஸானது கேமராவை உபயோகிக்கிறது."</string>
     <string name="appops_microphone" msgid="741508267659494555">"இந்த ஆப்ஸானது, மைக்ரோஃபோனை உபயோகிக்கிறது."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"இந்த ஆப்ஸானது, உங்கள் திரையில் பிற ஆப்ஸின் இடைமுகத்தின் மேல் தோன்றுகிறது."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"சார்ஜ் செய்யும் போது சதவீதத்தைக் காட்டு (இயல்பு)"</item>
     <item msgid="3327323682209964956">"இந்த ஐகானைக் காட்டாதே"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"குறைந்த முன்னுரிமை உள்ள அறிவிப்பு ஐகான்களைக் காட்டு"</string>
     <string name="other" msgid="4060683095962566764">"மற்றவை"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"திரையைப் பிரிக்கும் பிரிப்பான்"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"இடது புறம் முழுத் திரை"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது. மேலும் அறியத் தட்டவும்."</string>
     <string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"இணையத்திற்குச் செல்"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"உலாவிக்குச் செல்"</string>
     <string name="mobile_data" msgid="7094582042819250762">"மொபைல் டேட்டா"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"வைஃபை முடக்கத்தில் உள்ளது"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"அமைப்புகள்"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"சரி"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"உங்கள் <xliff:g id="TYPES_LIST">%2$s</xliff:g>ஐ <xliff:g id="APP">%1$s</xliff:g> ஆப்ஸ் பயன்படுத்துகிறது."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"உங்கள் <xliff:g id="TYPES_LIST">%s</xliff:g> ஆகியவற்றை ஆப்ஸ் பயன்படுத்துகின்றன."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"ஆப்ஸை திற"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"ரத்துசெய்"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"சரி"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"அமைப்புகள்"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"கடந்த <xliff:g id="TIME">%3$d</xliff:g> நிமிடங்களாக உங்கள் <xliff:g id="TYPE">%2$s</xliff:g>ஐ <xliff:g id="APP">%1$s</xliff:g> ஆப்ஸ் பயன்படுத்துகிறது"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"உங்கள் <xliff:g id="TYPE">%2$s</xliff:g> ஆகியவற்றை <xliff:g id="APPS">%1$s</xliff:g> ஆப்ஸ் பயன்படுத்துகின்றன"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"உங்கள் <xliff:g id="TYPES_LIST">%2$s</xliff:g>ஐ <xliff:g id="APP">%1$s</xliff:g> ஆப்ஸ் பயன்படுத்துகிறது"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"கேமரா"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"இருப்பிடம்"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"மைக்ரோஃபோன்"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index b895ae6..12dd31a 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"స్క్రీన్‌షాట్ తీయడానికి మళ్లీ ప్రయత్నించండి"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"నిల్వ స్థలం పరిమితంగా ఉన్న కారణంగా స్క్రీన్‌షాట్‌ను సేవ్ చేయడం సాధ్యపడదు"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"స్క్రీన్‌షాట్‌లు తీయడానికి యాప్ లేదా మీ సంస్థ అనుమతించలేదు"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"స్క్రీన్ రికార్డింగ్"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"స్క్రీన్ రికార్డ్ సెషన్ కోసం ఆన్‌గోయింగ్ నోటిఫికేషన్"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"రికార్డింగ్‌ను ప్రారంభించు"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"వాయిస్ఓవర్‌ని రికార్డ్ చేయి"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"నొక్కినవి చూపు"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"ఆపివేయి"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"పాజ్ చేయి"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"కొనసాగించు"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"రద్దు చేయి"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"షేర్ చేయి"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"తొలగించు"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"స్క్రీన్ రికార్డ్ రద్దు చేయబడింది"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"స్క్రీన్ రికార్డింగ్ సేవ్ చేయబడింది, చూడటం కోసం నొక్కండి"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"స్క్రీన్ రికార్డింగ్ తొలగించబడింది"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"స్క్రీన్ రికార్డింగ్‌ని తొలగిస్తున్నప్పుడు ఎర్రర్ ఏర్పడింది"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"అనుమతులను పొందడం విఫలమైంది"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ఫైల్ బదిలీ ఎంపికలు"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"మీడియా ప్లేయర్‌గా (MTP) మౌంట్ చేయి"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"కెమెరాగా (PTP) మౌంట్ చేయి"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"నోటిఫికేషన్‌లు"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"ఇకపై మీకు ఈ నోటిఫికేషన్‌లు కనిపించవు"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"ఈ నోటిఫికేషన్‌లు కుదించబడ్డాయి"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"మీరు సాధారణంగా ఈ నోటిఫికేషన్‌లను విస్మరిస్తారు. \nవాటి ప్రదర్శనను కొనసాగించాలా?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"ఈ నోటిఫికేషన్‌లను చూపిస్తూ ఉండాలా?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"నోటిఫికేషన్‌లను ఆపివేయి"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"చూపిస్తూనే ఉండు"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"కుదించు"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"ఈ యాప్ నుండి నోటిఫికేషన్‌లను చూపిస్తూ ఉండాలా?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"ఈ నోటిఫికేషన్‌లను ఆఫ్ చేయలేరు"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"ఈ యాప్ ఈ కెమెరాను ఉపయోగిస్తోంది."</string>
     <string name="appops_microphone" msgid="741508267659494555">"ఈ యాప్ మైక్రోఫోన్‌ను ఉపయోగిస్తుంది."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"ఈ యాప్ మీ స్క్రీన్‌లోని ఇతర యాప్‌లపై ప్రదర్శించబడుతోంది."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"ఛార్జ్ అవుతున్నప్పుడు శాతాన్ని చూపు (డిఫాల్ట్)"</item>
     <item msgid="3327323682209964956">"ఈ చిహ్నాన్ని చూపవద్దు"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"తక్కువ ప్రాధాన్యత నోటిఫికేషన్ చిహ్నాలను చూపించు"</string>
     <string name="other" msgid="4060683095962566764">"ఇతరం"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"విభజన స్క్రీన్ విభాగిని"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"ఎడమవైపు పూర్తి స్క్రీన్"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"ఇన్‌స్టాల్ చేయకుండా యాప్ తెరవబడింది."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"ఇన్‌స్టాల్ చేయకుండా యాప్ తెరవబడింది. మరింత తెలుసుకోవడానికి నొక్కండి."</string>
     <string name="app_info" msgid="6856026610594615344">"యాప్ సమాచారం"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"వెబ్‌కు వెళ్లు"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"బ్రౌజర్‌కు వెళ్లండి"</string>
     <string name="mobile_data" msgid="7094582042819250762">"మొబైల్ డేటా"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ఆఫ్‌లో ఉంది"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"సెట్టింగ్‌లు"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"అర్థమైంది"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"డంప్ SysUI హీప్"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> మీ <xliff:g id="TYPES_LIST">%2$s</xliff:g>ని ఉపయోగిస్తోంది."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"అప్లికేషన్‌లు మీ <xliff:g id="TYPES_LIST">%s</xliff:g>ని ఉపయోగిస్తున్నాయి."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"యాప్‌ని తెరవండి"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"రద్దు చేయండి"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"సరే"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"సెట్టింగ్‌లు"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"గత <xliff:g id="TIME">%3$d</xliff:g> నిమిషాలుగా <xliff:g id="APP">%1$s</xliff:g> మీ <xliff:g id="TYPE">%2$s</xliff:g>ని ఉపయోగిస్తోంది"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> మీ <xliff:g id="TYPE">%2$s</xliff:g>ని ఉపయోగిస్తున్నాయి"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> మీ <xliff:g id="TYPES_LIST">%2$s</xliff:g>ను ఉపయోగిస్తోంది"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"కెమెరా"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"స్థానం"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"మైక్రోఫోన్"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 4df01ed..8efeabe 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"ลองบันทึกภาพหน้าจออีกครั้ง"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"บันทึกภาพหน้าจอไม่ได้เนื่องจากพื้นที่เก็บข้อมูลมีจำกัด"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"แอปหรือองค์กรของคุณไม่อนุญาตให้จับภาพหน้าจอ"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"การบันทึกหน้าจอ"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"การแจ้งเตือนต่อเนื่องสำหรับเซสชันการบันทึกหน้าจอ"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"เริ่มต้นการบันทึก"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"บันทึกเสียงบรรยาย"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"แสดงการแตะ"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"หยุด"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"หยุด"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"ทำต่อ"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"ยกเลิก"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"แชร์"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"ลบ"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"ยกเลิกการบันทึกหน้าจอแล้ว"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"บันทึกการบันทึกหน้าจอแล้ว แตะเพื่อดู"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"ลบการบันทึกหน้าจอแล้ว"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"เกิดข้อผิดพลาดในการลบการบันทึกหน้าจอ"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"ขอสิทธิ์ไม่สำเร็จ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"ตัวเลือกการถ่ายโอนไฟล์ USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ต่อเชื่อมเป็นโปรแกรมเล่นสื่อ (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ต่อเชื่อมเป็นกล้องถ่ายรูป (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"การแจ้งเตือน"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"คุณจะไม่เห็นการแจ้งเตือนเหล่านี้อีก"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"การแจ้งเตือนเหล่านี้จะย่อเล็กสุด"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"โดยปกติแล้ว คุณจะปิดการแจ้งเตือนเหล่านี้ \nต้องการให้แสดงต่อไหม"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"แสดงการแจ้งเตือนเหล่านี้ต่อไปไหม"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"ปิดการแจ้งเตือน"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"แสดงต่อไป"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"ย่อเล็กสุด"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"แสดงการแจ้งเตือนจากแอปนี้ต่อไปไหม"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"ปิดการแจ้งเตือนเหล่านี้ไม่ได้"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"แอปนี้กำลังใช้กล้อง"</string>
     <string name="appops_microphone" msgid="741508267659494555">"แอปนี้กำลังใช้ไมโครโฟน"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"แอปนี้กำลังแสดงทับแอปอื่นๆ ในหน้าจอ"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"แสดงเปอร์เซ็นต์เมื่อชาร์จ (ค่าเริ่มต้น)"</item>
     <item msgid="3327323682209964956">"อย่าแสดงไอคอนนี้"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"แสดงไอคอนการแจ้งเตือนลำดับความสำคัญต่ำ"</string>
     <string name="other" msgid="4060683095962566764">"อื่นๆ"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"เส้นแบ่งหน้าจอ"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"เต็มหน้าจอทางซ้าย"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"เปิดแอปได้โดยไม่ต้องติดตั้ง"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"เปิดแอปได้โดยไม่ต้องติดตั้ง แตะเพื่อดูข้อมูลเพิ่มเติม"</string>
     <string name="app_info" msgid="6856026610594615344">"ข้อมูลแอป"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ไปที่เว็บ"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"ไปที่เบราว์เซอร์"</string>
     <string name="mobile_data" msgid="7094582042819250762">"เน็ตมือถือ"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi ปิดอยู่"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"การตั้งค่า"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"รับทราบ"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> ใช้<xliff:g id="TYPES_LIST">%2$s</xliff:g>ของคุณอยู่"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"หลายแอปพลิเคชันใช้<xliff:g id="TYPES_LIST">%s</xliff:g>ของคุณอยู่"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"เปิดแอป"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"ยกเลิก"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ตกลง"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"การตั้งค่า"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> ใช้<xliff:g id="TYPE">%2$s</xliff:g>ของคุณอยู่ในช่วง <xliff:g id="TIME">%3$d</xliff:g> นาทีที่ผ่านมา"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> ใช้<xliff:g id="TYPE">%2$s</xliff:g>ของคุณอยู่"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> ใช้<xliff:g id="TYPES_LIST">%2$s</xliff:g>ของคุณอยู่"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"กล้องถ่ายรูป"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"ตำแหน่ง"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"ไมโครโฟน"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 71a26ac..db6ce32f 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Subukang kumuhang muli ng screenshot"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Hindi ma-save ang screenshot dahil sa limitadong espasyo ng storage"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Hindi pinahihintulutan ng app o ng iyong organisasyon ang pagkuha ng mga screenshot"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Pag-record ng Screen"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Kasalukuyang notification para sa session ng pag-record ng screen"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Simulan ang Pag-record"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"I-record ang voiceover"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Ipakita ang mga pag-tap"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Ihinto"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"I-pause"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Ituloy"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Kanselahin"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Ibahagi"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"I-delete"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Kinansela ang pag-record ng screen"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Na-save ang pag-record ng screen, i-tap para tingnan"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Na-delete ang pag-record ng screen"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Error sa pag-delete sa pag-record ng screen"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Hindi nakuha ang mga pahintulot"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opsyon paglipat ng USB file"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"I-mount bilang isang media player (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"I-mount bilang camera (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Mga Notification"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Hindi mo na makikita ang mga notification na ito"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Imi-minimize ang mga notification na ito"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Karaniwan mong dini-dismiss ang mga ganitong notification. \nPatuloy na ipakita ang mga ito?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Patuloy na ipakita ang mga notification na ito?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Ihinto ang mga notification"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Patuloy na ipakita"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"I-minimize"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Patuloy na ipakita ang mga notification mula sa app na ito?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Hindi maaaring i-off ang mga notification na ito"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Ginagamit ng app na ito ang camera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Ginagamit ng app na ito ang mikropono."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Ipinapakita ang app na ito sa ibabaw ng iba pang app sa iyong screen."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Ipakita ang porsyento kapag nagcha-charge (default)"</item>
     <item msgid="3327323682209964956">"Huwag ipakita ang icon na ito"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Ipakita ang mga icon ng notification na may mababang priority"</string>
     <string name="other" msgid="4060683095962566764">"Iba pa"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Divider ng split-screen"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"I-full screen ang nasa kaliwa"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Nabuksan ang app nang hindi ini-install."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Nabuksan ang app nang hindi ini-install. I-tap para matuto pa."</string>
     <string name="app_info" msgid="6856026610594615344">"Impormasyon ng app"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Pumunta sa web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Pumunta sa browser"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobile data"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Naka-off ang Wi-Fi"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Mga Setting"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Itapon SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"Ginagamit ng <xliff:g id="APP">%1$s</xliff:g> ang iyong <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Ginagamit ng mga application ang iyong <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Buksan: app"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Kanselahin"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Okay"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Mga Setting"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"Ginagamit ng <xliff:g id="APP">%1$s</xliff:g> ang iyong <xliff:g id="TYPE">%2$s</xliff:g> para sa huling <xliff:g id="TIME">%3$d</xliff:g> (na) minuto"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Ginagamit ng <xliff:g id="APPS">%1$s</xliff:g> ang iyong <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"Ginagamit ng <xliff:g id="APP">%1$s</xliff:g> ang iyong <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"camera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"lokasyon"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikropono"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index b3809c4..c7a8150 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Tekrar ekran görüntüsü almayı deneyin"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Depolama alanı sınırlı olduğundan ekran görüntüsü kaydedilemiyor"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Uygulama veya kuruluşunuz, ekran görüntüsü alınmasına izin vermiyor."</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Ekran Kaydı"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Ekran kaydı oturumu için devam eden bildirim"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Kaydı Başlat"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Seslendirme kaydet"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Dokunmaları göster"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Durdur"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Duraklat"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Devam ettir"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"İptal"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Paylaş"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Sil"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Ekran kaydı iptal edildi"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Ekran kaydı tamamlandı, görüntülemek için dokunun"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Ekran kaydı silindi"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Ekran kaydı silinirken hata oluştu"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"İzinler alınamadı"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB dosya aktarım seçenekleri"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Medya oynatıcı olarak ekle (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Kamera olarak ekle (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Bildirimler"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Bu bildirimleri artık görmeyeceksiniz"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Bu bildirimler küçültülecek"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Bu bildirimleri genellikle kapatıyorsunuz. \nBildirimler gösterilmeye devam edilsin mi?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Bu bildirimler gösterilmeye devam edilsin mi?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Bildirimleri durdur"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Göstermeye devam et"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Küçült"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Bu uygulamadan gelen bildirimler gösterilmeye devam edilsin mi?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Bu bildirimler kapatılamaz"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Bu uygulama kamerayı kullanıyor."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Bu uygulama mikrofonu kullanıyor."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Bu uygulama, ekranınızdaki diğer uygulamaların üzerinde görüntüleniyor."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Şarj olurken yüzdeyi göster (varsayılan)"</item>
     <item msgid="3327323682209964956">"Bu simgeyi gösterme"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Düşük öncelikli bildirim simgelerini göster"</string>
     <string name="other" msgid="4060683095962566764">"Diğer"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Bölünmüş ekran ayırıcı"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Solda tam ekran"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Uygulama yüklenmeden açıldı."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Uygulama yüklenmeden açıldı. Daha fazla bilgi için dokunun."</string>
     <string name="app_info" msgid="6856026610594615344">"Uygulama bilgileri"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Web\'e git"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Tarayıcıya git"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobil veriler"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Kablosuz bağlantı kapalı"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Ayarlar"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Anladım"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"SysUI Yığın Dökümü"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> şunları kullanıyor: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Uygulamalar şunları kullanıyor: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Uygulama aç"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"İptal"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Tamam"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Ayarlar"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> en az <xliff:g id="TIME">%3$d</xliff:g> dakikadır şunları kullanıyor: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> şunları kullanıyor: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> şunları kullanıyor: <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"konum"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index a52ec2a..dfac474 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Спробуйте зробити знімок екрана ще раз"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Не вдалося зберегти знімок екрана через обмежений обсяг пам’яті"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Додаток або адміністратор вашої організації не дозволяють робити знімки екрана"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Запис екрана"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Сповіщення про сеанс запису екрана"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Почати запис"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Записувати голосовий супровід"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Показувати дотики"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Зупинити"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Призупинити"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Відновити"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Скасувати"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Поділитися"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Видалити"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Запис екрана скасовано"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Запис екрана збережено. Натисніть, щоб переглянути"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Запис екрана видалено"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Не вдалося видалити запис екрана"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Не вдалось отримати дозволи"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Парам.передав.файлів через USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Підключити як медіапрогравач (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Підключити як камеру (PTP)"</string>
@@ -588,15 +604,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Сповіщення"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Ви більше не бачитимете цих сповіщень"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Ці сповіщення буде згорнуто"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Ви зазвичай закриваєте ці сповіщення. \nПоказувати їх?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Чи показувати ці сповіщення надалі?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Не показувати сповіщення"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Показувати надалі"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Згорнути"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Чи показувати сповіщення з цього додатка надалі?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ці сповіщення не можна вимкнути"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Цей додаток використовує камеру."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Цей додаток використовує мікрофон."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Цей додаток відображається поверх інших додатків на екрані."</string>
@@ -735,8 +757,7 @@
     <item msgid="2139628951880142927">"Показувати відсотки під час заряджання (за умовчанням)"</item>
     <item msgid="3327323682209964956">"Не показувати цей значок"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Показувати значки сповіщень із низьким пріоритетом"</string>
     <string name="other" msgid="4060683095962566764">"Інше"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Розділювач екрана"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Ліве вікно на весь екран"</string>
@@ -816,7 +837,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Додаток відкрито без встановлення."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Додаток відкрито без встановлення. Торкніться, щоб дізнатися більше."</string>
     <string name="app_info" msgid="6856026610594615344">"Про додаток"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Перейти на веб-сайт"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Веб-переглядач"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Мобільний трафік"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi вимкнено"</string>
@@ -848,4 +869,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Налаштування"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"Додаток <xliff:g id="APP">%1$s</xliff:g> використовує <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Додатки використовують <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Відкрити додаток"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Скасувати"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Параметри"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"Додаток <xliff:g id="APP">%1$s</xliff:g> використовує <xliff:g id="TYPE">%2$s</xliff:g> протягом стількох останніх хвилин: <xliff:g id="TIME">%3$d</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Додатки <xliff:g id="APPS">%1$s</xliff:g> використовують <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"Додаток <xliff:g id="APP">%1$s</xliff:g> використовує <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"камеру"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"місце"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"мікрофон"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index eb0c60b..8b52391 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"دوبارہ اسکرین شاٹ لینے کی کوشش کریں"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"اسٹوریج کی محدود جگہ کی وجہ سے اسکرین شاٹ کو محفوظ نہیں کیا جا سکتا"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"اسکرین ریکارڈنگ"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"اسکرین ریکارڈ سیشن کیلئے جاری اطلاع"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"ریکارڈنگ شروع کریں"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"وائس اوور ریکارڈ کریں"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"تھپتھپاہٹیں دکھائیں"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"روکیں"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"موقوف کریں"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"دوبارہ شروع کریں"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"منسوخ کریں"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"اشتراک کریں"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"حذف کریں"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"اسکرین ریکارڈنگ منسوخ ہو گئی"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"اسکرین ریکارڈنگ محفوظ ہو گئی، دیکھنے کیلئے تھپتھپائیں"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"اسکرین ریکارڈنگ حذف ہو گئی"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"اسکرین ریکارڈنگ کو حذف کرنے میں خرابی"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"اجازتیں حاصل کرنے میں ناکامی"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏USB فائل منتقل کرنیکے اختیارات"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏ایک میڈیا پلیئر (MTP) کے بطور ماؤنٹ کریں"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"‏ایک کیمرہ (PTP) کے بطور ماؤنٹ کریں"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"اطلاعات"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"آپ کو یہ اطلاعات مزید دکھائی نہیں دیں گی"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"ان اطلاعات کو چھوٹا کر دیا جائے گا"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"آپ عام طور پر ان اطلاعات کو مسترد کرتے ہیں۔ \nان کو دکھاتے رہیں؟"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"یہ اطلاعات دکھانا جاری رکھیں؟"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"اطلاعات روک دیں"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"دکھانا جاری رکھیں"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"چھوٹا کریں"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"اس ایپ کی طرف سے اطلاعات دکھانا جاری رکھیں؟"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"ان اطلاعات کو آف نہیں کیا جا سکتا"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"یہ ایپ کیمرے کا استعمال کر رہی ہے۔"</string>
     <string name="appops_microphone" msgid="741508267659494555">"یہ ایپ مائیکروفون کا استعمال کر رہی ہے۔"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"یہ ایپ آپ کی اسکرین پر دیگر ایپس پر ڈسپلے کر رہی ہے۔"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"چارج ہوتے وقت فیصد دکھائیں (ڈیفالٹ)"</item>
     <item msgid="3327323682209964956">"یہ آئیکن نہ دکھائیں"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"کم ترجیحی اطلاع کے آئیکنز دکھائیں"</string>
     <string name="other" msgid="4060683095962566764">"دیگر"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"سپلٹ اسکرین تقسیم کار"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"بائیں فل اسکرین"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"انسٹال کیے بغیر کھلنے والی ایپ۔"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"انسٹال کیے بغیر کھلنے والی ایپ۔ مزید جاننے کے لیے تھپتھپائيں۔"</string>
     <string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"ویب پر جائیں"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"براؤزر پر جائیں"</string>
     <string name="mobile_data" msgid="7094582042819250762">"موبائل ڈیٹا"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"‏Wi-Fi آف ہے"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"ترتیبات"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"سمجھ آ گئی"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> آپ کی <xliff:g id="TYPES_LIST">%2$s</xliff:g> کا استعمال کر رہی ہے۔"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"ایپلیکیشنز آپ کی <xliff:g id="TYPES_LIST">%s</xliff:g> کا استعمال کر رہی ہیں۔"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"ایپ کھولیں"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"منسوخ کریں"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"ٹھیک ہے"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"ترتیبات"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> گزشتہ <xliff:g id="TIME">%3$d</xliff:g> منٹ سے آپ کی <xliff:g id="TYPE">%2$s</xliff:g> کا استعمال کر رہی ہے۔"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> آپ کی <xliff:g id="TYPE">%2$s</xliff:g> کا استعمال کر رہی ہیں"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> آپ کی <xliff:g id="TYPES_LIST">%2$s</xliff:g> کا استعمال کر رہی ہے"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"کیمرا"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"مقام"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"مائیکروفون"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index e7c3300..4c3909b 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Qayta skrinshot olib ko‘ring"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Xotirada joy kamligi uchun skrinshot saqlanmadi"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Ilova yoki tashkilotingiz skrinshot olishni taqiqlagan"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Ekrandan video yozib olish"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Ekrandan yozib olish seansi uchun joriy bildirishnoma"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Yozuvni boshlash"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Kadrorti nutqini yozib olish"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Bosishlarni ko‘rsatish"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"To‘xtatish"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Pauza"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Davom etish"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Bekor qilish"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Ulashish"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"O‘chirish"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Ekrandan yozib olish bekor qilindi"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Ekrandan yozib olingan video saqlandi. Uni ochish uchun bildirishnomani bosing."</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Ekrandan yozib olingan video o‘chirib tashlandi"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Ekrandan yozib olingan vi olib tashlanmadi"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Zarur ruxsatlar olinmadi"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fayl ko‘chirish moslamalari"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Media pleyer sifatida ulash (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Kamera sifatida ulash (PTP)"</string>
@@ -582,15 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Bildirishnomalar"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Bu bildirishnomalar endi chiqmaydi"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Bu bildirishnomalar kichraytiriladi"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"Bu bildirishnomalar ovozsiz chiqariladi"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Bu bildirishnomalar sizni ogohlantiradi"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Odatda bunday bildirishnomalarni yopasiz. \nUlar ochiq tursinmi?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Mazkur bildirishnomalar chiqaversinmi?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Chiqmasin"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Ha"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Kichraytirish"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Ovozsiz"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Chiqarish va ogohlantirish"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Bu ilovadan keladigan bildirishnomalar chiqaversinmi?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Bu bildirishnomalarni chiqmaydigan qilish imkonsiz"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Bu ilova kameradan foydalanmoqda."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Bu ilova mikrofondan foydalanmoqda."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Bu ilova ekranda boshqa ilovalar ustidan ochilgan."</string>
@@ -725,8 +743,7 @@
     <item msgid="2139628951880142927">"Quvvat olayotganda foizda ko‘rsatilsin (birlamchi)"</item>
     <item msgid="3327323682209964956">"Bu belgi boshqa ko‘rsatilmasin"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Muhim boʻlmagan bildirishnoma ikonkalarini koʻrsatish"</string>
     <string name="other" msgid="4060683095962566764">"Boshqa"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Ekranni ikkiga bo‘lish chizig‘i"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Chapda to‘liq ekran"</string>
@@ -806,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Ilova o‘rnatilmasdan ochildi."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Ilova o‘rnatilmasdan ochildi. Batafsil axborot uchun bu yerga bosing."</string>
     <string name="app_info" msgid="6856026610594615344">"Ilova haqida"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Brauzerga o‘tish"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Brauzerni ochish"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobil internet"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi o‘chiq"</string>
@@ -838,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Sozlamalar"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> ishlatmoqda: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Ilovalarda ishlatilmoqda: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Ilovani ochish"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Bekor qilish"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Sozlamalar"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> oxirgi <xliff:g id="TIME">%3$d</xliff:g> daqiqadan beri ishlatmoqda: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> ishlatmoqda: <xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> ishlatmoqda: <xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"kamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"joylashuv"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"mikrofon"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 4356ac5..5fbccf0 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Hãy thử chụp lại màn hình"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"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="173674476457581486">"Ứ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="screenrecord_name" msgid="4196719243134204796">"Đang ghi màn hình"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Thông báo đang diễn ra về phiên ghi màn hình"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Bắt đầu ghi"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Ghi phần thuyết minh"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Hiển thị số lần nhấn"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Dừng"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Tạm dừng"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Tiếp tục"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Hủy"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Chia sẻ"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Xóa"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Đã hủy bản ghi màn hình"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Đã lưu bản ghi màn hình, nhấn để xem"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Đã xóa bản ghi màn hình"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Lỗi khi xóa bản ghi màn hình"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Không được cấp đủ quyền"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Tùy chọn truyền tệp USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Gắn như một trình phát đa phương tiện (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Gắn như một máy ảnh (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Thông báo"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Bạn sẽ không thấy các thông báo này nữa"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Các thông báo này sẽ được thu nhỏ"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Bạn thường bỏ qua những thông báo này. \nTiếp tục hiển thị thông báo?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Tiếp tục hiển thị các thông báo này?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Dừng thông báo"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Tiếp tục hiển thị"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Thu nhỏ"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Tiếp tục hiển thị các thông báo từ ứng dụng này?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Không thể tắt các thông báo này"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Ứng dụng này đang sử dụng máy ảnh."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Ứng dụng này đang sử dụng micrô."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Ứng dụng này đang hiển thị chồng lên các ứng dụng khác trên màn hình."</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"Hiển thị phần trăm khi sạc (mặc định)"</item>
     <item msgid="3327323682209964956">"Không hiển thị biểu tượng này"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Hiển thị biểu tượng thông báo có mức ưu tiên thấp"</string>
     <string name="other" msgid="4060683095962566764">"Khác"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Bộ chia chia đôi màn hình"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Toàn màn hình bên trái"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Ứng dụng được mở mà không cần cài đặt."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Ứng dụng được mở mà không cần cài đặt. Nhấn để tìm hiểu thêm."</string>
     <string name="app_info" msgid="6856026610594615344">"Thông tin ứng dụng"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Truy cập web"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Đi tới trình duyệt"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Dữ liệu di động"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi tắt"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Cài đặt"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"Trích xuất bộ nhớ SysUI"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g> đang dùng <xliff:g id="TYPES_LIST">%2$s</xliff:g> của bạn."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Các ứng dụng đang dùng <xliff:g id="TYPES_LIST">%s</xliff:g> của bạn."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Mở ứng dụng"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Hủy"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"OK"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Cài đặt"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g> đang dùng <xliff:g id="TYPE">%2$s</xliff:g> của bạn trong <xliff:g id="TIME">%3$d</xliff:g> phút qua"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g> đang dùng <xliff:g id="TYPE">%2$s</xliff:g> của bạn"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g> đang dùng <xliff:g id="TYPES_LIST">%2$s</xliff:g> của bạn"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"máy ảnh"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"vị trí"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"micrô"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 5424266..8ab6905 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"请再次尝试截屏"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"由于存储空间有限,无法保存屏幕截图"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"此应用或您所在的单位不允许进行屏幕截图"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"屏幕录制"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"持续显示屏幕录制会话通知"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"开始录制"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"录制旁白"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"显示点按操作反馈"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"停止"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"暂停"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"继续"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"取消"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"分享"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"删除"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"已取消录制屏幕"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"屏幕录制内容已保存,点按即可查看"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"已删除屏幕录制内容"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"删除屏幕录制内容时出错"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"无法获取权限"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB文件传输选项"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"作为媒体播放器(MTP)装载"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"作为相机(PTP)装载"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"您将不会再看到这些通知"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"系统将会最小化这些通知"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"您通常会关闭这些通知。\n是否继续显示通知?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"要继续显示这些通知吗?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"停止通知"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"继续显示"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"最小化"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"要继续显示来自此应用的通知吗?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"无法关闭这些通知"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"此应用正在使用摄像头。"</string>
     <string name="appops_microphone" msgid="741508267659494555">"此应用正在使用麦克风。"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"此应用正显示在屏幕上其他应用的上层。"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"充电时显示百分比(默认)"</item>
     <item msgid="3327323682209964956">"不显示此图标"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"显示低优先级的通知图标"</string>
     <string name="other" msgid="4060683095962566764">"其他"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"分屏分隔线"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"左侧全屏"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"已打开免安装应用。"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"已打开免安装应用。点按即可了解详情。"</string>
     <string name="app_info" msgid="6856026610594615344">"应用信息"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"转到网页版"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"转到浏览器"</string>
     <string name="mobile_data" msgid="7094582042819250762">"移动数据"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"WLAN 已关闭"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"设置"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"知道了"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"转储 SysUI 堆"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"<xliff:g id="APP">%1$s</xliff:g>正在使用您的<xliff:g id="TYPES_LIST">%2$s</xliff:g>。"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"有多个应用正在使用您的<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"打开应用"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"取消"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"确定"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"设置"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"<xliff:g id="APP">%1$s</xliff:g>在过去 <xliff:g id="TIME">%3$d</xliff:g> 分钟内一直在使用您的<xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g>正在使用您的<xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"<xliff:g id="APP">%1$s</xliff:g>正在使用您的<xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"相机"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"位置信息"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"麦克风"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 38e8b3c..19450af 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"請再嘗試拍攝螢幕擷取畫面"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"由於儲存空間有限,因此無法儲存螢幕擷取畫面"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"應用程式或您的機構不允許擷取螢幕畫面"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"錄影畫面"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"持續顯示錄影畫面工作階段通知"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"開始錄影"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"錄製畫面外的音效"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"顯示輕按選項"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"停止"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"暫停"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"繼續"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"取消"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"分享"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"刪除"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"已取消錄影畫面"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"已儲存錄影畫面,輕按即可查看"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"已刪除錄影畫面"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"刪除錄影畫面時發生錯誤"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"無法獲得權限"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"掛接為媒體播放器 (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"掛接為相機 (PTP)"</string>
@@ -582,15 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"您不會再看到這些通知"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"這些通知將會縮到最小"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"系統會顯示這些通知,但不發出音效"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"這些通知會提醒您"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"您通常會關閉這些通知。\n要繼續顯示通知嗎?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"要繼續顯示這些通知嗎?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"停止通知"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"繼續顯示"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"最小化"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"顯示通知但不發出音效"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"顯示並提醒"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"要繼續顯示此應用程式的通知嗎?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"無法關閉這些通知"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"此應用程式目前使用相機。"</string>
     <string name="appops_microphone" msgid="741508267659494555">"此應用程式目前使用麥克風。"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"此應用程式目前透過其他應用程式在畫面上顯示內容。"</string>
@@ -725,8 +743,7 @@
     <item msgid="2139628951880142927">"充電時顯示百分比 (預設)"</item>
     <item msgid="3327323682209964956">"不顯示這個圖示"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"顯示低優先順序通知圖示"</string>
     <string name="other" msgid="4060683095962566764">"其他"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"分割畫面分隔線"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"左邊全螢幕"</string>
@@ -806,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"已開啟免安裝應用程式。"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"已開啟免安裝應用程式。輕按即可瞭解詳情。"</string>
     <string name="app_info" msgid="6856026610594615344">"應用程式資料"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"前往網頁版"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"前往瀏覽器"</string>
     <string name="mobile_data" msgid="7094582042819250762">"流動數據"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi 已關閉"</string>
@@ -838,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"設定"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"知道了"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"傾印 SysUI 記憶體快照"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"「<xliff:g id="APP">%1$s</xliff:g>」正在使用<xliff:g id="TYPES_LIST">%2$s</xliff:g>。"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"有多個應用程式正在使用<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"開啟應用程式"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"取消"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"確定"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"設定"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"「<xliff:g id="APP">%1$s</xliff:g>」在過去 <xliff:g id="TIME">%3$d</xliff:g> 分鐘內一直使用<xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"<xliff:g id="APPS">%1$s</xliff:g>正在使用<xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"「<xliff:g id="APP">%1$s</xliff:g>」正在使用<xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"相機"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"位置"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"麥克風"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index e399c44..6adc9d9 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"請再次嘗試拍攝螢幕擷取畫面"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"由於儲存空間有限,因此無法儲存螢幕擷取畫面"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"這個應用程式或貴機構不允許擷取螢幕畫面"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"錄製螢幕畫面"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"持續顯示螢幕畫面錄製工作階段通知"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"開始錄製"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"錄製畫面外的音效"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"顯示觸控回應"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"停止"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"暫停"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"繼續"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"取消"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"分享"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"刪除"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"已取消錄製螢幕畫面"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"已儲存螢幕畫面錄製內容,輕觸即可查看"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"已刪除螢幕畫面錄製內容"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"刪除螢幕畫面錄製內容時發生錯誤"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"無法取得權限"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"掛接為媒體播放器 (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"掛接為相機 (PTP)"</string>
@@ -582,15 +598,21 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"你不會再看到這些通知"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"系統將最小化這些通知"</string>
+    <!-- no translation found for notification_channel_silenced (2877199534497961942) -->
+    <skip />
+    <!-- no translation found for notification_channel_unsilenced (4790904571552394137) -->
+    <skip />
     <string name="inline_blocking_helper" msgid="3055064577771478591">"你通常會關閉這些通知。\n要繼續顯示通知嗎?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"要繼續顯示這些通知嗎?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"停止顯示通知"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"繼續顯示"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"最小化"</string>
+    <!-- no translation found for inline_silent_button_silent (4411510650503783646) -->
+    <skip />
+    <!-- no translation found for inline_silent_button_alert (2967599358027208807) -->
+    <skip />
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"要繼續顯示這個應用程式的通知嗎?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"無法關閉這些通知"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"這個應用程式正在使用相機。"</string>
     <string name="appops_microphone" msgid="741508267659494555">"這個應用程式正在使用麥克風。"</string>
     <string name="appops_overlay" msgid="6165912637560323464">"這個應用程式顯示在畫面上其他應用程式的上層。"</string>
@@ -725,8 +747,7 @@
     <item msgid="2139628951880142927">"充電時顯示百分比 (預設)"</item>
     <item msgid="3327323682209964956">"不顯示這個圖示"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"顯示低優先順序通知圖示"</string>
     <string name="other" msgid="4060683095962566764">"其他"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"分割畫面分隔線"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"以全螢幕顯示左側畫面"</string>
@@ -806,7 +827,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"已開啟免安裝應用程式。"</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"已開啟免安裝應用程式。輕觸即可瞭解詳情。"</string>
     <string name="app_info" msgid="6856026610594615344">"應用程式資訊"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"前往網頁版"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"前往瀏覽器"</string>
     <string name="mobile_data" msgid="7094582042819250762">"行動數據"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> - <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"Wi-Fi 已關閉"</string>
@@ -838,4 +859,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"設定"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"我知道了"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"傾印 SysUI 記憶體快照"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"「<xliff:g id="APP">%1$s</xliff:g>」正在使用<xliff:g id="TYPES_LIST">%2$s</xliff:g>。"</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"有多個應用程式正在使用<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"開啟應用程式"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"取消"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"確定"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"設定"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"「<xliff:g id="APP">%1$s</xliff:g>」過去 <xliff:g id="TIME">%3$d</xliff:g> 分鐘一直在使用<xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"「<xliff:g id="APPS">%1$s</xliff:g>」正在使用<xliff:g id="TYPE">%2$s</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"「<xliff:g id="APP">%1$s</xliff:g>」正在使用<xliff:g id="TYPES_LIST">%2$s</xliff:g>"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"相機"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"位置"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"麥克風"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 3887f14..b96b075 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -70,6 +70,22 @@
     <string name="screenshot_failed_to_save_unknown_text" msgid="3637758096565605541">"Zama ukuthatha isithombe-skrini futhi"</string>
     <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Ayikwazi ukulondoloza isithombe-skrini ngenxa yesikhala sesitoreji esikhawulelwe"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Ukuthatha izithombe-skrini akuvunyelwe uhlelo lokusebenza noma inhlangano yakho"</string>
+    <string name="screenrecord_name" msgid="4196719243134204796">"Ukurekhoda isikrini"</string>
+    <string name="screenrecord_channel_description" msgid="4630777331970993858">"Isaziso esiqhubekayo seseshini yokurekhoda isikrini"</string>
+    <string name="screenrecord_start_label" msgid="5177739269492196055">"Qala ukurekhoda"</string>
+    <string name="screenrecord_mic_label" msgid="4522870600914810019">"Rekhoda izwi elingaphezulu"</string>
+    <string name="screenrecord_taps_label" msgid="1776467076607964790">"Bonisa amathebhu"</string>
+    <string name="screenrecord_stop_label" msgid="2544887572381260038">"Misa"</string>
+    <string name="screenrecord_pause_label" msgid="7162476078856786227">"Phumula"</string>
+    <string name="screenrecord_resume_label" msgid="3605818317015993314">"Qalisa kabusha"</string>
+    <string name="screenrecord_cancel_label" msgid="3385204992871088609">"Khansela"</string>
+    <string name="screenrecord_share_label" msgid="4197867360204019389">"Yabelana"</string>
+    <string name="screenrecord_delete_label" msgid="7893716870917824013">"Susa"</string>
+    <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Ukurekhoda isikrini kukhanseliwe"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Ukurekhoda isikrini kulondoloziwe, thepha ukuze ubuke"</string>
+    <string name="screenrecord_delete_description" msgid="5743190456090354585">"Ukurekhoda isikrini kususiwe"</string>
+    <string name="screenrecord_delete_error" msgid="8154904464563560282">"Iphutha lokususa ukurekhoda isikrini"</string>
+    <string name="screenrecord_permission_error" msgid="1526755299469001000">"Yehlulekile ukuthola izimvume"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Okukhethwa kokudluliswa kwefayela ye-USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Lengisa njengesidlali semediya (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Lengisa ikhamera (PTP)"</string>
@@ -582,15 +598,17 @@
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Izaziso"</string>
     <string name="notification_channel_disabled" msgid="344536703863700565">"Ngeke usabona lezi zaziso"</string>
     <string name="notification_channel_minimized" msgid="1664411570378910931">"Lezi zaziso zizokwehlisa"</string>
+    <string name="notification_channel_silenced" msgid="2877199534497961942">"Lezi zaziso zizoboniswa ngokuthulile"</string>
+    <string name="notification_channel_unsilenced" msgid="4790904571552394137">"Lezi zaziso zizokuxwayisa"</string>
     <string name="inline_blocking_helper" msgid="3055064577771478591">"Uvamise ukucashisa lezi zaziso. \nQhubeka ulokhu uzibonisa?"</string>
     <string name="inline_keep_showing" msgid="8945102997083836858">"Qhubeka nokubonisa lezi zaziso?"</string>
     <string name="inline_stop_button" msgid="4172980096860941033">"Misa izaziso"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"Qhubeka nokubonisa"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"Nciphisa"</string>
+    <string name="inline_silent_button_silent" msgid="4411510650503783646">"Bonisa ngokuthulile"</string>
+    <string name="inline_silent_button_alert" msgid="2967599358027208807">"Bonisa futhi xwayisa"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Qhubeka nokubonisa izaziso kusuka kulolu hlelo lokusebenza?"</string>
     <string name="notification_unblockable_desc" msgid="1037434112919403708">"Lezi zaziso azikwazi ukuvalwa"</string>
-    <!-- no translation found for notification_delegate_header (9167022191405284627) -->
-    <skip />
     <string name="appops_camera" msgid="8100147441602585776">"Lolu hlelo lokusebenza lusebenzisa ikhamera."</string>
     <string name="appops_microphone" msgid="741508267659494555">"Lolu hlelo lokusebenza lusebenzisa imakrofoni."</string>
     <string name="appops_overlay" msgid="6165912637560323464">"Lolu hlelo lokusebenza luboniswa ngaphezulu kwezinye izinhlelo zokusebenza kusikrini sakho."</string>
@@ -725,8 +743,7 @@
     <item msgid="2139628951880142927">"Bonisa iphesentheji uma ishaja (okuzenzakalelayo)"</item>
     <item msgid="3327323682209964956">"Ungabonisi lesi sithonjana"</item>
   </string-array>
-    <!-- no translation found for tuner_low_priority (1325884786608312358) -->
-    <skip />
+    <string name="tuner_low_priority" msgid="1325884786608312358">"Bonisa izithonjana zesaziso zokubaluleka okuncane"</string>
     <string name="other" msgid="4060683095962566764">"Okunye"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"Isihlukanisi sokuhlukanisa isikrini"</string>
     <string name="accessibility_action_divider_left_full" msgid="2801570521881574972">"Isikrini esigcwele esingakwesokunxele"</string>
@@ -806,7 +823,7 @@
     <string name="instant_apps_message" msgid="1183313016396018086">"Uhlelo lokusebenza luvulwe ngaphndle kokufakwa."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Uhlelo lokusebenza luvulwe ngaphandle kokufakwa. Thepha ukuze ufunde kabanzi."</string>
     <string name="app_info" msgid="6856026610594615344">"Ulwazi lohlelo lokusebenza"</string>
-    <string name="go_to_web" msgid="1106022723459948514">"Iya kuwebhu"</string>
+    <string name="go_to_web" msgid="2650669128861626071">"Iya kusiphequluli"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Idatha yeselula"</string>
     <string name="mobile_data_text_format" msgid="3526214522670876454">"<xliff:g id="ID_1">%1$s</xliff:g> — <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"I-Wi-Fi ivaliwe"</string>
@@ -838,4 +855,16 @@
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Izilungiselelo"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"Ngiyezwa"</string>
     <string name="heap_dump_tile_name" msgid="9141031328971226374">"I-Dump SysUI Heap"</string>
+    <string name="ongoing_privacy_chip_content_single_app" msgid="4479560741898690064">"I-<xliff:g id="APP">%1$s</xliff:g> isebenzisa i-<xliff:g id="TYPES_LIST">%2$s</xliff:g> yakho."</string>
+    <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8640691753867990511">"Izinhlelo zokusebenza zisebenzisa i-<xliff:g id="TYPES_LIST">%s</xliff:g> yakho."</string>
+    <string name="ongoing_privacy_dialog_open_app" msgid="2483886665314567948">"Vula uhlelo lokusebenza"</string>
+    <string name="ongoing_privacy_dialog_cancel" msgid="5479124524931216790">"Khansela"</string>
+    <string name="ongoing_privacy_dialog_okay" msgid="5823914553907253532">"Kulungile"</string>
+    <string name="ongoing_privacy_dialog_open_settings" msgid="6382622467527049074">"Izilungiselelo"</string>
+    <string name="ongoing_privacy_dialog_app_item" msgid="486085465491760739">"I-<xliff:g id="APP">%1$s</xliff:g> isebenzisa i-<xliff:g id="TYPE">%2$s</xliff:g> yakho ngeminithi lokugcina elingu-<xliff:g id="TIME">%3$d</xliff:g>"</string>
+    <string name="ongoing_privacy_dialog_apps_item" msgid="9207187236823950491">"Ama-<xliff:g id="APPS">%1$s</xliff:g> asebenzisa i-<xliff:g id="TYPE">%2$s</xliff:g> yakho"</string>
+    <string name="ongoing_privacy_dialog_single_app" msgid="3884812469179810924">"I-<xliff:g id="APP">%1$s</xliff:g> isebenzisa i-<xliff:g id="TYPES_LIST">%2$s</xliff:g> yakho"</string>
+    <string name="privacy_type_camera" msgid="1676604631892420333">"ikhamera"</string>
+    <string name="privacy_type_location" msgid="6435497989657286700">"indawo"</string>
+    <string name="privacy_type_microphone" msgid="4153045784928554506">"imakrofoni"</string>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index c61b1d2..d8648fa 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -147,7 +147,7 @@
 
     <!-- The number of milliseconds before the ambient notification auto-dismisses. This will
          override the default pulse length. -->
-    <integer name="ambient_notification_decay">6000</integer>
+    <integer name="ambient_notification_decay">10000</integer>
 
     <!-- Minimum display time for a heads up notification, in milliseconds. -->
     <integer name="ambient_notification_minimum_time">2000</integer>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 525421a..97f5f86 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -215,6 +215,9 @@
     <!-- The width of the view containing navigation buttons -->
     <dimen name="navigation_key_width">70dp</dimen>
 
+    <!-- The width/height of the icon of a navigation button -->
+    <dimen name="navigation_icon_size">32dp</dimen>
+
     <dimen name="navigation_key_padding">0dp</dimen>
 
     <!-- The width of the view containing the menu/ime navigation bar icons -->
@@ -366,6 +369,7 @@
     <dimen name="qs_page_indicator_height">8dp</dimen>
     <dimen name="qs_tile_icon_size">24dp</dimen>
     <dimen name="qs_tile_text_size">12sp</dimen>
+    <dimen name="qs_carrier_info_text_size">14sp</dimen>
     <dimen name="qs_tile_divider_height">1dp</dimen>
     <dimen name="qs_panel_padding">16dp</dimen>
     <dimen name="qs_dual_tile_height">112dp</dimen>
@@ -478,6 +482,9 @@
     <!-- The height of the divider between the individual notifications when the notification wants it to be increased. This is currently the case for notification groups -->
     <dimen name="notification_divider_height_increased">6dp</dimen>
 
+    <!-- The height of the gap between adjacent notification sections. -->
+    <dimen name="notification_section_divider_height">@dimen/notification_side_paddings</dimen>
+
     <!-- The minimum amount of top overscroll to go to the quick settings. -->
     <dimen name="min_top_overscroll_to_qs">36dp</dimen>
 
@@ -858,7 +865,6 @@
     <dimen name="nav_content_padding">0dp</dimen>
     <dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen>
     <dimen name="nav_quick_scrub_track_thickness">10dp</dimen>
-    <dimen name="nav_home_back_gesture_drag_limit">40dp</dimen>
 
     <!-- Navigation bar shadow params. -->
     <dimen name="nav_key_button_shadow_offset_x">0dp</dimen>
@@ -889,6 +895,7 @@
     <dimen name="biometric_dialog_biometric_icon_size">64dp</dimen>
     <dimen name="biometric_dialog_corner_size">4dp</dimen>
     <dimen name="biometric_dialog_animation_translation_offset">350dp</dimen>
+    <dimen name="biometric_dialog_border_padding">4dp</dimen>
 
     <!-- Wireless Charging Animation values -->
     <dimen name="wireless_charging_dots_radius_start">0dp</dimen>
@@ -933,18 +940,34 @@
          that just start below the notch. -->
     <dimen name="display_cutout_touchable_region_size">12dp</dimen>
 
+    <!-- Padding below Ongoing App Ops dialog title -->
+    <dimen name="ongoing_appops_dialog_sep">16dp</dimen>
+    <!--Padding around text items in Ongoing App Ops dialog -->
+    <dimen name="ongoing_appops_dialog_text_padding">16dp</dimen>
     <!-- Height of icons in Ongoing App Ops dialog. Both App Op icon and application icon -->
-    <dimen name="ongoing_appops_dialog_icon_height">48dp</dimen>
+    <dimen name="ongoing_appops_dialog_icon_height">28dp</dimen>
     <!-- Margin between text lines in Ongoing App Ops dialog -->
     <dimen name="ongoing_appops_dialog_text_margin">15dp</dimen>
+    <!-- Side padding of title in Ongoing App Ops dialog -->
+    <dimen name="ongoing_appops_dialog_title_padding">10dp</dimen>
     <!-- Padding around Ongoing App Ops dialog content -->
     <dimen name="ongoing_appops_dialog_content_padding">24dp</dimen>
-    <!-- Margins around the Ongoing App Ops chip. In landscape, the side margins are 0 -->
+    <!-- Side margins around the Ongoing App Ops chip-->
     <dimen name="ongoing_appops_chip_margin">12dp</dimen>
+    <!-- Top and bottom margins around the Ongoing App Ops chip -->
+    <dimen name="ongoing_appops_top_chip_margin">12dp</dimen>
     <!-- Start and End padding for Ongoing App Ops chip -->
     <dimen name="ongoing_appops_chip_side_padding">6dp</dimen>
     <!-- Padding between background of Ongoing App Ops chip and content -->
-    <dimen name="ongoing_appops_chip_bg_padding">4dp</dimen>
+    <dimen name="ongoing_appops_chip_bg_padding">0dp</dimen>
+    <!-- Margin between icons of Ongoing App Ops chip -->
+    <dimen name="ongoing_appops_chip_icon_margin">4dp</dimen>
+    <!-- Icon size of Ongoing App Ops chip -->
+    <dimen name="ongoing_appops_chip_icon_size">18dp</dimen>
     <!-- Radius of Ongoing App Ops chip corners -->
     <dimen name="ongoing_appops_chip_bg_corner_radius">12dp</dimen>
+    <!-- Text size for Ongoing App Ops dialog title -->
+    <dimen name="ongoing_appops_dialog_title_size">24sp</dimen>
+    <!-- Text size for Ongoing App Ops dialog items -->
+    <dimen name="ongoing_appops_dialog_item_size">20sp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7d09c00..4a0bc9b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1540,6 +1540,12 @@
     <!-- Notification inline controls: Shown when a channel's notifications are minimized -->
     <string name="notification_channel_minimized">These notifications will be minimized</string>
 
+    <!-- Notification inline controls: Shown when a channel's notifications are silenced [CHAR_LIMIT=100] -->
+    <string name="notification_channel_silenced">These notifications will be shown silently</string>
+
+    <!-- Notification inline controls: Shown when a channel's notifications are set to alert [CHAR_LIMIT=100] -->
+    <string name="notification_channel_unsilenced">These notifications will alert you</string>
+
     <!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
     <string name="inline_blocking_helper">You usually dismiss these notifications.
     \nKeep showing them?</string>
@@ -1556,6 +1562,12 @@
     <!-- Notification inline controls: minimize notifications button -->
     <string name="inline_minimize_button">Minimize</string>
 
+    <!-- Notification inline controls: show notifications silently button [CHAR_LIMIT=25] -->
+    <string name="inline_silent_button_silent">Show silently</string>
+
+    <!-- Notification inline controls: show and alert button [CHAR_LIMIT=25] -->
+    <string name="inline_silent_button_alert">Show and alert</string>
+
     <!-- Notification Inline controls: continue receiving notifications prompt, app level -->
     <string name="inline_keep_showing_app">Keep showing notifications from this app?</string>
 
@@ -2131,7 +2143,7 @@
     <string name="app_info">App info</string>
 
     <!-- Action label for switching to a browser for an instant app [CHAR LIMIT=20] -->
-    <string name="go_to_web">Go to web</string>
+    <string name="go_to_web">Go to browser</string>
 
     <!-- Quick settings tile for toggling mobile data [CHAR LIMIT=20] -->
     <string name="mobile_data">Mobile data</string>
@@ -2238,39 +2250,48 @@
          app for debugging. Will not be seen by users. [CHAR LIMIT=20] -->
     <string name="heap_dump_tile_name">Dump SysUI Heap</string>
 
+    <!-- Text on chip for multiple apps using a single app op [CHAR LIMIT=10] -->
+    <string name="ongoing_privacy_chip_multiple_apps"><xliff:g id="num_apps" example="3">%d</xliff:g> apps</string>
+
     <!-- Content description for ongoing privacy chip. Use with a single app [CHAR LIMIT=NONE]-->
     <string name="ongoing_privacy_chip_content_single_app"><xliff:g id="app" example="Example App">%1$s</xliff:g> is using your <xliff:g id="types_list" example="camera, location">%2$s</xliff:g>.</string>
 
     <!-- Content description for ongoing privacy chip. Use with multiple apps [CHAR LIMIT=NONE]-->
     <string name="ongoing_privacy_chip_content_multiple_apps">Applications are using your <xliff:g id="types_list" example="camera, location">%s</xliff:g>.</string>
 
-    <!-- Action on Ongoing Privacy Dialog to open application [CHAR LIMIT=10]-->
-    <string name="ongoing_privacy_dialog_open_app">Open app</string>
+    <!-- Content description for ongoing privacy chip. Use with multiple apps using same app op[CHAR LIMIT=NONE]-->
+    <string name="ongoing_privacy_chip_content_multiple_apps_single_op"><xliff:g id="num_apps" example="3">%1$d</xliff:g> applications are using your <xliff:g id="type" example="camera">%2$s</xliff:g>.</string>
 
     <!-- Action on Ongoing Privacy Dialog to dismiss [CHAR LIMIT=10]-->
     <string name="ongoing_privacy_dialog_cancel">Cancel</string>
 
-    <!-- Action on Ongoing Privacy Dialog to dismiss [CHAR LIMIT=10]-->
-    <string name="ongoing_privacy_dialog_okay">Okay</string>
+    <!-- Action on Ongoing Privacy Dialog to open privacy hub [CHAR LIMIT=15]-->
+    <string name="ongoing_privacy_dialog_open_settings">View details</string>
 
-    <!-- Action on Ongoing Privacy Dialog to open privacy hub [CHAR LIMIT=10]-->
-    <string name="ongoing_privacy_dialog_open_settings">Settings</string>
+    <!-- Text for item in Ongoing Privacy Dialog title when only one app is using app ops [CHAR LIMIT=NONE] -->
+    <string name="ongoing_privacy_dialog_single_app_title">App using your <xliff:g id="types_list" example="camera( and location)">%s</xliff:g></string>
 
-    <!-- Text for item in Ongoing Privacy Dialog when only one app is using a particular type of app op [CHAR LIMIT=NONE] -->
-    <string name="ongoing_privacy_dialog_app_item"><xliff:g id="app" example="Example App">%1$s</xliff:g> is using your <xliff:g id="type" example="camera">%2$s</xliff:g> for the last <xliff:g id="time" example="3">%3$d</xliff:g> min</string>
+    <!-- Text for item in Ongoing Privacy Dialog title when multiple apps is using app ops [CHAR LIMIT=NONE] -->
+    <string name="ongoing_privacy_dialog_multiple_apps_title">Apps using your <xliff:g id="types_list" example="camera( and location)">%s</xliff:g></string>
 
-    <!-- Text for item in Ongoing Privacy Dialog when only multiple apps are using a particular type of app op [CHAR LIMIT=NONE] -->
-    <string name="ongoing_privacy_dialog_apps_item"><xliff:g id="apps" example="Camera, Phone">%1$s</xliff:g> are using your <xliff:g id="type" example="camera">%2$s</xliff:g></string>
+    <!-- Separator for types. Include spaces before and after if needed [CHAR LIMIT=10] -->
+    <string name="ongoing_privacy_dialog_separator">,\u0020</string>
 
-    <!-- Text for Ongoing Privacy Dialog when a single app is using app ops [CHAR LIMIT=NONE] -->
-    <string name="ongoing_privacy_dialog_single_app"><xliff:g id="app" example="Example App">%1$s</xliff:g> is using your <xliff:g id="types_list" example="camera, location">%2$s</xliff:g></string>
+    <!-- Separator for types, before last type. Include spaces before and after if needed [CHAR LIMIT=10] -->
+    <string name="ongoing_privacy_dialog_last_separator">\u0020and\u0020</string>
 
-    <!-- Text for camera app op [CHAR LIMIT=12]-->
+    <!-- Text for camera app op [CHAR LIMIT=20]-->
     <string name="privacy_type_camera">camera</string>
 
-    <!-- Text for location app op [CHAR LIMIT=12]-->
+    <!-- Text for location app op [CHAR LIMIT=20]-->
     <string name="privacy_type_location">location</string>
 
-    <!-- Text for microphone app op [CHAR LIMIT=12]-->
+    <!-- Text for microphone app op [CHAR LIMIT=20]-->
     <string name="privacy_type_microphone">microphone</string>
+
+    <!-- Text for indicating extra apps using app ops [CHAR LIMIT=NONE] -->
+    <plurals name="ongoing_privacy_dialog_overflow_text">
+        <item quantity="one"><xliff:g id="num_apps" example="1">%d</xliff:g> other app</item>
+        <item quantity="other"><xliff:g id="num_apps" example="3">%d</xliff:g> other app</item>
+    </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 6244e1c..e9aa1b6 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -125,7 +125,7 @@
 
     <style name="TextAppearance.StatusBar.Clock" parent="@*android:style/TextAppearance.StatusBar.Icon">
         <item name="android:textSize">@dimen/status_bar_clock_size</item>
-        <item name="android:fontFamily">sans-serif-medium</item>
+        <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
         <item name="android:textColor">@color/status_bar_clock_color</item>
     </style>
 
@@ -135,7 +135,7 @@
 
     <style name="TextAppearance.StatusBar.Expanded.Clock">
         <item name="android:textSize">@dimen/qs_time_expanded_size</item>
-        <item name="android:fontFamily">sans-serif-medium</item>
+        <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:textStyle">normal</item>
     </style>
@@ -240,9 +240,31 @@
 
     <style name="TextAppearance.QS.TileLabel">
         <item name="android:textSize">@dimen/qs_tile_text_size</item>
+        <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+    </style>
+
+    <style name="TextAppearance.QS.TileLabel.Secondary">
+        <item name="android:textSize">@dimen/qs_tile_text_size</item>
         <item name="android:fontFamily">sans-serif</item>
     </style>
 
+    <style name="TextAppearance.QS.CarrierInfo">
+        <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+        <item name="android:textSize">@dimen/qs_carrier_info_text_size</item>
+    </style>
+
+    <style name="TextAppearance.AppOpsDialog" />
+
+    <style name="TextAppearance.AppOpsDialog.Title">
+        <item name="android:textSize">@dimen/ongoing_appops_dialog_title_size</item>
+        <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
+    </style>
+
+    <style name="TextAppearance.AppOpsDialog.Item">
+        <item name="android:textSize">@dimen/ongoing_appops_dialog_item_size</item>
+        <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+    </style>
+
     <style name="BaseBrightnessDialogContainer" parent="@style/Theme.SystemUI">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
index a0a3687..b7d5197 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
@@ -16,10 +16,6 @@
 
 package com.android.keyguard;
 
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -28,6 +24,7 @@
 import android.net.wifi.WifiManager;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.text.method.SingleLineTransformationMethod;
 import android.util.AttributeSet;
@@ -40,7 +37,9 @@
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.settingslib.WirelessUtils;
 
-import android.telephony.TelephonyManager;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
 
 public class CarrierText extends TextView {
     private static final boolean DEBUG = KeyguardConstants.DEBUG;
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
index ac8f024..210b82d 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
@@ -16,7 +16,6 @@
 
 package com.android.keyguard;
 
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.content.Context;
@@ -37,8 +36,8 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.util.EmergencyAffordanceManager;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.util.EmergencyDialerConstants;
 
 /**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 013745a..b439c6c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -126,6 +126,16 @@
         mClockView.setFormat24Hour(format);
     }
 
+    /**
+     * Set the amount (ratio) that the device has transitioned to doze.
+     * @param darkAmount Amount of transition to doze: 1f for doze and 0f for awake.
+     */
+    public void setDarkAmount(float darkAmount) {
+        if (mClockPlugin != null) {
+            mClockPlugin.setDarkAmount(darkAmount);
+        }
+    }
+
     public Paint getPaint() {
         return mClockView.getPaint();
     }
@@ -143,6 +153,15 @@
     }
 
     /**
+     * Notifies that time tick alarm from doze service fired.
+     */
+    public void dozeTimeTick() {
+        if (mClockPlugin != null) {
+            mClockPlugin.dozeTimeTick();
+        }
+    }
+
+    /**
      * When plugin changes, set all kept parameters into newer plugin.
      */
     private void initPluginParams() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 2bc0e45c..e051317 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -15,54 +15,164 @@
  */
 package com.android.keyguard;
 
-import static android.view.Display.INVALID_DISPLAY;
+import static android.view.Display.DEFAULT_DISPLAY;
 
+import android.annotation.Nullable;
 import android.app.Presentation;
 import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnDismissListener;
 import android.graphics.Point;
+import android.hardware.display.DisplayManager;
 import android.media.MediaRouter;
 import android.media.MediaRouter.RouteInfo;
 import android.os.Bundle;
-import android.util.Slog;
+import android.util.Log;
+import android.util.SparseArray;
 import android.view.Display;
 import android.view.View;
 import android.view.WindowManager;
 
+import java.util.function.BooleanSupplier;
+
 // TODO(multi-display): Support multiple external displays
 public class KeyguardDisplayManager {
     protected static final String TAG = "KeyguardDisplayManager";
     private static boolean DEBUG = KeyguardConstants.DEBUG;
 
     private final ViewMediatorCallback mCallback;
+
     private final MediaRouter mMediaRouter;
+    private final DisplayManager mDisplayService;
     private final Context mContext;
 
-    Presentation mPresentation;
     private boolean mShowing;
 
+    private final SparseArray<Presentation> mPresentations = new SparseArray<>();
+
+    private final DisplayManager.DisplayListener mDisplayListener =
+            new DisplayManager.DisplayListener() {
+
+        @Override
+        public void onDisplayAdded(int displayId) {
+            final Display display = mDisplayService.getDisplay(displayId);
+            if (mShowing) {
+                notifyIfChanged(() -> showPresentation(display));
+            }
+        }
+
+        @Override
+        public void onDisplayChanged(int displayId) {
+            if (displayId == DEFAULT_DISPLAY) return;
+            final Display display = mDisplayService.getDisplay(displayId);
+            if (display != null && mShowing) {
+                final Presentation presentation = mPresentations.get(displayId);
+                if (presentation != null && !presentation.getDisplay().equals(display)) {
+                    hidePresentation(displayId);
+                    showPresentation(display);
+                }
+            }
+        }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+            notifyIfChanged(() -> hidePresentation(displayId));
+        }
+    };
+
     public KeyguardDisplayManager(Context context, ViewMediatorCallback callback) {
         mContext = context;
         mCallback = callback;
-        mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+        mMediaRouter = mContext.getSystemService(MediaRouter.class);
+        mDisplayService = mContext.getSystemService(DisplayManager.class);
+        mDisplayService.registerDisplayListener(mDisplayListener, null /* handler */);
+    }
+
+    /**
+     * @param display The display to show the presentation on.
+     * @return {@code true} if a presentation was added.
+     *         {@code false} if the presentation cannot be added on that display or the presentation
+     *         was already there.
+     */
+    private boolean showPresentation(Display display) {
+        if (display == null || display.getDisplayId() == DEFAULT_DISPLAY) return false;
+        if (DEBUG) Log.i(TAG, "Keyguard enabled on display: " + display);
+        final int displayId = display.getDisplayId();
+        Presentation presentation = mPresentations.get(displayId);
+        if (presentation == null) {
+            presentation = new KeyguardPresentation(mContext, display);
+            presentation.setOnDismissListener(dialog -> {
+                if (null != mPresentations.get(displayId)) {
+                    mPresentations.remove(displayId);
+                }
+            });
+            try {
+                presentation.show();
+            } catch (WindowManager.InvalidDisplayException ex) {
+                Log.w(TAG, "Invalid display:", ex);
+                presentation = null;
+            }
+            if (presentation != null) {
+                mPresentations.append(displayId, presentation);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @param displayId The id of the display to hide the presentation off.
+     * @return {@code true} if the a presentation was removed.
+     *         {@code false} if the presentation was not added before.
+     */
+    private boolean hidePresentation(int displayId) {
+        final Presentation presentation = mPresentations.get(displayId);
+        if (presentation != null) {
+            presentation.dismiss();
+            mPresentations.remove(displayId);
+            return true;
+        }
+        return false;
+    }
+
+    private void notifyIfChanged(BooleanSupplier updateMethod) {
+        if (updateMethod.getAsBoolean()) {
+            final int[] displayList = getPresentationDisplayIds();
+            mCallback.onSecondaryDisplayShowingChanged(displayList);
+        }
+    }
+
+    /**
+     * @return An array of displayId's on which a {@link KeyguardPresentation} is showing on.
+     */
+    @Nullable
+    private int[] getPresentationDisplayIds() {
+        final int size = mPresentations.size();
+        if (size == 0) return null;
+
+        final int[] displayIds = new int[size];
+        for (int i = mPresentations.size() - 1; i >= 0; i--) {
+            final Presentation presentation = mPresentations.valueAt(i);
+            if (presentation != null) {
+                displayIds[i] = presentation.getDisplay().getDisplayId();
+            }
+        }
+        return displayIds;
     }
 
     public void show() {
         if (!mShowing) {
-            if (DEBUG) Slog.v(TAG, "show");
+            if (DEBUG) Log.v(TAG, "show");
             mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
                     mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
-            updateDisplays(true);
+            notifyIfChanged(() -> updateDisplays(true /* showing */));
         }
         mShowing = true;
     }
 
     public void hide() {
         if (mShowing) {
-            if (DEBUG) Slog.v(TAG, "hide");
+            if (DEBUG) Log.v(TAG, "hide");
             mMediaRouter.removeCallback(mMediaRouterCallback);
-            updateDisplays(false);
+            notifyIfChanged(() -> updateDisplays(false /* showing */));
         }
         mShowing = false;
     }
@@ -71,71 +181,38 @@
             new MediaRouter.SimpleCallback() {
         @Override
         public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
-            if (DEBUG) Slog.d(TAG, "onRouteSelected: type=" + type + ", info=" + info);
-            updateDisplays(mShowing);
+            if (DEBUG) Log.d(TAG, "onRouteSelected: type=" + type + ", info=" + info);
+            notifyIfChanged(() -> updateDisplays(mShowing));
         }
 
         @Override
         public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
-            if (DEBUG) Slog.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info);
-            updateDisplays(mShowing);
+            if (DEBUG) Log.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info);
+            notifyIfChanged(() -> updateDisplays(mShowing));
         }
 
         @Override
         public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) {
-            if (DEBUG) Slog.d(TAG, "onRoutePresentationDisplayChanged: info=" + info);
-            updateDisplays(mShowing);
+            if (DEBUG) Log.d(TAG, "onRoutePresentationDisplayChanged: info=" + info);
+            notifyIfChanged(() -> updateDisplays(mShowing));
         }
     };
 
-    private OnDismissListener mOnDismissListener = new OnDismissListener() {
-
-        @Override
-        public void onDismiss(DialogInterface dialog) {
-            mPresentation = null;
-        }
-    };
-
-    protected void updateDisplays(boolean showing) {
-        Presentation originalPresentation = mPresentation;
+    protected boolean updateDisplays(boolean showing) {
+        boolean changed = false;
         if (showing) {
-            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(
-                    MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
-            boolean useDisplay = route != null
-                    && route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE;
-            Display presentationDisplay = useDisplay ? route.getPresentationDisplay() : null;
-
-            if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) {
-                if (DEBUG) Slog.v(TAG, "Display gone: " + mPresentation.getDisplay());
-                mPresentation.dismiss();
-                mPresentation = null;
-            }
-
-            if (mPresentation == null && presentationDisplay != null) {
-                if (DEBUG) Slog.i(TAG, "Keyguard enabled on display: " + presentationDisplay);
-                mPresentation = new KeyguardPresentation(mContext, presentationDisplay,
-                        R.style.keyguard_presentation_theme);
-                mPresentation.setOnDismissListener(mOnDismissListener);
-                try {
-                    mPresentation.show();
-                } catch (WindowManager.InvalidDisplayException ex) {
-                    Slog.w(TAG, "Invalid display:", ex);
-                    mPresentation = null;
-                }
+            final Display[] displays = mDisplayService.getDisplays();
+            for (Display display : displays) {
+                changed |= showPresentation(display);
             }
         } else {
-            if (mPresentation != null) {
-                mPresentation.dismiss();
-                mPresentation = null;
+            changed = mPresentations.size() > 0;
+            for (int i = mPresentations.size() - 1; i >= 0; i--) {
+                mPresentations.valueAt(i).dismiss();
             }
+            mPresentations.clear();
         }
-
-        // mPresentation is only updated when the display changes
-        if (mPresentation != originalPresentation) {
-            final int displayId = mPresentation != null
-                    ? mPresentation.getDisplay().getDisplayId() : INVALID_DISPLAY;
-            mCallback.onSecondaryDisplayShowingChanged(displayId);
-        }
+        return changed;
     }
 
     private final static class KeyguardPresentation extends Presentation {
@@ -157,9 +234,10 @@
             }
         };
 
-        public KeyguardPresentation(Context context, Display display, int theme) {
-            super(context, display, theme);
+        KeyguardPresentation(Context context, Display display) {
+            super(context, display, R.style.keyguard_presentation_theme);
             getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+            setCancelable(false);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
index 63b7ae2..c2bbfbf 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
@@ -22,19 +22,15 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.UserHandle;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.euicc.EuiccManager;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.Button;
-import android.telephony.SubscriptionManager;
-import android.telephony.SubscriptionInfo;
-import android.telephony.euicc.EuiccManager;
-import android.util.Log;
-
-import java.lang.ref.WeakReference;
 
 /***
  * This button is used by the device with embedded SIM card to disable current carrier to unlock
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index 34df15f..cf22286 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -19,8 +19,8 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.content.Context;
-import android.content.res.Resources;
 import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.media.AudioManager;
 import android.os.SystemClock;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index cb8c119..3cc18dd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -23,8 +23,6 @@
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.internal.annotations.VisibleForTesting;
-
 /**
  * A Pin based Keyguard input view
  */
@@ -68,12 +66,18 @@
     protected void setPasswordEntryEnabled(boolean enabled) {
         mPasswordEntry.setEnabled(enabled);
         mOkButton.setEnabled(enabled);
+        if (enabled && !mPasswordEntry.hasFocus()) {
+            mPasswordEntry.requestFocus();
+        }
     }
 
     @Override
     protected void setPasswordEntryInputEnabled(boolean enabled) {
         mPasswordEntry.setEnabled(enabled);
         mOkButton.setEnabled(enabled);
+        if (enabled && !mPasswordEntry.hasFocus()) {
+            mPasswordEntry.requestFocus();
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index b8df3c06..7af27f2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.os.UserHandle;
-import androidx.annotation.VisibleForTesting;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Slog;
@@ -31,6 +30,8 @@
 import android.view.WindowManager;
 import android.widget.FrameLayout;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
index 1a09364..272b3bd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
@@ -15,9 +15,10 @@
  */
 package com.android.keyguard;
 
-import com.android.internal.widget.LockPatternUtils;
 import android.content.res.ColorStateList;
 
+import com.android.internal.widget.LockPatternUtils;
+
 public interface KeyguardSecurityView {
     static public final int SCREEN_ON = 1;
     static public final int VIEW_REVEALED = 2;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index 74e2a68..e6a0250 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -18,8 +18,8 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
-import android.content.res.TypedArray;
 import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -28,18 +28,15 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewHierarchyEncoder;
-import android.view.WindowManager;
 import android.widget.FrameLayout;
 import android.widget.ViewFlipper;
 
 import com.android.internal.widget.LockPatternUtils;
 
-import java.lang.Override;
-
 /**
  * Subclass of the current view flipper that allows us to overload dispatchTouchEvent() so
- * we can emulate {@link WindowManager.LayoutParams#FLAG_SLIPPERY} within a view hierarchy.
- *
+ * we can emulate {@link android.view.WindowManager.LayoutParams#FLAG_SLIPPERY} within a view
+ * hierarchy.
  */
 public class KeyguardSecurityViewFlipper extends ViewFlipper implements KeyguardSecurityView {
     private static final String TAG = "KeyguardSecurityViewFlipper";
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 42c7a56..6528d8c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -16,32 +16,31 @@
 
 package com.android.keyguard;
 
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.telephony.PhoneConstants;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.app.AlertDialog;
 import android.app.AlertDialog.Builder;
 import android.app.Dialog;
 import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.euicc.EuiccManager;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.ImageView;
 
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.telephony.PhoneConstants;
+
 /**
  * Displays a PIN pad for unlocking.
  */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 1b61568..1157f86 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -16,20 +16,19 @@
 
 package com.android.keyguard;
 
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.euicc.EuiccManager;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
@@ -38,8 +37,8 @@
 
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.telephony.PhoneConstants;
 
 
 /**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 50b98a1..c41ef0e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -17,6 +17,8 @@
 package com.android.keyguard;
 
 import static android.app.slice.Slice.HINT_LIST_ITEM;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
 
 import android.animation.LayoutTransition;
 import android.animation.ObjectAnimator;
@@ -80,6 +82,7 @@
     private float mDarkAmount = 0;
 
     private LiveData<Slice> mLiveData;
+    private int mDisplayId = INVALID_DISPLAY;
     private int mIconSize;
     /**
      * Runnable called whenever the view contents change.
@@ -129,6 +132,7 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
 
+        mDisplayId = getDisplay().getDisplayId();
         // Make sure we always have the most current slice
         mLiveData.observeForever(this);
         Dependency.get(ConfigurationController.class).addCallback(this);
@@ -138,7 +142,10 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
 
-        mLiveData.removeObserver(this);
+        // TODO(b/117344873) Remove below work around after this issue be fixed.
+        if (mDisplayId == DEFAULT_DISPLAY) {
+            mLiveData.removeObserver(this);
+        }
         Dependency.get(ConfigurationController.class).removeCallback(this);
     }
 
@@ -236,46 +243,6 @@
         }
     }
 
-    /**
-     * Breaks a string in 2 lines where both have similar character count
-     * but first line is always longer.
-     *
-     * @param charSequence Original text.
-     * @return Optimal string.
-     */
-    private static CharSequence findBestLineBreak(CharSequence charSequence) {
-        if (TextUtils.isEmpty(charSequence)) {
-            return charSequence;
-        }
-
-        String source = charSequence.toString();
-        // Ignore if there is only 1 word,
-        // or if line breaks were manually set.
-        if (source.contains("\n") || !source.contains(" ")) {
-            return source;
-        }
-
-        final String[] words = source.split(" ");
-        final StringBuilder optimalString = new StringBuilder(source.length());
-        int current = 0;
-        while (optimalString.length() < source.length() - optimalString.length()) {
-            optimalString.append(words[current]);
-            if (current < words.length - 1) {
-                optimalString.append(" ");
-            }
-            current++;
-        }
-        optimalString.append("\n");
-        for (int i = current; i < words.length; i++) {
-            optimalString.append(words[i]);
-            if (current < words.length - 1) {
-                optimalString.append(" ");
-            }
-        }
-
-        return optimalString.toString();
-    }
-
     public void setDarkAmount(float darkAmount) {
         mDarkAmount = darkAmount;
         mRow.setDarkAmount(darkAmount);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index a403b75..be795d2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -47,7 +47,6 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
 
 import com.google.android.collect.Sets;
 
@@ -276,6 +275,7 @@
     public void dozeTimeTick() {
         refreshTime();
         mKeyguardSlice.refresh();
+        mClockView.dozeTimeTick();
     }
 
     private void refreshTime() {
@@ -385,6 +385,7 @@
             return;
         }
         mDarkAmount = darkAmount;
+        mClockView.setDarkAmount(darkAmount);
         updateDark();
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
index 41b86a7..a07c5cb 100644
--- a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
@@ -96,9 +96,9 @@
     int getBouncerPromptReason();
 
     /**
-     * Invoked when the secondary display showing a keyguard window changes.
+     * Invoked when the secondary displays showing a keyguard window changes.
      */
-    void onSecondaryDisplayShowingChanged(int displayId);
+    void onSecondaryDisplayShowingChanged(int[] displayId);
 
     /**
      * Consumes a message that was enqueued to be displayed on the next time the bouncer shows up.
diff --git a/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java b/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
index bbc8ecd..5ed9eaa 100644
--- a/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
@@ -18,7 +18,6 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
-import android.os.LocaleList;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index f6fec54..053ea67 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -19,7 +19,10 @@
 import static android.app.StatusBarManager.DISABLE_NONE;
 import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
 
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
 import android.animation.ArgbEvaluator;
+import android.annotation.IntDef;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.Resources;
@@ -55,15 +58,23 @@
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 import com.android.systemui.util.Utils.DisableStateTracker;
-import com.android.systemui.R;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
 import java.text.NumberFormat;
 
 public class BatteryMeterView extends LinearLayout implements
         BatteryStateChangeCallback, Tunable, DarkReceiver, ConfigurationListener {
 
+
+    @Retention(SOURCE)
+    @IntDef({MODE_DEFAULT, MODE_ON, MODE_OFF})
+    public @interface BatteryPercentMode {}
+    public static final int MODE_DEFAULT = 0;
+    public static final int MODE_ON = 1;
+    public static final int MODE_OFF = 2;
+
     private final BatteryMeterDrawableBase mDrawable;
     private final String mSlotBattery;
     private final ImageView mBatteryIconView;
@@ -74,6 +85,7 @@
     private SettingObserver mSettingObserver;
     private int mTextColor;
     private int mLevel;
+    private int mShowPercentMode = MODE_DEFAULT;
     private boolean mForceShowPercent;
     private boolean mShowPercentAvailable;
 
@@ -154,7 +166,19 @@
     }
 
     public void setForceShowPercent(boolean show) {
-        mForceShowPercent = show;
+        setPercentShowMode(show ? MODE_ON : MODE_DEFAULT);
+    }
+
+    /**
+     * Force a particular mode of showing percent
+     *
+     * 0 - No preference
+     * 1 - Force on
+     * 2 - Force off
+     * @param mode desired mode (none, on, off)
+     */
+    public void setPercentShowMode(@BatteryPercentMode int mode) {
+        mShowPercentMode = mode;
         updateShowPercent();
     }
 
@@ -273,7 +297,8 @@
                 .getIntForUser(getContext().getContentResolver(),
                 SHOW_BATTERY_PERCENT, 0, mUser);
 
-        if ((mShowPercentAvailable && systemSetting) || mForceShowPercent) {
+        if ((mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
+                || mShowPercentMode == MODE_ON) {
             if (!showing) {
                 mBatteryPercentView = loadPercentView();
                 if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
diff --git a/packages/SystemUI/src/com/android/systemui/DejankUtils.java b/packages/SystemUI/src/com/android/systemui/DejankUtils.java
index 4ee3bd3..bec8820 100644
--- a/packages/SystemUI/src/com/android/systemui/DejankUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/DejankUtils.java
@@ -16,12 +16,12 @@
 
 package com.android.systemui;
 
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.util.Assert;
-
 import android.os.Handler;
 import android.view.Choreographer;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.util.Assert;
+
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index b7844bc..5e6d272 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -44,14 +44,15 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.PluginDependencyProvider;
 import com.android.systemui.plugins.PluginInitializerImpl;
-import com.android.systemui.recents.OverviewProxyService;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.shared.plugins.PluginManagerImpl;
 import com.android.systemui.plugins.VolumeDialogController;
 import com.android.systemui.power.EnhancedEstimates;
 import com.android.systemui.power.EnhancedEstimatesImpl;
 import com.android.systemui.power.PowerNotificationWarnings;
 import com.android.systemui.power.PowerUI;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManagerImpl;
+import com.android.systemui.statusbar.DisplayNavigationBarController;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.NotificationData.KeyguardEnvironment;
@@ -295,7 +296,7 @@
                 new WakefulnessLifecycle());
 
         mProviders.put(FragmentService.class, () ->
-                new FragmentService(mContext));
+                new FragmentService());
 
         mProviders.put(ExtensionController.class, () ->
                 new ExtensionControllerImpl(mContext));
@@ -362,6 +363,9 @@
         mProviders.put(AppOpsController.class, () ->
                 new AppOpsControllerImpl(mContext, getDependency(BG_LOOPER)));
 
+        mProviders.put(DisplayNavigationBarController.class, () ->
+                new DisplayNavigationBarController(mContext, getDependency(MAIN_HANDLER)));
+
         // Put all dependencies above here so the factory can override them if it wants.
         SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
 
diff --git a/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java b/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java
index 81e4db3..5c0df17 100644
--- a/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java
+++ b/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java
@@ -14,7 +14,6 @@
 
 package com.android.systemui;
 
-import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.IDockedStackListener;
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index f5ad747..ecf4c0a 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -32,9 +32,9 @@
 import android.view.ViewConfiguration;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.policy.ScrollAdapter;
 
 public class ExpandHelper implements Gefingerpoken {
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
index 1fa925e..bab472c 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
@@ -23,7 +23,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
-import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.messages.nano.SystemMessageProto;
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
index 9d286cf..cb9523f 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
@@ -42,8 +42,6 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 
-import com.android.systemui.R;
-
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index b1463a3..16e869e 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -14,6 +14,10 @@
 
 package com.android.systemui;
 
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -33,10 +37,6 @@
 import com.android.systemui.tuner.TunerService.Tunable;
 import com.android.systemui.util.leak.RotationUtils;
 
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
-
 public class HardwareUiLayout extends LinearLayout implements Tunable {
 
     private static final String EDGE_BLEED = "sysui_hwui_edge_bleed";
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index d8eb965..1d2d7fa 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -20,6 +20,7 @@
 import android.content.ComponentCallbacks2;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.RecordingCanvas;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region.Op;
@@ -30,7 +31,6 @@
 import android.util.Log;
 import android.view.Display;
 import android.view.DisplayInfo;
-import android.graphics.RecordingCanvas;
 import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.view.WindowManager;
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
index 1e458fa..50f1b44 100644
--- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java
+++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
@@ -16,17 +16,17 @@
 
 package com.android.systemui;
 
-import android.hardware.biometrics.BiometricSourceType;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.hardware.biometrics.BiometricSourceType;
 import android.os.Build;
 import android.os.PowerManager;
 import android.os.SystemClock;
 
-import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.internal.util.LatencyTracker;
+import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.statusbar.phone.BiometricUnlockController;
 import com.android.systemui.statusbar.phone.StatusBar;
 
diff --git a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
index f6ad626..f9617ca 100644
--- a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
@@ -21,8 +21,8 @@
 import android.view.View;
 
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.plugins.ViewProvider;
+import com.android.systemui.shared.plugins.PluginManager;
 
 /**
  * Define an interface or abstract class as follows that includes the
diff --git a/packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java b/packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java
index 6dc2d67..8351bbf 100644
--- a/packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java
@@ -21,7 +21,6 @@
 import android.graphics.Region.Op;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.InternalInsetsInfo;
 import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
 import android.widget.FrameLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index c844496..1dd231c 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -63,6 +63,8 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.util.Preconditions;
 import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView;
 import com.android.systemui.fragments.FragmentHostManager;
@@ -79,8 +81,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import androidx.annotation.VisibleForTesting;
-
 /**
  * An overlay that draws screen decorations in software (e.g for rounded corners or display cutout)
  * for antialiasing and emulation purposes.
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 3fe9944..3666400 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -33,10 +33,11 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityEvent;
+
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.FlingAnimationUtils;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 public class SwipeHelper implements Gefingerpoken {
     static final String TAG = "com.android.systemui.SwipeHelper";
@@ -87,8 +88,6 @@
     private Runnable mWatchLongPress;
     private final long mLongPressTimeout;
 
-    protected boolean mSwipingInProgress;
-
     final private int[] mTmpPos = new int[2];
     private final int mFalsingThreshold;
     private boolean mTouchAboveFalsingThreshold;
@@ -129,10 +128,6 @@
         mDisableHwLayers = disableHwLayers;
     }
 
-    public boolean isSwipingInProgress() {
-        return mSwipingInProgress;
-    }
-
     private float getPos(MotionEvent ev) {
         return mSwipeDirection == X ? ev.getX() : ev.getY();
     }
@@ -324,7 +319,6 @@
                     if (Math.abs(delta) > mPagingTouchSlop
                             && Math.abs(delta) > Math.abs(deltaPerpendicular)) {
                         if (mCallback.canChildBeDragged(mCurrView)) {
-                            mSwipingInProgress = true;
                             mCallback.onBeginDrag(mCurrView);
                             mDragging = true;
                             mInitialTouchPos = getPos(ev);
@@ -444,7 +438,6 @@
                     wasRemoved = row.isRemoved();
                 }
                 if (!mCancelled || wasRemoved) {
-                    mSwipingInProgress = false;
                     mCallback.onChildDismissed(animView);
                 }
                 if (endAction != null) {
@@ -604,13 +597,15 @@
                     }
                     // don't let items that can't be dismissed be dragged more than
                     // maxScrollDistance
-                    if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissed(mCurrView)) {
+                    if (CONSTRAIN_SWIPE && !mCallback.canChildBeDismissedInDirection(mCurrView,
+                            delta > 0)) {
                         float size = getSize(mCurrView);
                         float maxScrollDistance = MAX_SCROLL_SIZE_FRACTION * size;
                         if (absDelta >= size) {
                             delta = delta > 0 ? maxScrollDistance : -maxScrollDistance;
                         } else {
-                            delta = maxScrollDistance * (float) Math.sin((delta/size)*(Math.PI/2));
+                            delta = maxScrollDistance * (float) Math.sin(
+                                    (delta / size) * (Math.PI / 2));
                         }
                     }
 
@@ -634,7 +629,6 @@
                                 !swipedFastEnough() /* useAccelerateInterpolator */);
                     } else {
                         // snappity
-                        mSwipingInProgress = false;
                         mCallback.onDragCancelled(mCurrView);
                         snapChild(mCurrView, 0 /* leftTarget */, velocity);
                     }
@@ -674,9 +668,11 @@
     }
 
     public boolean isDismissGesture(MotionEvent ev) {
+        float translation = getTranslation(mCurrView);
         return ev.getActionMasked() == MotionEvent.ACTION_UP
+                && !mFalsingManager.isUnlockingDisabled()
                 && !isFalseGesture(ev) && (swipedFastEnough() || swipedFarEnough())
-                && mCallback.canChildBeDismissed(mCurrView);
+                && mCallback.canChildBeDismissedInDirection(mCurrView, translation > 0);
     }
 
     public boolean isFalseGesture(MotionEvent ev) {
@@ -707,6 +703,16 @@
 
         boolean canChildBeDismissed(View v);
 
+        /**
+         * Returns true if the provided child can be dismissed by a swipe in the given direction.
+         *
+         * @param isRightOrDown {@code true} if the swipe direction is right or down,
+         *                      {@code false} if it is left or up.
+         */
+        default boolean canChildBeDismissedInDirection(View v, boolean isRightOrDown) {
+            return canChildBeDismissed(v);
+        }
+
         boolean isAntiFalsingNeeded();
 
         void onBeginDrag(View v);
diff --git a/packages/SystemUI/src/com/android/systemui/SysUIToast.java b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
index 43b918d..8bcf057 100644
--- a/packages/SystemUI/src/com/android/systemui/SysUIToast.java
+++ b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
@@ -15,11 +15,12 @@
  */
 package com.android.systemui;
 
+import static android.widget.Toast.Duration;
+
 import android.annotation.StringRes;
 import android.content.Context;
 import android.view.WindowManager;
 import android.widget.Toast;
-import static android.widget.Toast.Duration;
 
 public class SysUIToast {
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemBars.java b/packages/SystemUI/src/com/android/systemui/SystemBars.java
index b5093b3..6edc23b 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemBars.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemBars.java
@@ -14,13 +14,8 @@
 
 package com.android.systemui;
 
-import android.content.res.Configuration;
-import android.provider.Settings;
 import android.util.Log;
 
-import com.android.systemui.R;
-import com.android.systemui.SystemUI;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index c4bf27b..2dd362e 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -22,9 +22,9 @@
 import android.util.Log;
 import android.view.ViewGroup;
 
+import com.android.internal.colorextraction.ColorExtractor.GradientColors;
 import com.android.internal.util.function.TriConsumer;
 import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.colorextraction.ColorExtractor.GradientColors;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.Dependency.DependencyProvider;
 import com.android.systemui.classifier.FalsingManager;
@@ -32,20 +32,20 @@
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.statusbar.AmbientPulseManager;
 import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 8e29841..ac108be 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -24,13 +24,13 @@
 import android.os.SystemProperties;
 import android.util.Slog;
 
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
 import com.android.internal.os.BinderInternal;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.plugins.PluginManagerImpl;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 public class SystemUIService extends Service {
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
index 69e347c9..46e004c 100644
--- a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
+++ b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.analytics;
 
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
+
 import android.content.Context;
 import android.database.ContentObserver;
 import android.hardware.Sensor;
@@ -32,13 +35,15 @@
 import android.view.MotionEvent;
 import android.widget.Toast;
 
+import com.android.systemui.Dependency;
+import com.android.systemui.plugins.FalsingPlugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.shared.plugins.PluginManager;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
-
 /**
  * Tracks touch, sensor and phone events when the lockscreen is on. If the phone is unlocked
  * the data containing these events is saved to a file. This data is collected
@@ -53,6 +58,8 @@
     private static final String COLLECT_BAD_TOUCHES = "data_collector_collect_bad_touches";
     private static final String ALLOW_REJECTED_TOUCH_REPORTS =
             "data_collector_allow_rejected_touch_reports";
+    private static final String DISABLE_UNLOCKING_FOR_FALSING_COLLECTION =
+            "data_collector_disable_unlocking";
 
     private static final long TIMEOUT_MILLIS = 11000; // 11 seconds.
     public static final boolean DEBUG = false;
@@ -65,14 +72,16 @@
     private SensorLoggerSession mCurrentSession = null;
 
     private boolean mEnableCollector = false;
-    private boolean mTimeoutActive = false;
     private boolean mCollectBadTouches = false;
     private boolean mCornerSwiping = false;
     private boolean mTrackingStarted = false;
     private boolean mAllowReportRejectedTouch = false;
+    private boolean mDisableUnlocking = false;
 
     private static DataCollector sInstance = null;
 
+    private FalsingPlugin mFalsingPlugin = null;
+
     protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
         @Override
         public void onChange(boolean selfChange) {
@@ -80,6 +89,16 @@
         }
     };
 
+    private final PluginListener mPluginListener = new PluginListener<FalsingPlugin>() {
+        public void onPluginConnected(FalsingPlugin plugin, Context context) {
+            mFalsingPlugin = plugin;
+        }
+
+        public void onPluginDisconnected(FalsingPlugin plugin) {
+            mFalsingPlugin = null;
+        }
+    };
+
     private DataCollector(Context context) {
         mContext = context;
 
@@ -98,7 +117,14 @@
                 mSettingsObserver,
                 UserHandle.USER_ALL);
 
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(DISABLE_UNLOCKING_FOR_FALSING_COLLECTION), false,
+                mSettingsObserver,
+                UserHandle.USER_ALL);
+
         updateConfiguration();
+
+        Dependency.get(PluginManager.class).addPluginListener(mPluginListener, FalsingPlugin.class);
     }
 
     public static DataCollector getInstance(Context context) {
@@ -118,6 +144,9 @@
         mAllowReportRejectedTouch = Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
                 mContext.getContentResolver(),
                 ALLOW_REJECTED_TOUCH_REPORTS, 0);
+        mDisableUnlocking = mEnableCollector && Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt(
+                mContext.getContentResolver(),
+                DISABLE_UNLOCKING_FOR_FALSING_COLLECTION, 0);
     }
 
     private boolean sessionEntrypoint() {
@@ -144,7 +173,7 @@
         SensorLoggerSession session = mCurrentSession;
         mCurrentSession = null;
 
-        if (mEnableCollector) {
+        if (mEnableCollector || mDisableUnlocking) {
             session.end(System.currentTimeMillis(), result);
             queueSession(session);
         }
@@ -181,24 +210,28 @@
             @Override
             public void run() {
                 byte[] b = Session.toByteArray(currentSession.toProto());
-                String dir = mContext.getFilesDir().getAbsolutePath();
-                if (currentSession.getResult() != Session.SUCCESS) {
-                    if (!mCollectBadTouches) {
-                        return;
-                    }
-                    dir += "/bad_touches";
+
+                if (mFalsingPlugin != null) {
+                    mFalsingPlugin.dataCollected(currentSession.getResult() == Session.SUCCESS, b);
                 } else {
-                    dir += "/good_touches";
-                }
+                    String dir = mContext.getFilesDir().getAbsolutePath();
+                    if (currentSession.getResult() != Session.SUCCESS) {
+                        if (!mDisableUnlocking && !mCollectBadTouches) {
+                            return;
+                        }
+                        dir += "/bad_touches";
+                    } else if (!mDisableUnlocking) {
+                        dir += "/good_touches";
+                    }
 
-                File file = new File(dir);
-                file.mkdir();
-                File touch = new File(file, "trace_" + System.currentTimeMillis());
-
-                try {
-                    new FileOutputStream(touch).write(b);
-                } catch (IOException e) {
-                    throw new RuntimeException(e);
+                    File file = new File(dir);
+                    file.mkdir();
+                    File touch = new File(file, "trace_" + System.currentTimeMillis());
+                    try {
+                        new FileOutputStream(touch).write(b);
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
                 }
             }
         });
@@ -208,19 +241,6 @@
     public synchronized void onSensorChanged(SensorEvent event) {
         if (isEnabled() && mCurrentSession != null) {
             mCurrentSession.addSensorEvent(event, System.nanoTime());
-            enforceTimeout();
-        }
-    }
-
-    private void enforceTimeout() {
-        if (mTimeoutActive) {
-            if (System.currentTimeMillis() - mCurrentSession.getStartTimestampMillis()
-                    > TIMEOUT_MILLIS) {
-                onSessionEnd(Session.UNKNOWN);
-                if (DEBUG) {
-                    Log.i(TAG, "Analytics timed out.");
-                }
-            }
         }
     }
 
@@ -233,9 +253,12 @@
      *         rejected touch report.
      */
     public boolean isEnabled() {
-        return mEnableCollector || mAllowReportRejectedTouch;
+        return mEnableCollector || mAllowReportRejectedTouch || mDisableUnlocking;
     }
 
+    public boolean isUnlockingDisabled() {
+        return mDisableUnlocking;
+    }
     /**
      * @return true if the full data set for data gathering should be collected - including
      *         extensive sensor data, which is is not normally included with rejected touch reports.
@@ -450,7 +473,6 @@
             }
             mCurrentSession.addMotionEvent(event);
             mCurrentSession.setTouchArea(width, height);
-            enforceTimeout();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
index d6472b7..d294012 100644
--- a/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
+++ b/packages/SystemUI/src/com/android/systemui/analytics/SensorLoggerSession.java
@@ -16,17 +16,17 @@
 
 package com.android.systemui.analytics;
 
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.SensorEvent;
+import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.TouchEvent;
+
 import android.os.Build;
 import android.util.Log;
 import android.view.MotionEvent;
 
 import java.util.ArrayList;
 
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.SensorEvent;
-import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.TouchEvent;
-
 /**
  * Collects touch, sensor and phone events and converts the data to
  * TouchAnalyticsProto.Session.
@@ -104,6 +104,7 @@
         proto.startTimestampMillis = mStartTimestampMillis;
         proto.durationMillis = mEndTimestampMillis - mStartTimestampMillis;
         proto.build = Build.FINGERPRINT;
+        proto.deviceId = Build.DEVICE;
         proto.result = mResult;
         proto.type = mType;
         proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents);
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
index 4bd095d..79d4f8d 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
@@ -31,7 +31,6 @@
 import android.view.View;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.animation.AnimationUtils;
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
index 67bc8b6..c0047c0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -140,7 +140,7 @@
 
     @Override
     public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation) {
+            boolean requireConfirmation, int userId) {
         if (DEBUG) Log.d(TAG, "showBiometricDialog, type: " + type);
         // Remove these messages as they are part of the previous client
         mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
@@ -151,6 +151,7 @@
         args.arg2 = receiver;
         args.argi1 = type;
         args.arg3 = requireConfirmation;
+        args.argi2 = userId;
         mHandler.obtainMessage(MSG_SHOW_DIALOG, args).sendToTarget();
     }
 
@@ -194,7 +195,8 @@
         }
         mReceiver = (IBiometricPromptReceiver) args.arg2;
         mCurrentDialog.setBundle((Bundle)args.arg1);
-        mCurrentDialog.setRequireConfirmation((boolean)args.arg3);
+        mCurrentDialog.setRequireConfirmation((boolean) args.arg3);
+        mCurrentDialog.setUserId(args.argi2);
         mCurrentDialog.setSkipIntro(skipAnimation);
         mWindowManager.addView(mCurrentDialog, mCurrentDialog.getLayoutParams());
         mDialogShowing = true;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
index 7935115..38427ad 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
@@ -16,15 +16,19 @@
 
 package com.android.systemui.biometrics;
 
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
 import android.hardware.biometrics.BiometricPrompt;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
+import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -42,6 +46,7 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.util.leak.RotationUtils;
 
 /**
  * Abstract base class. Shows a dialog for BiometricPrompt.
@@ -63,6 +68,8 @@
     private final IBinder mWindowToken = new Binder();
     private final Interpolator mLinearOutSlowIn;
     private final WindowManager mWindowManager;
+    private final UserManager mUserManager;
+    private final DevicePolicyManager mDevicePolicyManager;
     private final float mAnimationTranslationOffset;
     private final int mErrorColor;
     private final int mTextColor;
@@ -78,6 +85,7 @@
     private boolean mWasForceRemoved;
     private boolean mSkipIntro;
     protected boolean mRequireConfirmation;
+    private int mUserId; // used to determine if we should show work background
 
     protected abstract void updateIcon(int lastState, int newState);
     protected abstract int getHintStringResourceId();
@@ -120,7 +128,9 @@
         super(context);
         mCallback = callback;
         mLinearOutSlowIn = Interpolators.LINEAR_OUT_SLOW_IN;
-        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        mWindowManager = mContext.getSystemService(WindowManager.class);
+        mUserManager = mContext.getSystemService(UserManager.class);
+        mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
         mAnimationTranslationOffset = getResources()
                 .getDimension(R.dimen.biometric_dialog_animation_translation_offset);
 
@@ -198,8 +208,23 @@
         final TextView description = mLayout.findViewById(R.id.description);
         final Button negative = mLayout.findViewById(R.id.button2);
         final Button positive = mLayout.findViewById(R.id.button1);
+        final ImageView backgroundView = mLayout.findViewById(R.id.background);
 
-        mDialog.getLayoutParams().width = (int) mDialogWidth;
+        if (mUserManager.isManagedProfile(mUserId)) {
+            final Drawable image = getResources().getDrawable(R.drawable.work_challenge_background,
+                    mContext.getTheme());
+            image.setColorFilter(mDevicePolicyManager.getOrganizationColorForUser(mUserId),
+                    PorterDuff.Mode.DARKEN);
+            backgroundView.setImageDrawable(image);
+        } else {
+            backgroundView.setImageDrawable(null);
+            backgroundView.setBackgroundColor(R.color.biometric_dialog_dim_color);
+        }
+
+        if (RotationUtils.getRotation(mContext) != RotationUtils.ROTATION_NONE) {
+            mDialog.getLayoutParams().width = (int) mDialogWidth;
+        }
+
         mLastState = STATE_NONE;
         updateState(STATE_AUTHENTICATING);
 
@@ -325,6 +350,10 @@
         positive.setVisibility(View.VISIBLE);
     }
 
+    public void setUserId(int userId) {
+        mUserId = userId;
+    }
+
     public ViewGroup getLayout() {
         return mLayout;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
index 96af08b..50fefe9 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
@@ -17,9 +17,9 @@
 
 import android.content.Context;
 
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 public class CarNotificationEntryManager extends NotificationEntryManager {
     public CarNotificationEntryManager(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
index e4b2e07..09c000b 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
@@ -23,10 +23,10 @@
 import com.android.systemui.Dependency.DependencyProvider;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.car.CarFacetButtonController;
 import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.car.hvac.HvacController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java b/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
new file mode 100644
index 0000000..28a3808
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 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.chooser;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Activity for selecting which application ought to handle an ACTION_SEND intent.
+ */
+public final class ChooserActivity extends Activity {
+
+    private static final String TAG = "ChooserActivity";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        ChooserHelper.onChoose(this);
+        finish();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/chooser/ChooserHelper.java b/packages/SystemUI/src/com/android/systemui/chooser/ChooserHelper.java
new file mode 100644
index 0000000..a7df6f1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/chooser/ChooserHelper.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 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.chooser;
+
+import android.app.Activity;
+import android.app.ActivityTaskManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+
+/**
+ * When a target is chosen from the SystemUI Chooser activity, unpack its arguments and
+ * startActivityAsCaller to handle the now-chosen intent.
+ */
+public class ChooserHelper {
+
+    private static final String TAG = "ChooserHelper";
+
+    static void onChoose(Activity activity) {
+        final Intent thisIntent = activity.getIntent();
+        final Bundle thisExtras = thisIntent.getExtras();
+        final Intent chosenIntent = thisIntent.getParcelableExtra(Intent.EXTRA_INTENT);
+        final Bundle options = thisIntent.getParcelableExtra(ActivityTaskManager.EXTRA_OPTIONS);
+        final IBinder permissionToken =
+                thisExtras.getBinder(ActivityTaskManager.EXTRA_PERMISSION_TOKEN);
+        final boolean ignoreTargetSecurity =
+                thisIntent.getBooleanExtra(ActivityTaskManager.EXTRA_IGNORE_TARGET_SECURITY, false);
+        final int userId = thisIntent.getIntExtra(Intent.EXTRA_USER_ID, -1);
+        activity.startActivityAsCaller(
+                chosenIntent, options, permissionToken, ignoreTargetSecurity, userId);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
index cdf4ba7..6d13973 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
@@ -18,7 +18,6 @@
 
 import android.os.Build;
 import android.os.SystemProperties;
-import android.util.Log;
 import android.view.MotionEvent;
 
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
index 71ddba5..cb7c998 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
@@ -23,8 +23,6 @@
 import android.util.Log;
 
 import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 3d578c3..2c61da3 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -201,6 +201,9 @@
         return mHumanInteractionClassifier.isEnabled() || mDataCollector.isEnabled();
     }
 
+    public boolean isUnlockingDisabled() {
+        return mDataCollector.isUnlockingDisabled();
+    }
     /**
      * @return true if the classifier determined that this is not a human interacting with the phone
      */
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index 592a275..577d57a 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -24,13 +24,11 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
-import android.util.Log;
 import android.view.MotionEvent;
 
 import com.android.systemui.R;
 
 import java.util.ArrayDeque;
-import java.util.ArrayList;
 
 /**
  * An classifier trying to determine whether it is a human interacting with the phone or not.
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index e2047bf..d93ed178 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -22,7 +22,6 @@
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
 import android.os.Handler;
-import android.os.PowerManager;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.keyguard.KeyguardUpdateMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java b/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java
index 30dfd36..4a2e06c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java
@@ -22,11 +22,6 @@
 public interface DozeReceiver {
 
     /**
-     * If device enters or leaves doze mode
-     */
-    void setDozing(boolean dozing);
-
-    /**
      * Invoked every time a minute is elapsed in doze mode
      */
     void dozeTimeTick();
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 5d99c57..01a2345 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -31,6 +31,7 @@
 import android.provider.Settings;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Dependency;
 
 /**
  * Controls the screen brightness when dozing.
@@ -82,9 +83,11 @@
         mSensorToScrimOpacity = sensorToScrimOpacity;
 
         if (mDebuggable) {
-            IntentFilter filter = new IntentFilter();
-            filter.addAction(ACTION_AOD_BRIGHTNESS);
-            mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, null);
+            Dependency.get(Dependency.BG_HANDLER).post(()-> {
+                IntentFilter filter = new IntentFilter();
+                filter.addAction(ACTION_AOD_BRIGHTNESS);
+                mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, handler);
+            });
         }
     }
 
@@ -123,7 +126,9 @@
     private void onDestroy() {
         setLightSensorEnabled(false);
         if (mDebuggable) {
-            mContext.unregisterReceiver(this);
+            Dependency.get(Dependency.BG_HANDLER).post(()-> {
+                mContext.unregisterReceiver(this);
+            });
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
index 4fc2d9b..25c2c39 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
@@ -16,9 +16,10 @@
 
 package com.android.systemui.doze;
 
-import androidx.annotation.VisibleForTesting;
 import android.view.Display;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index c61e10a..4557b4d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -38,6 +38,7 @@
 
     private DozeMachine mDozeMachine;
     private DozeServicePlugin mDozePlugin;
+    private PluginManager mPluginManager;
 
     public DozeService() {
         setDebug(DEBUG);
@@ -53,14 +54,14 @@
             finish();
             return;
         }
-        Dependency.get(PluginManager.class).addPluginListener(this,
-                DozeServicePlugin.class, false /* Allow multiple */);
+        mPluginManager = Dependency.get(PluginManager.class);
+        mPluginManager.addPluginListener(this, DozeServicePlugin.class, false /* allowMultiple */);
         mDozeMachine = new DozeFactory().assembleMachine(this);
     }
 
     @Override
     public void onDestroy() {
-        Dependency.get(PluginManager.class).removePluginListener(this);
+        mPluginManager.removePluginListener(this);
         super.onDestroy();
         mDozeMachine = null;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
index 3013b96..a0c490951 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
@@ -16,9 +16,10 @@
 
 package com.android.systemui.doze;
 
-import androidx.annotation.VisibleForTesting;
 import android.view.Display;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
index 47f86fe..9a5a5b8 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
@@ -23,8 +23,6 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
index f06ea45..84b91bc 100644
--- a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
@@ -19,7 +19,6 @@
 import android.app.Activity;
 import android.os.Bundle;
 import android.view.View;
-import android.view.ViewGroup;
 
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 0ed1cd1..60e39b2 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -28,11 +28,12 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Parcelable;
-import androidx.annotation.NonNull;
 import android.util.ArrayMap;
 import android.view.LayoutInflater;
 import android.view.View;
 
+import androidx.annotation.NonNull;
+
 import com.android.settingslib.applications.InterestingConfigChanges;
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.Plugin;
@@ -59,11 +60,11 @@
     private FragmentController mFragments;
     private FragmentLifecycleCallbacks mLifecycleCallbacks;
 
-    FragmentHostManager(Context context, FragmentService manager, View rootView) {
-        mContext = context;
+    FragmentHostManager(FragmentService manager, View rootView) {
+        mContext = rootView.getContext();
         mManager = manager;
         mRootView = rootView;
-        mConfigChanges.applyNewConfig(context.getResources());
+        mConfigChanges.applyNewConfig(mContext.getResources());
         createFragmentHost(null);
     }
 
@@ -203,6 +204,10 @@
         }
     }
 
+    public static void removeAndDestroy(View view) {
+        Dependency.get(FragmentService.class).removeAndDestroy(view);
+    }
+
     class HostCallbacks extends FragmentHostCallback<FragmentHostManager> {
         public HostCallbacks() {
             super(mContext, FragmentHostManager.this.mHandler, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index f9bf4f5..bf7d629 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -14,18 +14,13 @@
 
 package com.android.systemui.fragments;
 
-import android.content.Context;
 import android.content.res.Configuration;
-import android.os.Bundle;
 import android.os.Handler;
 import android.util.ArrayMap;
-import android.util.Log;
 import android.view.View;
 
 import com.android.systemui.ConfigurationChangedReceiver;
 import com.android.systemui.Dumpable;
-import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIApplication;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -40,11 +35,6 @@
 
     private final ArrayMap<View, FragmentHostState> mHosts = new ArrayMap<>();
     private final Handler mHandler = new Handler();
-    private final Context mContext;
-
-    public FragmentService(Context context) {
-        mContext = context;
-    }
 
     public FragmentHostManager getFragmentHostManager(View view) {
         View root = view.getRootView();
@@ -56,6 +46,13 @@
         return state.getFragmentHostManager();
     }
 
+    public void removeAndDestroy(View view) {
+        final FragmentHostState state = mHosts.remove(view.getRootView());
+        if (state != null) {
+            state.mFragmentHostManager.destroy();
+        }
+    }
+
     public void destroyAll() {
         for (FragmentHostState state : mHosts.values()) {
             state.mFragmentHostManager.destroy();
@@ -84,7 +81,7 @@
 
         public FragmentHostState(View view) {
             mView = view;
-            mFragmentHostManager = new FragmentHostManager(mContext, FragmentService.this, mView);
+            mFragmentHostManager = new FragmentHostManager(FragmentService.this, mView);
         }
 
         public void sendConfigurationChange(Configuration newConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index e0657c9..7d52a9a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -43,12 +43,12 @@
 import android.widget.Toast;
 
 import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
 import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
index d833c16..7bec5c0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
@@ -19,6 +19,7 @@
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.systemui.Dependency;
 import com.android.systemui.UiOffloadThread;
+
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
index 4c98c08..b3481c5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
@@ -19,8 +19,6 @@
 import android.os.Handler;
 import android.os.Message;
 
-import com.android.internal.policy.IKeyguardDrawnCallback;
-
 /**
  * Dispatches the lifecycles keyguard gets from WindowManager on the main thread.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 22b41a4..81247cd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.keyguard;
 
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import android.app.Service;
 import android.content.Intent;
 import android.os.Binder;
@@ -34,8 +36,6 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.SystemUIApplication;
 
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
 public class KeyguardService extends Service {
     static final String TAG = "KeyguardService";
     static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 82b79ac..e78951a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -25,7 +25,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.graphics.drawable.Icon;
 import android.icu.text.DateFormat;
 import android.icu.text.DisplayContext;
 import android.net.Uri;
@@ -35,6 +34,13 @@
 import android.service.notification.ZenModeConfig;
 import android.text.TextUtils;
 
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.SliceProvider;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.ListBuilder.RowBuilder;
+import androidx.slice.builders.SliceAction;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NextAlarmController;
@@ -46,13 +52,6 @@
 import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
-import androidx.core.graphics.drawable.IconCompat;
-import androidx.slice.Slice;
-import androidx.slice.SliceProvider;
-import androidx.slice.builders.ListBuilder;
-import androidx.slice.builders.ListBuilder.RowBuilder;
-import androidx.slice.builders.SliceAction;
-
 /**
  * Simple Slice provider that shows the current date.
  */
@@ -226,7 +225,7 @@
     private void updateNextAlarm() {
         if (withinNHours(mNextAlarmInfo, ALARM_VISIBILITY_HOURS)) {
             String pattern = android.text.format.DateFormat.is24HourFormat(getContext(),
-                    ActivityManager.getCurrentUser()) ? "H:mm" : "h:mm";
+                    ActivityManager.getCurrentUser()) ? "HH:mm" : "h:mm";
             mNextAlarm = android.text.format.DateFormat.format(pattern,
                     mNextAlarmInfo.getTriggerTime()).toString();
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4988f07..3b9110d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -17,7 +17,6 @@
 package com.android.systemui.keyguard;
 
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-import static android.view.Display.INVALID_DISPLAY;
 
 import static com.android.internal.telephony.IccCardConstants.State.ABSENT;
 import static com.android.internal.telephony.IccCardConstants.State.PIN_REQUIRED;
@@ -95,6 +94,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 
 /**
  * Mediates requests related to the keyguard.  This includes queries about the
@@ -246,8 +246,8 @@
     // AOD is enabled and status bar is in AOD state.
     private boolean mAodShowing;
 
-    // display id of the secondary display on which we have put a keyguard window
-    private int mSecondaryDisplayShowing = INVALID_DISPLAY;
+    // display ids of the external display on which we have put a keyguard window
+    private int[] mSecondaryDisplaysShowing;
 
     /** Cached value of #isInputRestricted */
     private boolean mInputRestricted;
@@ -700,9 +700,9 @@
         }
 
         @Override
-        public void onSecondaryDisplayShowingChanged(int displayId) {
+        public void onSecondaryDisplayShowingChanged(int[] displayIds) {
             synchronized (KeyguardViewMediator.this) {
-                setShowingLocked(mShowing, mAodShowing, displayId, false);
+                setShowingLocked(mShowing, mAodShowing, displayIds, false);
             }
         }
     };
@@ -749,10 +749,10 @@
             setShowingLocked(!shouldWaitForProvisioning()
                     && !mLockPatternUtils.isLockScreenDisabled(
                             KeyguardUpdateMonitor.getCurrentUser()),
-                    mAodShowing, mSecondaryDisplayShowing, true /* forceCallbacks */);
+                    mAodShowing, mSecondaryDisplaysShowing, true /* forceCallbacks */);
         } else {
             // The system's keyguard is disabled or missing.
-            setShowingLocked(false, mAodShowing, mSecondaryDisplayShowing, true);
+            setShowingLocked(false, mAodShowing, mSecondaryDisplaysShowing, true);
         }
 
         mStatusBarKeyguardViewManager =
@@ -1776,11 +1776,11 @@
     }
 
     private void updateActivityLockScreenState(boolean showing, boolean aodShowing,
-            int secondaryDisplayShowing) {
+            int[] secondaryDisplaysShowing) {
         mUiOffloadThread.submit(() -> {
             try {
                 ActivityTaskManager.getService().setLockScreenShown(showing, aodShowing,
-                        secondaryDisplayShowing);
+                        secondaryDisplaysShowing);
             } catch (RemoteException e) {
             }
         });
@@ -1895,7 +1895,8 @@
 
             if (!mHiding) {
                 // Tell ActivityManager that we canceled the keyguardExitAnimation.
-                setShowingLocked(mShowing, mAodShowing, mSecondaryDisplayShowing, true /* force */);
+                setShowingLocked(mShowing, mAodShowing, mSecondaryDisplaysShowing,
+                        true /* force */);
                 return;
             }
             mHiding = false;
@@ -1939,11 +1940,6 @@
                     mContext.getSystemService(Context.STATUS_BAR_SERVICE);
         }
 
-        // TODO(b/113914868): investigation log for disappearing home button
-        Log.d(TAG, "adjustStatusBarLocked (b/113914868): mShowing=" + mShowing
-                + " mStatusBarManager=" + mStatusBarManager + " mOccluded="
-                + mOccluded + " isSecure=" + isSecure() + " force=" + forceHideHomeRecentsButtons);
-
         if (mStatusBarManager == null) {
             Log.w(TAG, "Could not get status bar manager");
         } else {
@@ -1960,6 +1956,12 @@
                         +  " --> flags=0x" + Integer.toHexString(flags));
             }
 
+            // TODO(b/113914868): investigation log for disappearing home button
+            Log.d(TAG, "adjustStatusBarLocked (b/113914868): flags=" + flags
+                    + "mShowing=" + mShowing + " mStatusBarManager=" + mStatusBarManager
+                    + " mOccluded=" + mOccluded + " isSecure=" + isSecure()
+                    + " force=" + forceHideHomeRecentsButtons);
+
             mStatusBarManager.disable(flags);
         }
     }
@@ -2164,22 +2166,23 @@
     }
 
     private void setShowingLocked(boolean showing, boolean aodShowing) {
-        setShowingLocked(showing, aodShowing, mSecondaryDisplayShowing,
+        setShowingLocked(showing, aodShowing, mSecondaryDisplaysShowing,
                 false /* forceCallbacks */);
     }
 
-    private void setShowingLocked(boolean showing, boolean aodShowing, int secondaryDisplayShowing,
-            boolean forceCallbacks) {
+    private void setShowingLocked(boolean showing, boolean aodShowing,
+            int[] secondaryDisplaysShowing, boolean forceCallbacks) {
         final boolean notifyDefaultDisplayCallbacks = showing != mShowing
                 || aodShowing != mAodShowing || forceCallbacks;
-        if (notifyDefaultDisplayCallbacks || secondaryDisplayShowing != mSecondaryDisplayShowing) {
+        if (notifyDefaultDisplayCallbacks
+                || !Arrays.equals(secondaryDisplaysShowing, mSecondaryDisplaysShowing)) {
             mShowing = showing;
             mAodShowing = aodShowing;
-            mSecondaryDisplayShowing = secondaryDisplayShowing;
+            mSecondaryDisplaysShowing = secondaryDisplaysShowing;
             if (notifyDefaultDisplayCallbacks) {
                 notifyDefaultDisplayCallbacks(showing);
             }
-            updateActivityLockScreenState(showing, aodShowing, secondaryDisplayShowing);
+            updateActivityLockScreenState(showing, aodShowing, secondaryDisplaysShowing);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
index 74f7706..6498b91 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
@@ -28,6 +28,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Log;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index ab612dd..ddd9cbf 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -33,10 +33,8 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.MediaStore;
-import android.provider.MediaStore.Audio.AudioColumns;
 import android.util.Log;
 
-import com.android.internal.util.Preconditions;
 import com.android.systemui.SystemUI;
 
 import java.io.FileDescriptor;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
index 70b581a..7792e17 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
@@ -23,8 +23,10 @@
 import android.content.res.Configuration;
 import android.os.UserHandle;
 import android.os.UserManager;
+
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.CommandQueue;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index 9ce2606..8615e43 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -27,6 +27,7 @@
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 import android.widget.FrameLayout;
+
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.shared.system.WindowManagerWrapper;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 08208e5..8c3f436 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -35,6 +35,7 @@
 import android.view.IPinnedStackListener;
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.pip.BasePipManager;
@@ -42,6 +43,7 @@
 import com.android.systemui.shared.system.InputConsumerController;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.WindowManagerWrapper;
+
 import java.io.PrintWriter;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index b746c19..e447def 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -23,15 +23,14 @@
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ACTIONS;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ALLOW_TIMEOUT;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_CONTROLLER_MESSENGER;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_WILL_RESIZE_MENU;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_DISMISS_FRACTION;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MOVEMENT_BOUNDS;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MENU_STATE;
+import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MOVEMENT_BOUNDS;
 import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS;
-
-import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
+import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_WILL_RESIZE_MENU;
 import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE;
 import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL;
+import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 56b8324..46d53e4 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -37,8 +37,10 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Log;
+
 import com.android.systemui.pip.phone.PipMediaController.ActionListener;
 import com.android.systemui.shared.system.InputConsumerController;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index ce7da79..3858356 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -18,6 +18,7 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+
 import static com.android.systemui.Interpolators.FAST_OUT_LINEAR_IN;
 import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.systemui.Interpolators.LINEAR_OUT_SLOW_IN;
@@ -42,11 +43,13 @@
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.animation.Interpolator;
+
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.policy.PipSnapAlgorithm;
 import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.statusbar.FlingAnimationUtils;
+
 import java.io.PrintWriter;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index b9369d3..9aa21f8 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -18,7 +18,6 @@
 
 import android.graphics.PointF;
 import android.os.Handler;
-import android.os.SystemClock;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
index 10206d4..a40b72b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.pip.tv;
 
-import android.app.ActivityManager;
 import android.app.PendingIntent.CanceledException;
 import android.app.RemoteAction;
 import android.content.Context;
@@ -24,20 +23,15 @@
 import android.media.session.MediaController;
 import android.media.session.PlaybackState;
 import android.os.Handler;
-import android.os.RemoteException;
+import android.util.AttributeSet;
 import android.util.Log;
-import android.view.View;
 import android.view.Gravity;
 import android.view.LayoutInflater;
-import android.widget.ImageView;
+import android.view.View;
 import android.widget.LinearLayout;
-import android.util.AttributeSet;
 
 import com.android.systemui.R;
 
-import static android.media.session.PlaybackState.ACTION_PAUSE;
-import static android.media.session.PlaybackState.ACTION_PLAY;
-
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index e17e0bc..ca3cdf4 100755
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -49,6 +49,7 @@
 import android.view.IPinnedStackListener;
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.UiOffloadThread;
@@ -56,7 +57,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.WindowManagerWrapper;
-import java.io.PrintWriter;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
index e437eff..3a5fa22 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
@@ -22,7 +22,6 @@
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
 import android.os.Bundle;
-import android.view.View;
 
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
index ac41b75..89ecc6a 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
@@ -26,17 +26,15 @@
 import android.content.pm.ParceledListSlice;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.drawable.Icon;
 import android.media.MediaMetadata;
 import android.media.session.MediaController;
 import android.media.session.PlaybackState;
 import android.text.TextUtils;
 import android.util.Log;
-import android.view.View;
 
-import com.android.systemui.util.NotificationChannels;
-import com.android.systemui.R;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.systemui.R;
+import com.android.systemui.util.NotificationChannels;
 
 /**
  * A notification that informs users that PIP is running and also provides PIP controls.
diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
index 5686d80..3f24176 100644
--- a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
@@ -1,7 +1,5 @@
 package com.android.systemui.power;
 
-import android.util.Log;
-
 public class EnhancedEstimatesImpl implements EnhancedEstimates {
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 21eab59..b722f9f 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -41,6 +41,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.view.View;
+
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 568a039..35ae899 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -399,8 +399,8 @@
             if (b != null) {
                 mThermalService = IThermalService.Stub.asInterface(b);
                 try {
-                    mThermalService.registerThermalEventListener(
-                        new ThermalEventListener());
+                    mThermalService.registerThermalEventListenerWithType(
+                            new ThermalEventListener(), Temperature.TYPE_SKIN);
                 } catch (RemoteException e) {
                     // Should never happen.
                 }
@@ -552,7 +552,7 @@
 
     // Thermal event received from vendor thermal management subsystem
     private final class ThermalEventListener extends IThermalEventListener.Stub {
-        @Override public void notifyThrottling(boolean isThrottling, Temperature temp) {
+        @Override public void notifyThrottling(Temperature temp) {
             // Trigger an update of the temperature warning.  Only one
             // callback can be enabled at a time, so remove any existing
             // callback; updateTemperatureWarning will schedule another one.
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index 3953139d..d3715d0 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -14,21 +14,13 @@
 
 package com.android.systemui.privacy
 
-import android.app.ActivityManager
-import android.app.AppOpsManager
 import android.content.Context
-import android.graphics.Color
-import android.os.UserHandle
-import android.os.UserManager
 import android.util.AttributeSet
 import android.view.ViewGroup
 import android.widget.ImageView
 import android.widget.LinearLayout
 import android.widget.TextView
-import com.android.systemui.Dependency
 import com.android.systemui.R
-import com.android.systemui.appops.AppOpItem
-import com.android.systemui.appops.AppOpsController
 
 class OngoingPrivacyChip @JvmOverloads constructor(
     context: Context,
@@ -37,116 +29,81 @@
     defStyleRes: Int = 0
 ) : LinearLayout(context, attrs, defStyleAttrs, defStyleRes) {
 
-    companion object {
-        val OPS = intArrayOf(AppOpsManager.OP_CAMERA,
-                AppOpsManager.OP_RECORD_AUDIO,
-                AppOpsManager.OP_COARSE_LOCATION,
-                AppOpsManager.OP_FINE_LOCATION)
-    }
-
-    private lateinit var appName: TextView
+    private val iconMargin =
+            context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_icon_margin)
+    private val iconSize =
+            context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_icon_size)
+    val iconColor = context.resources.getColor(
+            R.color.status_bar_clock_color, context.theme)
+    private lateinit var text: TextView
     private lateinit var iconsContainer: LinearLayout
-    private var privacyList = emptyList<PrivacyItem>()
-    private val appOpsController = Dependency.get(AppOpsController::class.java)
-    private val userManager = context.getSystemService(UserManager::class.java)
-    private val currentUser = ActivityManager.getCurrentUser()
-    private val currentUserIds = userManager.getProfiles(currentUser).map { it.id }
-    private var listening = false
-
-    var builder = PrivacyDialogBuilder(context, privacyList)
-
-    private val callback = object : AppOpsController.Callback {
-        override fun onActiveStateChanged(
-            code: Int,
-            uid: Int,
-            packageName: String,
-            active: Boolean
-        ) {
-            val userId = UserHandle.getUserId(uid)
-            if (userId in currentUserIds) {
-                updatePrivacyList()
-            }
+    var builder = PrivacyDialogBuilder(context, emptyList<PrivacyItem>())
+    var privacyList = emptyList<PrivacyItem>()
+        set(value) {
+            field = value
+            builder = PrivacyDialogBuilder(context, value)
+            updateView()
         }
-    }
 
     override fun onFinishInflate() {
         super.onFinishInflate()
 
-        appName = findViewById(R.id.app_name)
+        text = findViewById(R.id.text_container)
         iconsContainer = findViewById(R.id.icons_container)
     }
 
-    fun setListening(listen: Boolean) {
-        if (listening == listen) return
-        listening = listen
-        if (listening) {
-            appOpsController.addCallback(OPS, callback)
-            updatePrivacyList()
-        } else {
-            appOpsController.removeCallback(OPS, callback)
-        }
-    }
-
-    private fun updatePrivacyList() {
-        privacyList = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) }
-                .mapNotNull { toPrivacyItem(it) }
-        builder = PrivacyDialogBuilder(context, privacyList)
-        updateView()
-    }
-
-    private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? {
-        val type: PrivacyType = when (appOpItem.code) {
-            AppOpsManager.OP_CAMERA -> PrivacyType.TYPE_CAMERA
-            AppOpsManager.OP_COARSE_LOCATION -> PrivacyType.TYPE_LOCATION
-            AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION
-            AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
-            else -> return null
-        }
-        val app = PrivacyApplication(appOpItem.packageName, context)
-        return PrivacyItem(type, app, appOpItem.timeStarted)
-    }
-
     // Should only be called if the builder icons or app changed
     private fun updateView() {
         fun setIcons(dialogBuilder: PrivacyDialogBuilder, iconsContainer: ViewGroup) {
             iconsContainer.removeAllViews()
             dialogBuilder.generateIcons().forEach {
                 it.mutate()
-                it.setTint(Color.WHITE)
-                iconsContainer.addView(ImageView(context).apply {
+                it.setTint(iconColor)
+                val image = ImageView(context).apply {
                     setImageDrawable(it)
-                    maxHeight = this@OngoingPrivacyChip.height
-                })
+                    scaleType = ImageView.ScaleType.CENTER_INSIDE
+                }
+                iconsContainer.addView(image, iconSize, iconSize)
+                val lp = image.layoutParams as MarginLayoutParams
+                lp.marginStart = iconMargin
+                image.layoutParams = lp
             }
         }
 
-        if (privacyList.isEmpty()) {
-            visibility = GONE
-            return
-        } else {
+        if (!privacyList.isEmpty()) {
             generateContentDescription()
-            visibility = VISIBLE
             setIcons(builder, iconsContainer)
-            appName.visibility = GONE
-            builder.app?.let {
-                appName.apply {
-                    setText(it.applicationName)
-                    setTextColor(Color.WHITE)
-                    visibility = VISIBLE
+            text.visibility = if (builder.types.size == 1) VISIBLE else GONE
+            if (builder.types.size == 1) {
+                if (builder.app != null) {
+                    text.setText(builder.app?.applicationName)
+                } else {
+                    text.text = context.getString(R.string.ongoing_privacy_chip_multiple_apps,
+                            builder.appsAndTypes.size)
                 }
             }
+        } else {
+            text.visibility = GONE
+            iconsContainer.removeAllViews()
         }
         requestLayout()
     }
 
     private fun generateContentDescription() {
-        val typesText = builder.generateTypesText()
-        if (builder.app != null) {
-            contentDescription = context.getString(R.string.ongoing_privacy_chip_content_single_app,
-                    builder.app?.applicationName, typesText)
-        } else {
+        val typesText = builder.joinTypes()
+        if (builder.types.size > 1) {
             contentDescription = context.getString(
                     R.string.ongoing_privacy_chip_content_multiple_apps, typesText)
+        } else {
+            if (builder.app != null) {
+                contentDescription =
+                        context.getString(R.string.ongoing_privacy_chip_content_single_app,
+                                builder.app?.applicationName, typesText)
+            } else {
+                contentDescription = context.getString(
+                        R.string.ongoing_privacy_chip_content_multiple_apps_single_op,
+                        builder.appsAndTypes.size, typesText)
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
index 1d0e16e..f6a95af 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
@@ -18,10 +18,10 @@
 import android.app.Dialog
 import android.content.Context
 import android.content.DialogInterface
-import android.graphics.drawable.Drawable
+import android.content.Intent
+import android.content.res.ColorStateList
 import android.view.LayoutInflater
 import android.view.View
-import android.view.ViewGroup
 import android.widget.ImageView
 import android.widget.LinearLayout
 import android.widget.TextView
@@ -34,29 +34,25 @@
     val dialogBuilder: PrivacyDialogBuilder
 ) {
 
-    val iconHeight = context.resources.getDimensionPixelSize(
+    val iconSize = context.resources.getDimensionPixelSize(
             R.dimen.ongoing_appops_dialog_icon_height)
-    val textMargin = context.resources.getDimensionPixelSize(
-            R.dimen.ongoing_appops_dialog_text_margin)
     val iconColor = context.resources.getColor(
             com.android.internal.R.color.text_color_primary, context.theme)
+    companion object {
+        private const val MAX_ITEMS = 10
+    }
 
     fun createDialog(): Dialog {
-        val builder = AlertDialog.Builder(context)
-                .setNeutralButton(R.string.ongoing_privacy_dialog_open_settings, null)
-        if (dialogBuilder.app != null) {
-            builder.setPositiveButton(R.string.ongoing_privacy_dialog_open_app,
+        val builder = AlertDialog.Builder(context).apply {
+            setNegativeButton(R.string.ongoing_privacy_dialog_cancel, null)
+            setPositiveButton(R.string.ongoing_privacy_dialog_open_settings,
                     object : DialogInterface.OnClickListener {
-                        val intent = context.packageManager
-                                .getLaunchIntentForPackage(dialogBuilder.app.packageName)
+                        val intent = Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE)
 
                         override fun onClick(dialog: DialogInterface?, which: Int) {
                             Dependency.get(ActivityStarter::class.java).startActivity(intent, false)
                         }
                     })
-            builder.setNegativeButton(R.string.ongoing_privacy_dialog_cancel, null)
-        } else {
-            builder.setPositiveButton(R.string.ongoing_privacy_dialog_okay, null)
         }
         builder.setView(getContentView())
         return builder.create()
@@ -66,44 +62,67 @@
         val layoutInflater = LayoutInflater.from(context)
         val contentView = layoutInflater.inflate(R.layout.ongoing_privacy_dialog_content, null)
 
-        val iconsContainer = contentView.findViewById(R.id.icons_container) as LinearLayout
-        val textContainer = contentView.findViewById(R.id.text_container) as LinearLayout
+        val title = contentView.findViewById(R.id.title) as TextView
+        val appsList = contentView.findViewById(R.id.items_container) as LinearLayout
 
-        addIcons(dialogBuilder, iconsContainer)
-        val lm = ViewGroup.MarginLayoutParams(
-                ViewGroup.MarginLayoutParams.WRAP_CONTENT,
-                ViewGroup.MarginLayoutParams.WRAP_CONTENT)
-        lm.topMargin = textMargin
-        val now = System.currentTimeMillis()
-        dialogBuilder.generateText(now).forEach {
-            val text = layoutInflater.inflate(R.layout.ongoing_privacy_text_item, null) as TextView
-            text.setText(it)
-            textContainer.addView(text, lm)
+        title.setText(dialogBuilder.getDialogTitle())
+
+        val numItems = dialogBuilder.appsAndTypes.size
+        for (i in 0..(numItems - 1)) {
+            if (i >= MAX_ITEMS) break
+            val item = dialogBuilder.appsAndTypes[i]
+            addAppItem(appsList, item.first, item.second, dialogBuilder.types.size > 1)
         }
+
+        if (numItems > MAX_ITEMS) {
+            val overflow = contentView.findViewById(R.id.overflow) as LinearLayout
+            overflow.visibility = View.VISIBLE
+            val overflowText = overflow.findViewById(R.id.app_name) as TextView
+            overflowText.text = context.resources.getQuantityString(
+                    R.plurals.ongoing_privacy_dialog_overflow_text,
+                    numItems - MAX_ITEMS,
+                    numItems - MAX_ITEMS
+            )
+            val overflowPlus = overflow.findViewById(R.id.app_icon) as ImageView
+            overflowPlus.apply {
+                imageTintList = ColorStateList.valueOf(iconColor)
+                setImageDrawable(context.getDrawable(R.drawable.plus))
+            }
+        }
+
         return contentView
     }
 
-    private fun addIcons(dialogBuilder: PrivacyDialogBuilder, iconsContainer: LinearLayout) {
+    private fun addAppItem(
+        itemList: LinearLayout,
+        app: PrivacyApplication,
+        types: List<PrivacyType>,
+        showIcons: Boolean = true
+    ) {
+        val layoutInflater = LayoutInflater.from(context)
+        val item = layoutInflater.inflate(R.layout.ongoing_privacy_dialog_item, itemList, false)
+        val appIcon = item.findViewById(R.id.app_icon) as ImageView
+        val appName = item.findViewById(R.id.app_name) as TextView
+        val icons = item.findViewById(R.id.icons) as LinearLayout
 
-        fun LinearLayout.addIcon(icon: Drawable) {
-            val image = ImageView(context).apply {
-                setImageDrawable(icon.apply {
-                    setBounds(0, 0, iconHeight, iconHeight)
-                    maxHeight = this@addIcon.height
-                })
-                adjustViewBounds = true
+        app.icon?.let {
+            appIcon.setImageDrawable(it)
+        }
+
+        appName.text = app.applicationName
+        if (showIcons) {
+            dialogBuilder.generateIconsForApp(types).forEach {
+                it.setBounds(0, 0, iconSize, iconSize)
+                val image = ImageView(context).apply {
+                    imageTintList = ColorStateList.valueOf(iconColor)
+                    setImageDrawable(it)
+                }
+                icons.addView(image, iconSize, LinearLayout.LayoutParams.WRAP_CONTENT)
             }
-            addView(image, LinearLayout.LayoutParams.WRAP_CONTENT,
-                    LinearLayout.LayoutParams.MATCH_PARENT)
+            icons.visibility = View.VISIBLE
+        } else {
+            icons.visibility = View.GONE
         }
-
-        dialogBuilder.generateIcons().forEach {
-            it.mutate()
-            it.setTint(iconColor)
-            iconsContainer.addIcon(it)
-        }
-        dialogBuilder.app.let {
-            it?.icon?.let { iconsContainer.addIcon(it) }
-        }
+        itemList.addView(item)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
index 2f86f78..519df19 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
@@ -15,60 +15,53 @@
 package com.android.systemui.privacy
 
 import android.content.Context
+import android.graphics.drawable.Drawable
 import com.android.systemui.R
-import java.lang.IllegalStateException
-import java.lang.Math.max
 
 class PrivacyDialogBuilder(val context: Context, itemsList: List<PrivacyItem>) {
-    companion object {
-        val MILLIS_IN_MINUTE: Long = 1000 * 60
-    }
 
-    private val itemsByType: Map<PrivacyType, List<PrivacyItem>>
+    val appsAndTypes: List<Pair<PrivacyApplication, List<PrivacyType>>>
+    val types: List<PrivacyType>
     val app: PrivacyApplication?
+    private val separator = context.getString(R.string.ongoing_privacy_dialog_separator)
+    private val lastSeparator = context.getString(R.string.ongoing_privacy_dialog_last_separator)
 
     init {
-        itemsByType = itemsList.groupBy { it.privacyType }
-        val apps = itemsList.map { it.application }.distinct()
-        val singleApp = apps.size == 1
-        app = if (singleApp) apps.get(0) else null
+        appsAndTypes = itemsList.groupBy({ it.application }, { it.privacyType })
+                .toList()
+                .sortedWith(compareBy({ -it.second.size }, { it.first }))
+        types = itemsList.map { it.privacyType }.distinct().sorted()
+        val singleApp = appsAndTypes.size == 1
+        app = if (singleApp) appsAndTypes[0].first else null
     }
 
-    private fun buildTextForItem(type: PrivacyType, now: Long): String {
-        val items = itemsByType.getOrDefault(type, emptyList<PrivacyItem>())
-        return when (items.size) {
-            0 -> throw IllegalStateException("List cannot be empty")
-            1 -> {
-                val item = items.get(0)
-                val minutesUsed = max(((now - item.timeStarted) / MILLIS_IN_MINUTE).toInt(), 1)
-                context.getString(R.string.ongoing_privacy_dialog_app_item,
-                        item.application.applicationName, type.getName(context), minutesUsed)
-            }
-            else -> {
-                val apps = items.map { it.application.applicationName }.joinToString()
-                context.getString(R.string.ongoing_privacy_dialog_apps_item,
-                        apps, type.getName(context))
-            }
+    fun generateIconsForApp(types: List<PrivacyType>): List<Drawable> {
+        return types.sorted().map { it.getIcon(context) }
+    }
+
+    fun generateIcons() = types.map { it.getIcon(context) }
+
+    private fun <T> List<T>.joinWithAnd(): StringBuilder {
+        return subList(0, size - 1).joinTo(StringBuilder(), separator = separator).apply {
+            append(lastSeparator)
+            append(this@joinWithAnd.last())
         }
     }
 
-    private fun buildTextForApp(types: Set<PrivacyType>): List<String> {
-        app?.let {
-            val typesText = types.map { it.getName(context) }.sorted().joinToString()
-            return listOf(context.getString(R.string.ongoing_privacy_dialog_single_app,
-                    it.applicationName, typesText))
-        } ?: throw IllegalStateException("There has to be a single app")
+    fun joinTypes(): String {
+        return when (types.size) {
+            0 -> ""
+            1 -> types[0].getName(context)
+            else -> types.map { it.getName(context) }.joinWithAnd().toString()
+        }
     }
 
-    fun generateText(now: Long): List<String> {
-        if (app == null || itemsByType.keys.size == 1) {
-            return itemsByType.keys.map { buildTextForItem(it, now) }
+    fun getDialogTitle(): String {
+        if (app != null) {
+            return context.getString(R.string.ongoing_privacy_dialog_single_app_title, joinTypes())
         } else {
-            return buildTextForApp(itemsByType.keys)
+            return context.getString(R.string.ongoing_privacy_dialog_multiple_apps_title,
+                    joinTypes())
         }
     }
-
-    fun generateTypesText() = itemsByType.keys.map { it.getName(context) }.sorted().joinToString()
-
-    fun generateIcons() = itemsByType.keys.map { it.getIcon(context) }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
index f409902..85e99f0 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
@@ -23,22 +23,27 @@
 typealias Privacy = PrivacyType
 
 enum class PrivacyType(val nameId: Int, val iconId: Int) {
-    TYPE_CAMERA(R.string.privacy_type_camera, com.android.internal.R.drawable.ic_camera),
+    TYPE_CAMERA(R.string.privacy_type_camera, R.drawable.stat_sys_camera),
     TYPE_LOCATION(R.string.privacy_type_location, R.drawable.stat_sys_location),
-    TYPE_MICROPHONE(R.string.privacy_type_microphone, R.drawable.ic_mic_26dp);
+    TYPE_MICROPHONE(R.string.privacy_type_microphone, R.drawable.stat_sys_mic_none);
 
     fun getName(context: Context) = context.resources.getString(nameId)
 
-    fun getIcon(context: Context) = context.resources.getDrawable(iconId, null)
+    fun getIcon(context: Context) = context.resources.getDrawable(iconId, context.theme)
 }
 
 data class PrivacyItem(
     val privacyType: PrivacyType,
-    val application: PrivacyApplication,
-    val timeStarted: Long
+    val application: PrivacyApplication
 )
 
-data class PrivacyApplication(val packageName: String, val context: Context) {
+data class PrivacyApplication(val packageName: String, val context: Context)
+    : Comparable<PrivacyApplication> {
+
+    override fun compareTo(other: PrivacyApplication): Int {
+        return applicationName.compareTo(other.applicationName)
+    }
+
     var icon: Drawable? = null
     var applicationName: String
 
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
new file mode 100644
index 0000000..3fa3e8e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2018 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.privacy
+
+import android.app.ActivityManager
+import android.app.AppOpsManager
+import android.content.Context
+import android.os.Handler
+import android.os.UserHandle
+import android.os.UserManager
+import com.android.systemui.Dependency
+import com.android.systemui.appops.AppOpItem
+import com.android.systemui.appops.AppOpsController
+
+class PrivacyItemController(val context: Context, val callback: Callback) {
+
+    companion object {
+        val OPS = intArrayOf(AppOpsManager.OP_CAMERA,
+                AppOpsManager.OP_RECORD_AUDIO,
+                AppOpsManager.OP_COARSE_LOCATION,
+                AppOpsManager.OP_FINE_LOCATION)
+    }
+
+    private var privacyList = emptyList<PrivacyItem>()
+    private val appOpsController = Dependency.get(AppOpsController::class.java)
+    private val userManager = context.getSystemService(UserManager::class.java)
+    private val currentUser = ActivityManager.getCurrentUser()
+    private val currentUserIds = userManager.getProfiles(currentUser).map { it.id }
+    private val bgHandler = Handler(Dependency.get(Dependency.BG_LOOPER))
+    private val uiHandler = Dependency.get(Dependency.MAIN_HANDLER)
+    private val notifyChanges = Runnable {
+        callback.privacyChanged(privacyList)
+    }
+    private val updateListAndNotifyChanges = Runnable {
+        updatePrivacyList()
+        uiHandler.post(notifyChanges)
+    }
+
+    private var listening = false
+
+    private val cb = object : AppOpsController.Callback {
+        override fun onActiveStateChanged(
+            code: Int,
+            uid: Int,
+            packageName: String,
+            active: Boolean
+        ) {
+            val userId = UserHandle.getUserId(uid)
+            if (userId in currentUserIds) {
+                update()
+            }
+        }
+    }
+
+    private fun update() {
+        bgHandler.post(updateListAndNotifyChanges)
+    }
+
+    fun setListening(listen: Boolean) {
+        if (listening == listen) return
+        listening = listen
+        if (listening) {
+            appOpsController.addCallback(OPS, cb)
+            update()
+        } else {
+            appOpsController.removeCallback(OPS, cb)
+        }
+    }
+
+    private fun updatePrivacyList() {
+        privacyList = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) }
+                .mapNotNull { toPrivacyItem(it) }
+    }
+
+    private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? {
+        val type: PrivacyType = when (appOpItem.code) {
+            AppOpsManager.OP_CAMERA -> PrivacyType.TYPE_CAMERA
+            AppOpsManager.OP_COARSE_LOCATION -> PrivacyType.TYPE_LOCATION
+            AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION
+            AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
+            else -> return null
+        }
+        val app = PrivacyApplication(appOpItem.packageName, context)
+        return PrivacyItem(type, app)
+    }
+
+    // Used by containing class to get notified of changes
+    interface Callback {
+        fun privacyChanged(privacyItems: List<PrivacyItem>)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java
index 2c7ec70..6a6f572 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.graphics.drawable.Drawable;
+
 import com.android.systemui.qs.tileimpl.SlashImageView;
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java b/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
index 767fd9e..1195184 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
@@ -23,6 +23,7 @@
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.ListAdapter;
+
 import com.android.systemui.R;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
index 376e6ae..c1aa706 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
@@ -20,7 +20,6 @@
 import android.widget.ImageView;
 
 import com.android.settingslib.graph.SignalDrawable;
-import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSTile.Icon;
 import com.android.systemui.plugins.qs.QSTile.State;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
index 6aad479..afce69e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.content.res.ColorStateList;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.RectF;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
index aa2f8d1..d5c5ba4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
@@ -6,10 +6,10 @@
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
+
 import com.android.systemui.R;
 
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 1451e71..dbd3042 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -23,14 +23,11 @@
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 import android.widget.FrameLayout;
 
 import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.statusbar.CommandQueue;
 
 /**
  * Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index ddd9910..dab0efe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -32,6 +32,7 @@
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.TextView;
+
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSTile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index 84eb3da5..b597a72 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -15,9 +15,10 @@
  */
 package com.android.systemui.qs;
 
-import androidx.annotation.Nullable;
 import android.view.View;
 
+import androidx.annotation.Nullable;
+
 /**
  * The bottom footer of the quick settings panel.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index f147fb3..8903a38 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -28,8 +28,6 @@
 import android.graphics.drawable.RippleDrawable;
 import android.os.Bundle;
 import android.os.UserManager;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
@@ -40,6 +38,9 @@
 import android.widget.LinearLayout;
 import android.widget.Toast;
 
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.keyguard.CarrierText;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index f9971d8..953eb70 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -22,8 +22,6 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Bundle;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
@@ -34,6 +32,9 @@
 import android.view.ViewTreeObserver;
 import android.widget.FrameLayout.LayoutParams;
 
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -42,9 +43,9 @@
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.qs.customize.QSCustomizer;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
-import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
 public class QSFragment extends Fragment implements QS, CommandQueue.Callbacks {
     private static final String TAG = "QS";
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index cf63e47..f1f0f69 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -17,6 +17,7 @@
 package com.android.systemui.qs;
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+
 import static com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState;
 
 import android.annotation.Nullable;
@@ -30,7 +31,6 @@
 import android.os.Message;
 import android.service.quicksettings.Tile;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.LinearLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java b/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
index 7ebab0b..001cbba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
@@ -17,7 +17,6 @@
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.graphics.Canvas;
-import androidx.core.widget.NestedScrollView;
 import android.util.Property;
 import android.view.MotionEvent;
 import android.view.View;
@@ -25,6 +24,8 @@
 import android.view.ViewParent;
 import android.widget.LinearLayout;
 
+import androidx.core.widget.NestedScrollView;
+
 import com.android.systemui.R;
 import com.android.systemui.qs.touch.OverScroll;
 import com.android.systemui.qs.touch.SwipeDetector;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 8f3a7b3..e2e943a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -33,8 +33,8 @@
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.View.OnClickListener;
+import android.view.ViewGroup;
 import android.view.Window;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -46,8 +46,6 @@
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.SecurityController;
 
-import static android.provider.Settings.ACTION_VPN_SETTINGS;
-
 public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener {
     protected static final String TAG = "QSSecurityFooter";
     protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index cefeeb5..d1c2df5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -31,14 +31,14 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.plugins.qs.QSFactory;
-import com.android.systemui.plugins.qs.QSTileView;
 import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTileView;
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.qs.external.TileLifecycleManager;
 import com.android.systemui.qs.external.TileServices;
 import com.android.systemui.qs.tileimpl.QSFactoryImpl;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.phone.AutoTileManager;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 3ee6195..427f638 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -15,6 +15,7 @@
 package com.android.systemui.qs;
 
 import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
+import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -28,23 +29,29 @@
 import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.media.AudioManager;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.AlarmClock;
+import android.provider.Settings;
 import android.service.notification.ZenModeConfig;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Pair;
+import android.view.DisplayCutout;
 import android.view.View;
 import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
+import android.widget.Space;
 import android.widget.TextView;
 
 import androidx.annotation.VisibleForTesting;
@@ -57,12 +64,15 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.privacy.OngoingPrivacyChip;
 import com.android.systemui.privacy.OngoingPrivacyDialog;
+import com.android.systemui.privacy.PrivacyItem;
+import com.android.systemui.privacy.PrivacyItemController;
 import com.android.systemui.qs.QSDetail.Callback;
 import com.android.systemui.statusbar.phone.PhoneStatusBarView;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
 import com.android.systemui.statusbar.phone.StatusIconContainer;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.Clock;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
@@ -70,6 +80,7 @@
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.ZenModeController;
 
+import java.util.List;
 import java.util.Locale;
 import java.util.Objects;
 
@@ -125,9 +136,14 @@
     private Clock mClockView;
     private DateView mDateView;
     private OngoingPrivacyChip mPrivacyChip;
+    private Space mSpace;
+    private BatteryMeterView mBatteryRemainingIcon;
+    private TextView mBatteryRemainingText;
+    private boolean mShowBatteryPercentAndEstimate;
 
     private NextAlarmController mAlarmController;
     private ZenModeController mZenController;
+    private PrivacyItemController mPrivacyItemController;
     /** Counts how many times the long press tooltip has been shown to the user. */
     private int mShownCount;
 
@@ -138,16 +154,29 @@
             updateStatusText();
         }
     };
+    private boolean mHasTopCutout = false;
+
+    private final PercentSettingObserver mPercentSettingObserver =
+            new PercentSettingObserver(new Handler(mContext.getMainLooper()));
 
     /**
      * Runnable for automatically fading out the long press tooltip (as if it were animating away).
      */
     private final Runnable mAutoFadeOutTooltipRunnable = () -> hideLongPressTooltip(false);
 
+    private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
+        @Override
+        public void privacyChanged(List<PrivacyItem> privacyItems) {
+            mPrivacyChip.setPrivacyList(privacyItems);
+            setChipVisibility(!privacyItems.isEmpty());
+        }
+    };
+
     public QuickStatusBarHeader(Context context, AttributeSet attrs) {
         super(context, attrs);
         mAlarmController = Dependency.get(NextAlarmController.class);
         mZenController = Dependency.get(ZenModeController.class);
+        mPrivacyItemController = new PrivacyItemController(context, mPICCallback);
         mShownCount = getStoredShownCount();
     }
 
@@ -186,14 +215,28 @@
         // Set the correct tint for the status icons so they contrast
         mIconManager.setTint(fillColor);
 
+        mShowBatteryPercentAndEstimate = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_battery_percentage_setting_available);
+
         mBatteryMeterView = findViewById(R.id.battery);
-        mBatteryMeterView.setForceShowPercent(true);
+        mBatteryMeterView.setPercentShowMode(mShowBatteryPercentAndEstimate
+                ? BatteryMeterView.MODE_ON : BatteryMeterView.MODE_OFF);
         mBatteryMeterView.setOnClickListener(this);
         mClockView = findViewById(R.id.clock);
         mClockView.setOnClickListener(this);
         mDateView = findViewById(R.id.date);
         mPrivacyChip = findViewById(R.id.privacy_chip);
         mPrivacyChip.setOnClickListener(this);
+        mSpace = findViewById(R.id.space);
+
+        // Tint for the battery icons are handled in setupHost()
+        mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon);
+        mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_OFF);
+
+        mBatteryRemainingText = findViewById(R.id.batteryRemainingText);
+        mBatteryRemainingText.setTextColor(fillColor);
+
+        updateShowPercent();
     }
 
     private void updateStatusText() {
@@ -208,6 +251,16 @@
         }
     }
 
+    private void setChipVisibility(boolean chipVisible) {
+        mBatteryMeterView.setVisibility(View.VISIBLE);
+        if (chipVisible) {
+            mPrivacyChip.setVisibility(View.VISIBLE);
+            if (mHasTopCutout) mBatteryMeterView.setVisibility(View.GONE);
+        } else {
+            mPrivacyChip.setVisibility(View.GONE);
+        }
+    }
+
     private boolean updateRingerStatus() {
         boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
         CharSequence originalRingerText = mRingerModeTextView.getText();
@@ -272,15 +325,10 @@
                 newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
         mBatteryMeterView.useWallpaperTextColor(shouldUseWallpaperTextColor);
         mClockView.useWallpaperTextColor(shouldUseWallpaperTextColor);
-
-        MarginLayoutParams lm = (MarginLayoutParams) mPrivacyChip.getLayoutParams();
-        int sideMargins = lm.leftMargin;
-        int topBottomMargins = (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
-                ? 0 : sideMargins;
-        lm.setMargins(sideMargins, topBottomMargins, sideMargins, topBottomMargins);
-        mPrivacyChip.setLayoutParams(lm);
     }
 
+
+
     @Override
     public void onRtlPropertiesChanged(int layoutDirection) {
         super.onRtlPropertiesChanged(layoutDirection);
@@ -325,6 +373,15 @@
 
         setLayoutParams(lp);
 
+        if (mPrivacyChip != null) {
+            MarginLayoutParams lm = (MarginLayoutParams) mPrivacyChip.getLayoutParams();
+            int sideMargins = lm.leftMargin;
+            int topBottomMargins = resources.getDimensionPixelSize(
+                    R.dimen.ongoing_appops_top_chip_margin);
+            lm.setMargins(sideMargins, topBottomMargins, sideMargins, topBottomMargins);
+            mPrivacyChip.setLayoutParams(lm);
+        }
+
         updateStatusIconAlphaAnimator();
         updateHeaderTextContainerAlphaAnimator();
     }
@@ -342,6 +399,14 @@
                 .build();
     }
 
+    private void updateBatteryRemainingText() {
+        if (!mShowBatteryPercentAndEstimate) {
+            return;
+        }
+        mBatteryRemainingText.setText(
+                Dependency.get(BatteryController.class).getEstimatedTimeRemainingString());
+    }
+
     public void setExpanded(boolean expanded) {
         if (mExpanded == expanded) return;
         mExpanded = expanded;
@@ -407,12 +472,16 @@
         super.onAttachedToWindow();
         Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager);
         requestApplyInsets();
+        mContext.getContentResolver().registerContentObserver(
+                Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mPercentSettingObserver,
+                ActivityManager.getCurrentUser());
     }
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        DisplayCutout cutout = insets.getDisplayCutout();
         Pair<Integer, Integer> padding = PhoneStatusBarView.cornerCutoutMargins(
-                insets.getDisplayCutout(), getDisplay());
+                cutout, getDisplay());
         if (padding == null) {
             mSystemIconsView.setPaddingRelative(
                     getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0,
@@ -421,6 +490,22 @@
             mSystemIconsView.setPadding(padding.first, 0, padding.second, 0);
 
         }
+        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSpace.getLayoutParams();
+        if (cutout != null) {
+            Rect topCutout = cutout.getBoundingRectTop();
+            if (topCutout.isEmpty()) {
+                mHasTopCutout = false;
+                lp.width = 0;
+                mSpace.setVisibility(View.GONE);
+            } else {
+                mHasTopCutout = true;
+                lp.width = topCutout.width();
+                mSpace.setVisibility(View.VISIBLE);
+            }
+        }
+        mSpace.setLayoutParams(lp);
+        // Decide whether to show BatteryMeterView
+        setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
         return super.onApplyWindowInsets(insets);
     }
 
@@ -429,6 +514,7 @@
     public void onDetachedFromWindow() {
         setListening(false);
         Dependency.get(StatusBarIconController.class).removeIconGroup(mIconManager);
+        mContext.getContentResolver().unregisterContentObserver(mPercentSettingObserver);
         super.onDetachedFromWindow();
     }
 
@@ -437,7 +523,7 @@
             return;
         }
         mHeaderQsPanel.setListening(listening);
-        mPrivacyChip.setListening(listening);
+        mPrivacyItemController.setListening(listening);
         mListening = listening;
 
         if (listening) {
@@ -445,6 +531,7 @@
             mAlarmController.addCallback(this);
             mContext.registerReceiver(mRingerReceiver,
                     new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
+            updateBatteryRemainingText();
         } else {
             mZenController.removeCallback(this);
             mAlarmController.removeCallback(this);
@@ -614,6 +701,14 @@
         // Use SystemUI context to get battery meter colors, and let it use the default tint (white)
         mBatteryMeterView.setColorsFromContext(mHost.getContext());
         mBatteryMeterView.onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
+
+        Rect tintArea = new Rect(0, 0, 0, 0);
+        int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
+                android.R.attr.colorForeground);
+        float intensity = getColorIntensity(colorForeground);
+        int fillColor = fillColorForIntensity(intensity, getContext());
+        mBatteryRemainingIcon.setColorsFromContext(mHost.getContext());
+        mBatteryRemainingIcon.onDarkChanged(tintArea, intensity, fillColor);
     }
 
     public void setCallback(Callback qsPanelCallback) {
@@ -638,7 +733,8 @@
     public void setMargins(int sideMargins) {
         for (int i = 0; i < getChildCount(); i++) {
             View v = getChildAt(i);
-            if (v == mSystemIconsView || v == mQuickQsStatusIcons || v == mHeaderQsPanel) {
+            if (v == mSystemIconsView || v == mQuickQsStatusIcons || v == mHeaderQsPanel
+                    || v == mPrivacyChip) {
                 continue;
             }
             RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) v.getLayoutParams();
@@ -646,4 +742,39 @@
             lp.rightMargin = sideMargins;
         }
     }
+
+    private void updateShowPercent() {
+        final boolean systemSetting = 0 != Settings.System
+                .getIntForUser(getContext().getContentResolver(),
+                        SHOW_BATTERY_PERCENT, 0, ActivityManager.getCurrentUser());
+
+        mShowBatteryPercentAndEstimate = systemSetting;
+
+        updateBatteryViews();
+    }
+
+    private void updateBatteryViews() {
+        if (mShowBatteryPercentAndEstimate) {
+            mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON);
+            mBatteryRemainingIcon.setVisibility(View.VISIBLE);
+            mBatteryRemainingText.setVisibility(View.VISIBLE);
+            updateBatteryRemainingText();
+        } else {
+            mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_OFF);
+            mBatteryRemainingIcon.setVisibility(View.GONE);
+            mBatteryRemainingText.setVisibility(View.GONE);
+        }
+    }
+
+    private final class PercentSettingObserver extends ContentObserver {
+        PercentSettingObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            super.onChange(selfChange, uri);
+            updateShowPercent();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
index f6b08b0..0389030 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -16,14 +16,14 @@
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
-import androidx.annotation.Nullable;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.view.View;
 import android.widget.ImageView;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import androidx.annotation.Nullable;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.ActivityStarter;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
index 2d9e4d7..3e82c54 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -22,14 +22,15 @@
 import android.app.Fragment;
 import android.content.Context;
 import android.os.Bundle;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.recyclerview.widget.GridLayoutManager;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.recyclerview.widget.GridLayoutManager;
+
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.qs.QSFooter;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
index 9b225bb..083a747 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
@@ -16,11 +16,12 @@
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.Rect;
-import androidx.annotation.IdRes;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.LinearLayout;
 
+import androidx.annotation.IdRes;
+
 import com.android.settingslib.Utils;
 import com.android.systemui.BatteryMeterView;
 import com.android.systemui.R;
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 dc17dd8..64ad95c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -20,13 +20,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.graphics.Point;
 import android.os.Bundle;
-import androidx.recyclerview.widget.DefaultItemAnimator;
-import androidx.recyclerview.widget.GridLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
@@ -37,6 +32,10 @@
 import android.widget.Toolbar;
 import android.widget.Toolbar.OnMenuItemClickListener;
 
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settingslib.Utils;
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 15d2e66..a29e93a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -23,13 +23,6 @@
 import android.graphics.Canvas;
 import android.graphics.drawable.ColorDrawable;
 import android.os.Handler;
-import androidx.core.view.ViewCompat;
-import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
-import androidx.recyclerview.widget.RecyclerView.State;
-import androidx.recyclerview.widget.RecyclerView.ViewHolder;
-import androidx.recyclerview.widget.ItemTouchHelper;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -39,6 +32,14 @@
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
+import androidx.core.view.ViewCompat;
+import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
+import androidx.recyclerview.widget.RecyclerView.State;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index bb65bed..8906665 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -15,6 +15,9 @@
  */
 package com.android.systemui.qs.external;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -41,13 +44,11 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
 import com.android.systemui.qs.QSTileHost;
-import java.util.Objects;
+import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+import java.util.Objects;
 
 public class CustomTile extends QSTileImpl<State> implements TileChangeListener {
     public static final String PREFIX = "custom(";
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
index 451e1f6..2345667 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
@@ -16,9 +16,7 @@
 package com.android.systemui.qs.external;
 
 import android.os.IBinder;
-import android.service.quicksettings.IQSService;
 import android.service.quicksettings.IQSTileService;
-import android.service.quicksettings.Tile;
 import android.util.Log;
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java
index 75dd0d9..1caab5a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java
@@ -18,7 +18,9 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.service.quicksettings.Tile;
+
 import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.R;
 
 public class TileColorPicker {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 4e0f38f..305fbf2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -15,15 +15,14 @@
  */
 package com.android.systemui.qs.external;
 
-import android.app.AppGlobals;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
-import android.content.ServiceConnection;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Handler;
@@ -34,10 +33,10 @@
 import android.service.quicksettings.IQSTileService;
 import android.service.quicksettings.Tile;
 import android.service.quicksettings.TileService;
-import androidx.annotation.VisibleForTesting;
 import android.util.ArraySet;
 import android.util.Log;
-import com.android.systemui.qs.external.PackageManagerAdapter;
+
+import androidx.annotation.VisibleForTesting;
 
 import java.util.Objects;
 import java.util.Set;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 9f9fe39..416c2da 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -30,9 +30,10 @@
 import android.service.quicksettings.IQSTileService;
 import android.service.quicksettings.Tile;
 import android.service.quicksettings.TileService;
-import androidx.annotation.VisibleForTesting;
 import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
 
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index ac7ef5d..b2f6043 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -20,8 +20,11 @@
 import android.view.ContextThemeWrapper;
 
 import com.android.systemui.R;
-import com.android.systemui.plugins.qs.*;
+import com.android.systemui.plugins.qs.QSFactory;
+import com.android.systemui.plugins.qs.QSIconView;
+import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.qs.tiles.AirplaneModeTile;
 import com.android.systemui.qs.tiles.BatterySaverTile;
@@ -41,7 +44,6 @@
 import com.android.systemui.qs.tiles.UserTile;
 import com.android.systemui.qs.tiles.WifiTile;
 import com.android.systemui.qs.tiles.WorkModeTile;
-import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.util.leak.GarbageMonitor;
 
 public class QSFactoryImpl implements QSFactory {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
index 9dd5d8f..e245312 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
@@ -34,8 +34,8 @@
 import com.android.systemui.plugins.qs.QSIconView;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.State;
-
 import com.android.systemui.qs.AlphaControlledSignalTileView.AlphaControlledSlashImageView;
+
 import java.util.Objects;
 
 public class QSIconViewImpl extends QSIconView {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java
index a3e9afd..72c68ce 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java
@@ -17,9 +17,10 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
-import androidx.annotation.NonNull;
 import android.widget.ImageView;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.plugins.qs.QSTile.SlashState;
 import com.android.systemui.qs.SlashDrawable;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 7f3537c..da2828e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -20,6 +20,7 @@
 import android.graphics.drawable.Drawable;
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
+
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.graph.BatteryMeterDrawableBase;
 import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index cd00311..c62a592 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.qs.tiles;
 
-import static com.android.settingslib.graph.BluetoothDeviceLayerDrawable.createLayerDrawable;
-
 import android.annotation.Nullable;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index b93f1c2..c13a07f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -22,14 +22,13 @@
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
 import com.android.systemui.R.drawable;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.SecureSetting;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
 
 /** Quick settings tile: Invert colors **/
 public class ColorInversionTile extends QSTileImpl<BooleanState> {
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 ace361b..fd8b9c9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -18,6 +18,7 @@
 import android.content.Intent;
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
+
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.Prefs;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index 7bcc6d7..5578558 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -16,11 +16,10 @@
 
 package com.android.systemui.qs.tiles;
 
-import android.annotation.ColorInt;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.content.res.ColorStateList;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.LinearLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 3c565ef..a639a95 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -29,13 +29,11 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.qs.QSHost;
-import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 
 import java.util.Arrays;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index d7f2a26..b5f2d00 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -27,8 +27,8 @@
 import com.android.systemui.R;
 import com.android.systemui.R.drawable;
 import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.LocationController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index 9edd65e..a365e4c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -22,17 +22,15 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
 import android.nfc.NfcAdapter;
 import android.provider.Settings;
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 
 /** Quick settings tile: Enable/Disable NFC **/
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index c41f087..90890c0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -21,19 +21,21 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.Intent;
+import android.hardware.display.ColorDisplayManager;
 import android.metrics.LogMaker;
 import android.provider.Settings;
 import android.service.quicksettings.Tile;
-import androidx.annotation.StringRes;
 import android.text.TextUtils;
 import android.util.Log;
 import android.widget.Switch;
 
+import androidx.annotation.StringRes;
+
 import com.android.internal.app.ColorDisplayController;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 
 import java.text.DateFormat;
@@ -53,7 +55,6 @@
     private static final String PATTERN_HOUR_MINUTE = "h:mm a";
     private static final String PATTERN_HOUR_NINUTE_24 = "HH:mm";
 
-
     private ColorDisplayController mController;
     private boolean mIsListening;
 
@@ -64,7 +65,7 @@
 
     @Override
     public boolean isAvailable() {
-        return ColorDisplayController.isAvailable(mContext);
+        return ColorDisplayManager.isNightDisplayAvailable(mContext);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 28b047b..6345816 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -19,17 +19,15 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
-
 import android.provider.Settings;
 import android.service.quicksettings.Tile;
 import android.widget.Switch;
 
-import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.RotationLockController;
 import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
index ad7d1b6..64fe54a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -30,7 +30,6 @@
 import android.widget.TextView;
 
 import com.android.internal.util.ArrayUtils;
-import com.android.settingslib.drawable.UserIconDrawable;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.UserAvatarView;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index bde1c98..e5c51a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -24,9 +24,9 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.qs.DetailAdapter;
-import com.android.systemui.qs.QSHost;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java b/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java
index 911bea6..e7161e1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java
@@ -19,12 +19,13 @@
 
 import android.content.Context;
 import android.graphics.PointF;
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
 /**
  * One dimensional scroll/drag/swipe gesture detector.
  *
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
index 661b958..958695d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
@@ -31,6 +31,7 @@
 import android.util.Log;
 import android.view.Display;
 import android.widget.Toast;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 19f7675..1b89324 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -17,9 +17,9 @@
 package com.android.systemui.recents;
 
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+import static android.view.MotionEvent.ACTION_CANCEL;
 import static android.view.MotionEvent.ACTION_DOWN;
 import static android.view.MotionEvent.ACTION_UP;
-import static android.view.MotionEvent.ACTION_CANCEL;
 
 import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
 import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
@@ -42,6 +42,7 @@
 import android.provider.Settings;
 import android.util.Log;
 import android.view.MotionEvent;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.Prefs;
@@ -55,6 +56,7 @@
 import com.android.systemui.statusbar.policy.CallbackController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index de22d21..0702d74 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -20,9 +20,11 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.provider.Settings;
+
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.statusbar.CommandQueue;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
index 8a04c11..3efed3f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
@@ -18,7 +18,9 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+
 import com.android.systemui.SysUiServiceProvider;
+
 import java.io.PrintWriter;
 
 interface RecentsImplementation {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index af0ebdc..34f3c60 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -19,16 +19,17 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 
-import static com.android.systemui.Prefs.Key.HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE;
 import static com.android.systemui.Prefs.Key.DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT;
+import static com.android.systemui.Prefs.Key.HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE;
 import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING;
 import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING;
 import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_COUNT;
 import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_FROM_HOME_COUNT;
-import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
 import static com.android.systemui.shared.system.LauncherEventUtil.DISMISS;
-import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
+import static com.android.systemui.shared.system.LauncherEventUtil
+        .RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
 import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP;
+import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
 
 import android.annotation.StringRes;
 import android.annotation.TargetApi;
@@ -45,9 +46,9 @@
 import android.graphics.PixelFormat;
 import android.graphics.drawable.ShapeDrawable;
 import android.os.Build;
+import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.os.UserManager;
-import android.os.RemoteException;
 import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -64,6 +65,7 @@
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
+
 import java.io.PrintWriter;
 import java.util.Collections;
 import java.util.HashSet;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index f92c50a..216b940 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.recents;
 
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
+
 import android.animation.ArgbEvaluator;
 import android.animation.ValueAnimator;
 import android.app.ActivityManager;
@@ -50,9 +53,6 @@
 
 import java.util.ArrayList;
 
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
-
 public class ScreenPinningRequest implements View.OnClickListener {
 
     private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java b/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java
index af8c2d0..ef4e195 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java
@@ -19,6 +19,7 @@
 import android.graphics.Outline;
 import android.graphics.Path;
 import android.graphics.drawable.shapes.PathShape;
+
 import androidx.annotation.NonNull;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 5eaee54..97534ed 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -18,6 +18,7 @@
 
 import static android.content.Context.NOTIFICATION_SERVICE;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+
 import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ACTION_INTENT;
 import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_CANCEL_NOTIFICATION;
 import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_DISALLOW_ENTER_PIP;
@@ -35,6 +36,8 @@
 import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
+import android.content.ClipData;
+import android.content.ClipDescription;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -66,7 +69,6 @@
 import android.view.Display;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
-import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.View;
 import android.view.ViewGroup;
@@ -74,6 +76,7 @@
 import android.view.animation.Interpolator;
 import android.widget.ImageView;
 import android.widget.Toast;
+
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
@@ -81,6 +84,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.util.NotificationChannels;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.OutputStream;
@@ -290,6 +294,12 @@
             Intent sharingIntent = new Intent(Intent.ACTION_SEND);
             sharingIntent.setType("image/png");
             sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
+            // Include URI in ClipData also, so that grantPermission picks it up.
+            // We don't use setData here because some apps interpret this as "to:".
+            ClipData clipdata = new ClipData(new ClipDescription("content",
+                    new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
+                    new ClipData.Item(uri));
+            sharingIntent.setClipData(clipdata);
             sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
             sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 
@@ -298,7 +308,8 @@
                     PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
             Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null,
                     chooserAction.getIntentSender())
-                    .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+                    .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
+                    .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 
             // Create a share action for the notification
             PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, 0,
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 3ed5f70..79228b9 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -43,7 +43,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedLockUtilsInternal;
 import com.android.systemui.Dependency;
 
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index 2ae53b5..0374a01 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -18,7 +18,6 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 64fa8f8..07675e2 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -26,6 +26,7 @@
 import android.view.KeyEvent;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.systemui.SystemUI;
 import com.android.systemui.recents.Recents;
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
index 8ec862e..156964a 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
@@ -19,6 +19,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
+
 import com.android.internal.policy.IShortcutService;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index ea194a7..cd2074f 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -26,9 +26,11 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManagerGlobal;
+
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.recents.Recents;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index fa01af6..7a7d1f6 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -55,6 +55,7 @@
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
 import android.widget.FrameLayout;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.DividerSnapAlgorithm;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
index b7a5d31..2486d653 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
@@ -16,12 +16,6 @@
 
 package com.android.systemui.stackdivider;
 
-import android.content.Context;
-import android.graphics.PixelFormat;
-import android.os.Binder;
-import android.view.View;
-import android.view.WindowManager;
-
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -32,6 +26,12 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.os.Binder;
+import android.view.View;
+import android.view.WindowManager;
+
 /**
  * Manages the window parameters of the docked stack divider.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
index f66db48..c6ac309 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
@@ -16,7 +16,8 @@
 
 package com.android.systemui.stackdivider;
 
-import static com.android.systemui.stackdivider.ForcedResizableInfoActivity.EXTRA_FORCED_RESIZEABLE_REASON;
+import static com.android.systemui.stackdivider.ForcedResizableInfoActivity
+        .EXTRA_FORCED_RESIZEABLE_REASON;
 
 import android.app.ActivityOptions;
 import android.content.Context;
@@ -25,6 +26,7 @@
 import android.os.UserHandle;
 import android.util.ArraySet;
 import android.widget.Toast;
+
 import com.android.systemui.R;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 600964e..228aab5 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -18,7 +18,6 @@
 
 import static android.view.WindowManager.DOCKED_INVALID;
 
-import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.graphics.Rect;
 import android.os.RemoteException;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index daaefb9..0c8f487 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -27,9 +27,9 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.util.Pair;
 
 import androidx.annotation.VisibleForTesting;
-import android.util.Pair;
 
 import com.android.internal.os.SomeArgs;
 import com.android.internal.statusbar.IStatusBar;
@@ -164,7 +164,7 @@
         default void onRotationProposal(int rotation, boolean isValid) { }
 
         default void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver,
-                int type, boolean requireConfirmation) { }
+                int type, boolean requireConfirmation, int userId) { }
         default void onBiometricAuthenticated() { }
         default void onBiometricHelp(String message) { }
         default void onBiometricError(String error) { }
@@ -524,13 +524,14 @@
 
     @Override
     public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation) {
+            boolean requireConfirmation, int userId) {
         synchronized (mLock) {
             SomeArgs args = SomeArgs.obtain();
             args.arg1 = bundle;
             args.arg2 = receiver;
             args.argi1 = type;
             args.arg3 = requireConfirmation;
+            args.argi2 = userId;
             mHandler.obtainMessage(MSG_BIOMETRIC_SHOW, args)
                     .sendToTarget();
         }
@@ -774,8 +775,9 @@
                         mCallbacks.get(i).showBiometricDialog(
                                 (Bundle) someArgs.arg1,
                                 (IBiometricPromptReceiver) someArgs.arg2,
-                                someArgs.argi1,
-                                (boolean) someArgs.arg3);
+                                someArgs.argi1 /* type */,
+                                (boolean) someArgs.arg3 /* requireConfirmation */,
+                                someArgs.argi2 /* userId */);
                     }
                     someArgs.recycle();
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DisplayNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/DisplayNavigationBarController.java
new file mode 100644
index 0000000..3b611a3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DisplayNavigationBarController.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.os.Handler;
+import android.util.SparseArray;
+import android.view.Display;
+import android.view.View;
+import android.view.WindowManagerGlobal;
+
+import com.android.systemui.statusbar.phone.NavigationBarFragment;
+
+/**
+ * A controller to handle external navigation bars
+ */
+public class DisplayNavigationBarController implements DisplayListener {
+
+    private final Context mContext;
+    private final Handler mHandler;
+    private final DisplayManager mDisplayManager;
+
+    /** A displayId - nav bar mapping */
+    private SparseArray<NavigationBarFragment> mExternalNavigationBarMap = new SparseArray<>();
+
+    public DisplayNavigationBarController(Context context, Handler handler) {
+        mContext = context;
+        mHandler = handler;
+        mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
+
+        registerListener();
+    }
+
+    @Override
+    public void onDisplayAdded(int displayId) {
+        final Display display = mDisplayManager.getDisplay(displayId);
+        addExternalNavigationBar(display);
+    }
+
+    @Override
+    public void onDisplayRemoved(int displayId) {
+        final NavigationBarFragment navBar = mExternalNavigationBarMap.get(displayId);
+        if (navBar != null) {
+            final View navigationView = navBar.getView().getRootView();
+            WindowManagerGlobal.getInstance().removeView(navigationView, true);
+            mExternalNavigationBarMap.remove(displayId);
+        }
+    }
+
+    @Override
+    public void onDisplayChanged(int displayId) {
+    }
+
+    /** Create external navigation bars when car/status bar initializes */
+    public void createNavigationBars() {
+        // Add external navigation bars if more than one displays exist.
+        final Display[] displays = mDisplayManager.getDisplays();
+        for (Display display : displays) {
+            addExternalNavigationBar(display);
+        }
+    }
+
+    /** remove external navigation bars and unset everything related to external navigation bars */
+    public void destroy() {
+        unregisterListener();
+        if (mExternalNavigationBarMap.size() > 0) {
+            for (int i = 0; i < mExternalNavigationBarMap.size(); i++) {
+                final View navigationWindow = mExternalNavigationBarMap.valueAt(i)
+                        .getView().getRootView();
+                WindowManagerGlobal.getInstance()
+                        .removeView(navigationWindow, true /* immediate */);
+            }
+            mExternalNavigationBarMap.clear();
+        }
+    }
+
+    private void registerListener() {
+        mDisplayManager.registerDisplayListener(this, mHandler);
+    }
+
+    private void unregisterListener() {
+        mDisplayManager.unregisterDisplayListener(this);
+    }
+
+    /**
+     * Add a phone navigation bar on an external display if the display supports system decorations.
+     *
+     * @param display the display to add navigation bar on
+     */
+    private void addExternalNavigationBar(Display display) {
+        if (display == null || display.getDisplayId() == DEFAULT_DISPLAY
+                || !display.supportsSystemDecorations()) {
+            return;
+        }
+
+        final int displayId = display.getDisplayId();
+        final Context externalDisplayContext = mContext.createDisplayContext(display);
+        NavigationBarFragment.create(externalDisplayContext,
+                (tag, fragment) -> {
+                    final NavigationBarFragment navBar = (NavigationBarFragment) fragment;
+                    // TODO(b/115978725): handle external nav bars sysuiVisibility
+                    navBar.setCurrentSysuiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
+                    mExternalNavigationBarMap.append(displayId, navBar);
+                }
+        );
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 8526afd..8a86826 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -128,7 +128,8 @@
                 }
                 return true;
             case MotionEvent.ACTION_UP:
-                if (!isFalseTouch() && mDragDownCallback.onDraggedDown(mStartingChild,
+                if (!mFalsingManager.isUnlockingDisabled() && !isFalseTouch()
+                        && mDragDownCallback.onDraggedDown(mStartingChild,
                         (int) (y - mInitialTouchY))) {
                     if (mStartingChild == null) {
                         cancelExpansion();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 00e0b95..7f39e47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -62,11 +62,13 @@
 import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
+
 import com.android.internal.app.AssistUtils;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 1f57634..a188c5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -40,7 +40,6 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.KeyguardAffordanceHelper;
 
 /**
  * An ImageView which does not have overlapping renderings commands and therefore does not need a
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index a00eac4..960d221 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -51,6 +51,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
 import com.android.systemui.statusbar.phone.LockIcon;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -66,7 +67,7 @@
 /**
  * Controls the indications and error messages shown on the Keyguard
  */
-public class KeyguardIndicationController {
+public class KeyguardIndicationController implements StateListener {
 
     private static final String TAG = "KeyguardIndication";
     private static final boolean DEBUG_CHARGING_SPEED = false;
@@ -154,6 +155,19 @@
         mContext.registerReceiverAsUser(mTickReceiver, UserHandle.SYSTEM,
                 new IntentFilter(Intent.ACTION_TIME_TICK), null,
                 Dependency.get(Dependency.TIME_TICK_HANDLER));
+
+        Dependency.get(StatusBarStateController.class).addListener(this);
+    }
+
+    /**
+     * Used by {@link com.android.systemui.statusbar.phone.StatusBar} to give the indication
+     * controller a chance to unregister itself as a receiver.
+     *
+     * //TODO: This can probably be converted to a fragment and not have to be manually recreated
+     */
+    public void destroy() {
+        mContext.unregisterReceiver(mTickReceiver);
+        Dependency.get(StatusBarStateController.class).removeListener(this);
     }
 
     /**
@@ -518,6 +532,16 @@
         updateAlphas();
     }
 
+    @Override
+    public void onStateChanged(int newState) {
+        // don't care
+    }
+
+    @Override
+    public void onDozingChanged(boolean isDozing) {
+        setDozing(isDozing);
+    }
+
     protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback {
         public static final int HIDE_DELAY_MS = 5000;
         private int mLastSuccessiveErrorMessage = -1;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java
index cdb0514..8642ca4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java
@@ -17,14 +17,11 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
-import android.content.res.Resources.Theme;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
+
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
index 62c21dc..ecd9814 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
@@ -1,9 +1,9 @@
 package com.android.systemui.statusbar;
 
-import com.android.systemui.statusbar.notification.NotificationData;
-
 import androidx.annotation.NonNull;
 
+import com.android.systemui.statusbar.notification.NotificationData;
+
 /**
  * Interface for anything that may need to keep notifications managed even after
  * {@link NotificationListener} removes it.  The lifetime extender is in charge of performing the
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
index 8994568..bc662e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
@@ -15,7 +15,6 @@
 package com.android.systemui.statusbar;
 
 import android.content.pm.UserInfo;
-import android.os.SystemProperties;
 import android.service.notification.StatusBarNotification;
 import android.util.SparseArray;
 
@@ -26,8 +25,6 @@
     String NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION
             = "com.android.systemui.statusbar.work_challenge_unlocked_notification_action";
 
-    boolean AUTO_DEMOTE_NOTIFICATIONS = SystemProperties.getBoolean("debug.demote_notifs", false);
-
     boolean shouldAllowLockscreenRemoteInput();
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 0108469..f7cc9cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -15,7 +15,6 @@
  */
 package com.android.systemui.statusbar;
 
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
 
 import android.app.ActivityManager;
@@ -49,6 +48,7 @@
 import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
@@ -293,10 +293,8 @@
             return false;
         }
         boolean exceedsPriorityThreshold;
-        if (AUTO_DEMOTE_NOTIFICATIONS) {
-            exceedsPriorityThreshold =
-                    getEntryManager().getNotificationData().getImportance(sbn.getKey())
-                            >= IMPORTANCE_DEFAULT;
+        if (NotificationUtils.useNewInterruptionModel(mContext)) {
+            exceedsPriorityThreshold = getEntryManager().getNotificationData().isHighPriority(sbn);
         } else {
             exceedsPriorityThreshold =
                     !getEntryManager().getNotificationData().isAmbient(sbn.getKey());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index c437b14..fc1e94a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -280,7 +280,10 @@
         if (metaDataChanged) {
             getEntryManager().updateNotifications();
         }
-        mPresenter.updateMediaMetaData(metaDataChanged, true);
+
+        if (mPresenter != null) {
+            mPresenter.updateMediaMetaData(metaDataChanged, true);
+        }
     }
 
     public void clearCurrentMediaNotification() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
index 5c8f4cb..0e9f950 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
@@ -16,11 +16,8 @@
 package com.android.systemui.statusbar;
 
 import android.content.Intent;
-import android.os.Handler;
-import android.view.View;
 
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
-import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index bf33614..b3be714 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -95,6 +95,7 @@
     private float mFirstElementRoundness;
     private Rect mClipRect = new Rect();
     private int mCutoutHeight;
+    private int mGapHeight;
 
     private final StateListener mStateListener = this::setStatusBarState;
 
@@ -154,6 +155,7 @@
         mScrollFastThreshold = res.getDimensionPixelOffset(R.dimen.scroll_fast_threshold);
         mShowNotificationShelf = res.getBoolean(R.bool.config_showNotificationShelf);
         mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
+        mGapHeight = res.getDimensionPixelSize(R.dimen.qs_notification_padding);
 
         if (!mShowNotificationShelf) {
             setVisibility(GONE);
@@ -276,6 +278,7 @@
         int baseZHeight = mAmbientState.getBaseZHeight();
         int backgroundTop = 0;
         float firstElementRoundness = 0.0f;
+        ExpandableNotificationRow previousRow = null;
 
         for (int i = 0; i < mHostLayout.getChildCount(); i++) {
             ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
@@ -343,8 +346,27 @@
                             + " \n number of notifications: " + mHostLayout.getChildCount() );
                 }
             }
+            if (row.isFirstInSection() && previousRow != null && previousRow.isLastInSection()) {
+                // If the top of the shelf is between the view before a gap and the view after a gap
+                // then we need to adjust the shelf's top roundness.
+                float distanceToGapBottom = row.getTranslationY() - getTranslationY();
+                float distanceToGapTop = getTranslationY()
+                        - (previousRow.getTranslationY() + previousRow.getActualHeight());
+                if (distanceToGapTop > 0) {
+                    // We interpolate our top roundness so that it's fully rounded if we're at the
+                    // bottom of the gap, and not rounded at all if we're at the top of the gap
+                    // (directly up against the bottom of previousRow)
+                    // Then we apply the same roundness to the bottom of previousRow so that the
+                    // corners join together as the shelf approaches previousRow.
+                    firstElementRoundness = (float) Math.min(1.0, distanceToGapTop / mGapHeight);
+                    previousRow.setBottomRoundness(firstElementRoundness,
+                            false /* don't animate */);
+                    backgroundTop = (int) distanceToGapBottom;
+                }
+            }
             notGoneIndex++;
             previousColor = ownColorUntinted;
+            previousRow = row;
         }
 
         clipTransientViews();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
index 47b7fe9..f23ae3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
@@ -22,10 +22,10 @@
 import android.graphics.drawable.Icon;
 import android.text.TextUtils;
 
-import com.android.systemui.statusbar.notification.NotificationData;
-
 import androidx.annotation.VisibleForTesting;
 
+import com.android.systemui.statusbar.notification.NotificationData;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -53,7 +53,8 @@
 
     public static NotificationUiAdjustment extractFromNotificationEntry(
             NotificationData.Entry entry) {
-        return new NotificationUiAdjustment(entry.key, entry.smartActions, entry.smartReplies);
+        return new NotificationUiAdjustment(
+                entry.key, entry.systemGeneratedSmartActions, entry.smartReplies);
     }
 
     public static boolean needReinflate(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 92765bb..7581d8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -24,7 +24,6 @@
 import android.view.ViewGroup;
 
 import com.android.systemui.Dependency;
-import com.android.systemui.InitController;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -380,6 +379,7 @@
             }
 
             row.showAppOpsIcons(entry.mActiveAppOps);
+            row.setAudiblyAlerted(entry.audiblyAlerted);
         }
 
         Trace.beginSection("NotificationPresenter#onUpdateRowStates");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
index 5090f74..f1a891b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
@@ -15,10 +15,9 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
-import android.net.ConnectivityManager;
 import android.graphics.Rect;
+import android.net.ConnectivityManager;
 import android.os.Bundle;
-import android.provider.Settings;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.text.TextUtils;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index 7f63191..929f43e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -16,10 +16,6 @@
 
 package com.android.systemui.statusbar;
 
-import com.android.internal.util.Preconditions;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.policy.RemoteInputView;
-
 import android.app.Notification;
 import android.app.RemoteInput;
 import android.content.Context;
@@ -27,6 +23,10 @@
 import android.util.ArrayMap;
 import android.util.Pair;
 
+import com.android.internal.util.Preconditions;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.policy.RemoteInputView;
+
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index 3bc4342..cb9060b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -28,16 +28,14 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffColorFilter;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import androidx.core.graphics.ColorUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Display;
 import android.view.View;
 import android.view.WindowManager;
-import android.view.animation.Interpolator;
+
+import androidx.core.graphics.ColorUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.colorextraction.ColorExtractor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index fb888dd..758c33a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -16,13 +16,11 @@
 package com.android.systemui.statusbar;
 
 import android.os.RemoteException;
-import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
 
 import java.util.Set;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java
index 56f78f4..0652227 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar;
 
 import com.android.internal.statusbar.StatusBarIcon;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index 3c52e8c..bc89889 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -27,16 +27,14 @@
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
-
 import android.widget.LinearLayout;
+
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.keyguard.AlphaOptimizedLinearLayout;
 import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
index 12c0fcb..eaf52cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateController.java
@@ -18,11 +18,17 @@
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.annotation.IntDef;
-import android.util.ArraySet;
-import android.util.Log;
+import android.util.FloatProperty;
+import android.view.animation.Interpolator;
+
 import com.android.internal.annotations.GuardedBy;
+import com.android.systemui.Interpolators;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.StatusBar;
+
 import java.lang.annotation.Retention;
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -38,14 +44,51 @@
 
     private static final Comparator <RankedListener> mComparator
             = (o1, o2) -> Integer.compare(o1.rank, o2.rank);
+    private static final FloatProperty<StatusBarStateController> SET_DARK_AMOUNT_PROPERTY =
+            new FloatProperty<StatusBarStateController>("mDozeAmount") {
+
+                @Override
+                public void setValue(StatusBarStateController object, float value) {
+                    object.setDozeAmountInternal(value);
+                }
+
+                @Override
+                public Float get(StatusBarStateController object) {
+                    return object.mDozeAmount;
+                }
+            };
 
     private final ArrayList<RankedListener> mListeners = new ArrayList<>();
-    private boolean mIsDozing;
     private int mState;
     private int mLastState;
     private boolean mLeaveOpenOnKeyguardHide;
     private boolean mKeyguardRequested;
 
+    /**
+     * If the device is currently dozing or not.
+     */
+    private boolean mIsDozing;
+
+    /**
+     * Current {@link #mDozeAmount} animator.
+     */
+    private ValueAnimator mDarkAnimator;
+
+    /**
+     * Current doze amount in this frame.
+     */
+    private float mDozeAmount;
+
+    /**
+     * Where the animator will stop.
+     */
+    private float mDozeAmountTarget;
+
+    /**
+     * The type of interpolator that should be used to the doze animation.
+     */
+    private Interpolator mDozeInterpolator = Interpolators.FAST_OUT_SLOW_IN;
+
     // TODO: b/115739177 (remove this explicit ordering if we can)
     @Retention(SOURCE)
     @IntDef({RANK_STATUS_BAR, RANK_STATUS_BAR_WINDOW_CONTROLLER, RANK_STACK_SCROLLER, RANK_SHELF})
@@ -94,6 +137,14 @@
         return mIsDozing;
     }
 
+    public float getDozeAmount() {
+        return mDozeAmount;
+    }
+
+    public float getInterpolatedDozeAmount() {
+        return mDozeInterpolator.getInterpolation(mDozeAmount);
+    }
+
     /**
      * Update the dozing state from {@link StatusBar}'s perspective
      * @param isDozing well, are we dozing?
@@ -116,6 +167,51 @@
         return true;
     }
 
+    /**
+     * Changes the current doze amount.
+     *
+     * @param dozeAmount New doze/dark amount.
+     * @param animated If change should be animated or not. This will cancel current animations.
+     */
+    public void setDozeAmount(float dozeAmount, boolean animated) {
+        if (mDarkAnimator != null && mDarkAnimator.isRunning()) {
+            if (animated && mDozeAmountTarget == dozeAmount) {
+                return;
+            } else {
+                mDarkAnimator.cancel();
+            }
+        }
+
+        mDozeAmountTarget = dozeAmount;
+        if (animated) {
+            startDozeAnimation();
+        } else {
+            setDozeAmountInternal(dozeAmount);
+        }
+    }
+
+    private void startDozeAnimation() {
+        if (mDozeAmount == 0f || mDozeAmount == 1f) {
+            mDozeInterpolator = mIsDozing
+                    ? Interpolators.FAST_OUT_SLOW_IN
+                    : Interpolators.TOUCH_RESPONSE_REVERSE;
+        }
+        mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, mDozeAmountTarget);
+        mDarkAnimator.setInterpolator(Interpolators.LINEAR);
+        mDarkAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
+        mDarkAnimator.start();
+    }
+
+    private void setDozeAmountInternal(float dozeAmount) {
+        mDozeAmount = dozeAmount;
+        float interpolatedAmount = mDozeInterpolator.getInterpolation(dozeAmount);
+        synchronized (mListeners) {
+            for (RankedListener rl : new ArrayList<>(mListeners)) {
+                rl.listener.onDozeAmountChanged(mDozeAmount, interpolatedAmount);
+            }
+        }
+    }
+
     public boolean goingToFullShade() {
         return mState == StatusBarState.SHADE && mLeaveOpenOnKeyguardHide;
     }
@@ -202,7 +298,8 @@
     public interface StateListener {
 
         /**
-         * Callback before the new state is applied, for those who need to preempt the change
+         * Callback before the new state is applied, for those who need to preempt the change.
+         *
          * @param oldState state before the change
          * @param newState new state to be applied in {@link #onStateChanged}
          */
@@ -218,17 +315,29 @@
         /**
          * Required callback. Get the new state and do what you will with it. Keep in mind that
          * other listeners are typically unordered and don't rely on your work being done before
-         * other peers
+         * other peers.
          *
-         * Only called if the state is actually different
+         * Only called if the state is actually different.
+         *
          * @param newState the new {@link StatusBarState}
          */
         public void onStateChanged(int newState);
 
         /**
          * Callback to be notified when Dozing changes. Dozing is stored separately from state.
+         *
          * @param isDozing {@code true} if dozing according to {@link StatusBar}
          */
         public default void onDozingChanged(boolean isDozing) {}
+
+        /**
+         * Callback to be notified when the doze amount changes. Useful for animations.
+         * Note: this will be called for each animation frame. Please be careful to avoid
+         * performance regressions.
+         *
+         * @param linear A number from 0 to 1, where 1 means that the device is dozing.
+         * @param eased Same as {@code linear} but transformed by an interpolator.
+         */
+        default void onDozeAmountChanged(float linear, float eased) {}
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
index f3fc99e..045221f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
@@ -27,18 +27,14 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
-
 import android.widget.LinearLayout;
-import com.android.keyguard.AlphaOptimizedLinearLayout;
+
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
index f9afc7c..c4fadff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
@@ -16,12 +16,12 @@
 
 package com.android.systemui.statusbar;
 
-import com.android.systemui.statusbar.phone.SystemUIDialog;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
 import android.content.Context;
 import android.content.DialogInterface;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
 
 public class UserUtil {
     public static void deleteUserWithPrompt(Context context, int userId,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
index 46f8863..bd32856 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
@@ -3,10 +3,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index 9ed0929..81f7846 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -16,13 +16,10 @@
 
 package com.android.systemui.statusbar.car;
 
-import android.app.UiModeManager;
 import android.content.Context;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 import android.widget.LinearLayout;
-import android.widget.TextView;
 
 import com.android.keyguard.AlphaOptimizedImageButton;
 import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index c35e1da..4bff5ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -35,7 +35,6 @@
 import com.android.systemui.classifier.FalsingLog;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.recents.Recents;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.statusbar.StatusBarState;
@@ -268,6 +267,8 @@
         buildNavBarWindows();
         buildNavBarContent();
         attachNavBarWindows();
+
+        mNavigationBarController.createNavigationBars();
     }
 
     private void buildNavBarContent() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
index 0304086..f2923f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
@@ -1,5 +1,7 @@
 package com.android.systemui.statusbar.car;
 
+import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
+
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadsetClient;
@@ -9,21 +11,19 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.telephony.SignalStrength;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.View;
 import android.widget.ImageView;
+
 import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ScalingDrawableWrapper;
 import com.android.systemui.statusbar.policy.BluetoothController;
 
-import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
-
 /**
  * Controller that monitors signal strength for a device that is connected via bluetooth.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java
index f9fa44b..0c91cba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java
@@ -21,10 +21,10 @@
 import android.os.CountDownTimer;
 import android.util.Log;
 
-import com.android.systemui.R;
-
 import androidx.annotation.GuardedBy;
 
+import com.android.systemui.R;
+
 /**
  * Wrapper for a countdown timer that switches to Guest if the user has been driving with
  * the keyguard up for configurable number of seconds.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 53a7afe..d802ed8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -29,7 +29,6 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.os.AsyncTask;
-import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -44,8 +43,8 @@
 
 import com.android.internal.util.UserIcons;
 import com.android.systemui.R;
-
 import com.android.systemui.statusbar.phone.SystemUIDialog;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
index 8c72544..6044a7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
@@ -16,11 +16,7 @@
 
 package com.android.systemui.statusbar.notification;
 
-import android.text.Layout;
-import android.text.TextUtils;
 import android.util.Pools;
-import android.view.View;
-import android.widget.TextView;
 
 /**
  * A transform state of the action list
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
index de4c312..dea1a07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
@@ -17,16 +17,11 @@
 package com.android.systemui.statusbar.notification;
 
 import android.view.View;
-import android.view.animation.Interpolator;
 
-import com.android.systemui.Interpolators;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.ViewTransformationHelper;
 
-import static com.android.systemui.statusbar.TransformableView.TRANSFORMING_VIEW_TITLE;
-import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
-
 /**
  * A custom transformation that modifies the interpolator
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java
index 454edbb..f5a76f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.notification;
 
 import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.ColorMatrix;
@@ -27,7 +26,6 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Shader;
-import android.graphics.Xfermode;
 import android.graphics.drawable.Drawable;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
index 8c0d700..ab94008 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
@@ -23,9 +23,10 @@
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
+import android.util.LayoutDirection;
+
 import androidx.annotation.VisibleForTesting;
 import androidx.palette.graphics.Palette;
-import android.util.LayoutDirection;
 
 import com.android.internal.util.ContrastColorUtil;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
index b97995d..a3fb225 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
@@ -20,7 +20,6 @@
 import android.view.View;
 
 import com.android.internal.widget.MessagingImageMessage;
-import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ViewTransformationHelper;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
index 3539fff..da6d977 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
@@ -51,13 +51,14 @@
 import android.view.View;
 import android.widget.ImageView;
 
+import androidx.annotation.Nullable;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.ContrastColorUtil;
 import com.android.systemui.Dependency;
 import com.android.systemui.ForegroundServiceController;
-import com.android.systemui.InitController;
 import com.android.systemui.statusbar.InflationTask;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
@@ -75,8 +76,6 @@
 import java.util.List;
 import java.util.Objects;
 
-import androidx.annotation.Nullable;
-
 /**
  * The list of currently displaying notifications.
  */
@@ -102,6 +101,9 @@
         public String key;
         public StatusBarNotification notification;
         public NotificationChannel channel;
+        public boolean audiblyAlerted;
+        public boolean noisy;
+        public int importance;
         public StatusBarIconView icon;
         public StatusBarIconView expandedIcon;
         public ExpandableNotificationRow row; // the outer expanded view
@@ -112,8 +114,9 @@
         public CharSequence remoteInputText;
         public List<SnoozeCriterion> snoozeCriteria;
         public int userSentiment = Ranking.USER_SENTIMENT_NEUTRAL;
+        /** Smart Actions provided by the NotificationAssistantService. */
         @NonNull
-        public List<Notification.Action> smartActions = Collections.emptyList();
+        public List<Notification.Action> systemGeneratedSmartActions = Collections.emptyList();
         public CharSequence[] smartReplies = new CharSequence[0];
 
         private int mCachedContrastColor = COLOR_INVALID;
@@ -140,6 +143,16 @@
          */
         private boolean hasSentReply;
 
+        /**
+         * Whether this notification should be displayed as a bubble.
+         */
+        private boolean mIsBubble;
+
+        /**
+         * Whether the user has dismissed this notification when it was in bubble form.
+         */
+        private boolean mUserDismissedBubble;
+
         public Entry(StatusBarNotification n) {
             this(n, null);
         }
@@ -154,9 +167,12 @@
 
         public void populateFromRanking(@NonNull Ranking ranking) {
             channel = ranking.getChannel();
+            audiblyAlerted = ranking.audiblyAlerted();
+            noisy = ranking.isNoisy();
+            importance = ranking.getImportance();
             snoozeCriteria = ranking.getSnoozeCriteria();
             userSentiment = ranking.getUserSentiment();
-            smartActions = ranking.getSmartActions() == null
+            systemGeneratedSmartActions = ranking.getSmartActions() == null
                     ? Collections.emptyList() : ranking.getSmartActions();
             smartReplies = ranking.getSmartReplies() == null
                     ? new CharSequence[0]
@@ -171,6 +187,22 @@
             return interruption;
         }
 
+        public void setIsBubble(boolean bubbleable) {
+            mIsBubble = bubbleable;
+        }
+
+        public boolean isBubble() {
+            return mIsBubble;
+        }
+
+        public void setBubbleDismissed(boolean userDismissed) {
+            mUserDismissedBubble = userDismissed;
+        }
+
+        public boolean isBubbleDismissed() {
+            return mUserDismissedBubble;
+        }
+
         /**
          * Resets the notification entry to be re-used.
          */
@@ -562,6 +594,20 @@
         }
     }
 
+    /**
+     * Returns true if this notification should be displayed in the high-priority notifications
+     * section (and on the lockscreen and status bar).
+     */
+    public boolean isHighPriority(StatusBarNotification statusBarNotification) {
+        if (mRankingMap != null) {
+            getRanking(statusBarNotification.getKey(), mTmpRanking);
+            return mTmpRanking.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
+                    || statusBarNotification.getNotification().isForegroundService()
+                    || statusBarNotification.getNotification().hasMediaSession();
+        }
+        return false;
+    }
+
     public boolean isAmbient(String key) {
         if (mRankingMap != null) {
             getRanking(key, mTmpRanking);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
index fb362c5..ef042ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationDozeHelper.java
@@ -26,7 +26,7 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.NotificationPanelView;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
 import java.util.function.Consumer;
 
@@ -63,13 +63,14 @@
         }
     }
 
+    // TODO: this should be using StatusBarStateController#getDozeAmount
     public void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
             boolean dark, long delay, Animator.AnimatorListener listener) {
         float startIntensity = dark ? 0f : 1f;
         float endIntensity = dark ? 1f : 0f;
         ValueAnimator animator = ValueAnimator.ofFloat(startIntensity, endIntensity);
         animator.addUpdateListener(updateListener);
-        animator.setDuration(NotificationPanelView.DOZE_ANIMATION_DURATION);
+        animator.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
         animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
         animator.setStartDelay(delay);
         if (listener != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 3bea7db..274d4b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -702,7 +702,6 @@
                 && !mPresenter.isPresenterFullyCollapsed();
         row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
         row.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp);
-        row.setSmartActions(entry.smartActions);
         row.setEntry(entry);
 
         row.updateInflationFlag(FLAG_CONTENT_VIEW_HEADS_UP, shouldHeadsUp(entry));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
index 66ba9e9..1f48c15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
@@ -16,8 +16,11 @@
 
 package com.android.systemui.statusbar.notification;
 
+import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
+
 import android.content.Context;
 import android.graphics.Color;
+import android.provider.Settings;
 import android.view.View;
 import android.widget.ImageView;
 
@@ -68,4 +71,10 @@
                 context.getResources().getDisplayMetrics().density);
         return (int) (dimensionPixelSize * factor);
     }
+
+    /** Returns the value of the new interruption model setting. */
+    public static boolean useNewInterruptionModel(Context context) {
+        return Settings.Secure.getInt(context.getContentResolver(),
+                NOTIFICATION_NEW_INTERRUPTION_MODEL, 0) != 0;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 07b8c35..337f312 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -29,9 +29,9 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.ViewTransformationHelper;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
  * A transform state of a view.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index da8954a..75613a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -16,9 +16,10 @@
 
 package com.android.systemui.statusbar.notification;
 
-import androidx.collection.ArraySet;
 import android.view.View;
 
+import androidx.collection.ArraySet;
+
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
index 28c07a3..43b5503 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
@@ -30,6 +30,9 @@
     /** Counter tag for when the user hits 'stop notifications' in the blocking helper. */
     public static final String BLOCKING_HELPER_STOP_NOTIFICATIONS =
             "blocking_helper_stop_notifications";
+    /** Counter tag for when the user hits 'show silently' in the blocking helper. */
+    public static final String BLOCKING_HELPER_TOGGLE_SILENT =
+            "blocking_helper_toggle_silent";
     /** Counter tag for when the user hits 'keep showing' in the blocking helper. */
     public static final String BLOCKING_HELPER_KEEP_SHOWING =
             "blocking_helper_keep_showing";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index b5fbde1..5dfd5d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -29,9 +29,11 @@
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.Dependency;
 import com.android.systemui.UiOffloadThread;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 
 import java.util.ArrayList;
@@ -42,7 +44,7 @@
  * Handles notification logging, in particular, logging which notifications are visible and which
  * are not.
  */
-public class NotificationLogger {
+public class NotificationLogger implements StateListener {
     private static final String TAG = "NotificationLogger";
 
     /** The minimum delay in ms between reports of notification visibility. */
@@ -63,7 +65,7 @@
     protected IStatusBarService mBarService;
     private long mLastVisibilityReportUptimeMs;
     private NotificationListContainer mListContainer;
-    private Object mDozingLock = new Object();
+    private final Object mDozingLock = new Object();
     private boolean mDozing;
 
     protected final OnChildLocationsChangedListener mNotificationLocationsChangedListener =
@@ -146,6 +148,8 @@
     public NotificationLogger() {
         mBarService = IStatusBarService.Stub.asInterface(
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+        // Not expected to be destroyed, don't need to unsubscribe
+        Dependency.get(StatusBarStateController.class).addListener(this);
     }
 
     public void setUpWithContainer(NotificationListContainer listContainer) {
@@ -175,7 +179,7 @@
         mNotificationLocationsChangedListener.onChildLocationsChanged();
     }
 
-    public void setDozing(boolean dozing) {
+    private void setDozing(boolean dozing) {
         synchronized (mDozingLock) {
             mDozing = dozing;
         }
@@ -258,6 +262,16 @@
         return mVisibilityReporter;
     }
 
+    @Override
+    public void onStateChanged(int newState) {
+        // don't care about state change
+    }
+
+    @Override
+    public void onDozingChanged(boolean isDozing) {
+        setDozing(isDozing);
+    }
+
     /**
      * A listener that is notified when some child locations might have changed.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 58db03c..3380b38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -40,9 +40,9 @@
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.notification.FakeShadowView;
 import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.phone.DoubleTapHelper;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.phone.DoubleTapHelper;
 
 /**
  * Base class for both {@link ExpandableNotificationRow} and {@link NotificationShelf}
@@ -134,6 +134,8 @@
     private float mAppearAnimationFraction = -1.0f;
     private float mAppearAnimationTranslation;
     private int mNormalColor;
+    private boolean mLastInSection;
+    private boolean mFirstInSection;
     private boolean mIsBelowSpeedBump;
     private FalsingManager mFalsingManager;
 
@@ -533,6 +535,32 @@
         mBackgroundDimmed.setDistanceToTopRoundness(distanceToTopRoundness);
     }
 
+    public boolean isLastInSection() {
+        return mLastInSection;
+    }
+
+    public boolean isFirstInSection() {
+        return mFirstInSection;
+    }
+
+    /** Sets whether this view is the last notification in a section. */
+    public void setLastInSection(boolean lastInSection) {
+        if (lastInSection != mLastInSection) {
+            mLastInSection = lastInSection;
+            mBackgroundNormal.setLastInSection(lastInSection);
+            mBackgroundDimmed.setLastInSection(lastInSection);
+        }
+    }
+
+    /** Sets whether this view is the first notification in a section. */
+    public void setFirstInSection(boolean firstInSection) {
+        if (firstInSection != mFirstInSection) {
+            mFirstInSection = firstInSection;
+            mBackgroundNormal.setFirstInSection(firstInSection);
+            mBackgroundDimmed.setFirstInSection(firstInSection);
+        }
+    }
+
     /**
      * Set an override tint color that is used for the background.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 965fb13..c7876cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -16,14 +16,22 @@
 
 package com.android.systemui.statusbar.notification.row;
 
-import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
-import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_AMBIENT;
-import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_CONTRACTED;
-import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_PUBLIC;
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.InflationCallback;
+import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
+        .ExpandAnimationParameters;
+import static com.android.systemui.statusbar.notification.row.NotificationContentView
+        .VISIBLE_TYPE_AMBIENT;
+import static com.android.systemui.statusbar.notification.row.NotificationContentView
+        .VISIBLE_TYPE_CONTRACTED;
+import static com.android.systemui.statusbar.notification.row.NotificationContentView
+        .VISIBLE_TYPE_HEADSUP;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater
+        .FLAG_CONTENT_VIEW_AMBIENT;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater
+        .FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater
+        .FLAG_CONTENT_VIEW_PUBLIC;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater
+        .InflationCallback;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -31,7 +39,6 @@
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.Notification;
 import android.app.NotificationChannel;
 import android.content.Context;
 import android.content.pm.PackageInfo;
@@ -1559,10 +1566,6 @@
         mNotificationInflater.setUsesIncreasedHeight(use);
     }
 
-    public void setSmartActions(List<Notification.Action> smartActions) {
-        mNotificationInflater.setSmartActions(smartActions);
-    }
-
     public void setUseIncreasedHeadsUpHeight(boolean use) {
         mUseIncreasedHeadsUpHeight = use;
         mNotificationInflater.setUsesIncreasedHeadsUpHeight(use);
@@ -1658,6 +1661,17 @@
         mPublicLayout.showAppOpsIcons(activeOps);
     }
 
+    /** Sets whether the notification being displayed audibly alerted the user. */
+    public void setAudiblyAlerted(boolean audiblyAlerted) {
+        if (NotificationUtils.useNewInterruptionModel(mContext)) {
+            if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() != null) {
+                mChildrenContainer.getHeaderView().setAudiblyAlerted(audiblyAlerted);
+            }
+            mPrivateLayout.setAudiblyAlerted(audiblyAlerted);
+            mPublicLayout.setAudiblyAlerted(audiblyAlerted);
+        }
+    }
+
     public View.OnClickListener getAppOpsOnClickListener() {
         return mOnAppOpsClickListener;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
index 1ed726d..62d596b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
@@ -46,6 +46,8 @@
     private int mTintColor;
     private float[] mCornerRadii = new float[8];
     private boolean mBottomIsRounded;
+    private boolean mLastInSection;
+    private boolean mFirstInSection;
     private int mBackgroundTop;
     private boolean mBottomAmountClips = true;
     private boolean mExpandAnimationRunning;
@@ -79,7 +81,10 @@
         if (drawable != null) {
             int top = mBackgroundTop;
             int bottom = mActualHeight;
-            if (mBottomIsRounded && mBottomAmountClips && !mExpandAnimationRunning) {
+            if (mBottomIsRounded
+                    && mBottomAmountClips
+                    && !mExpandAnimationRunning
+                    && !mLastInSection) {
                 bottom -= mClipBottomAmount;
             }
             int left = 0;
@@ -90,8 +95,10 @@
             }
             if (mTopAmountRounded) {
                 int clipTop = (int) (mClipTopAmount - mDistanceToTopRoundness);
-                top += clipTop;
-                if (clipTop >= 0) {
+                if (clipTop >= 0 || !mFirstInSection) {
+                    top += clipTop;
+                }
+                if (clipTop >= 0 && !mLastInSection) {
                     bottom += clipTop;
                 }
             }
@@ -216,19 +223,23 @@
         mBackground.setAlpha(drawableAlpha);
     }
 
-    public void setRoundness(float topRoundness, float bottomRoundNess) {
-        if (topRoundness == mCornerRadii[0] && bottomRoundNess == mCornerRadii[4]) {
+    /**
+     * Sets the current top and bottom roundness amounts for this background, between 0.0 (not
+     * rounded) and 1.0 (maximally rounded).
+     */
+    public void setRoundness(float topRoundness, float bottomRoundness) {
+        if (topRoundness == mCornerRadii[0] && bottomRoundness == mCornerRadii[4]) {
             return;
         }
-        mBottomIsRounded = bottomRoundNess != 0.0f;
+        mBottomIsRounded = bottomRoundness != 0.0f;
         mCornerRadii[0] = topRoundness;
         mCornerRadii[1] = topRoundness;
         mCornerRadii[2] = topRoundness;
         mCornerRadii[3] = topRoundness;
-        mCornerRadii[4] = bottomRoundNess;
-        mCornerRadii[5] = bottomRoundNess;
-        mCornerRadii[6] = bottomRoundNess;
-        mCornerRadii[7] = bottomRoundNess;
+        mCornerRadii[4] = bottomRoundness;
+        mCornerRadii[5] = bottomRoundness;
+        mCornerRadii[6] = bottomRoundness;
+        mCornerRadii[7] = bottomRoundness;
         updateBackgroundRadii();
     }
 
@@ -239,6 +250,18 @@
         }
     }
 
+    /** Sets whether this background belongs to the last notification in a section. */
+    public void setLastInSection(boolean lastInSection) {
+        mLastInSection = lastInSection;
+        invalidate();
+    }
+
+    /** Sets whether this background belongs to the first notification in a section. */
+    public void setFirstInSection(boolean firstInSection) {
+        mFirstInSection = firstInSection;
+        invalidate();
+    }
+
     private void updateBackgroundRadii() {
         if (mDontModifyCorners) {
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
index 1a4ef09..16796dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
@@ -16,10 +16,13 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import static android.service.notification.NotificationListenerService.Ranking
+        .USER_SENTIMENT_NEGATIVE;
+
 import android.content.Context;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
-import android.util.Log;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Dependency;
@@ -31,8 +34,6 @@
 import java.util.HashSet;
 import java.util.Set;
 
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-
 /**
  * Manager for the notification blocking helper - tracks and helps create the blocking helper
  * affordance.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 11cf8e0..fa3fa5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1551,6 +1551,19 @@
         }
     }
 
+    /** Sets whether the notification being displayed audibly alerted the user. */
+    public void setAudiblyAlerted(boolean audiblyAlerted) {
+        if (mContractedChild != null && mContractedWrapper.getNotificationHeader() != null) {
+            mContractedWrapper.getNotificationHeader().setAudiblyAlerted(audiblyAlerted);
+        }
+        if (mExpandedChild != null && mExpandedWrapper.getNotificationHeader() != null) {
+            mExpandedWrapper.getNotificationHeader().setAudiblyAlerted(audiblyAlerted);
+        }
+        if (mHeadsUpChild != null && mHeadsUpWrapper.getNotificationHeader() != null) {
+            mHeadsUpWrapper.getNotificationHeader().setAudiblyAlerted(audiblyAlerted);
+        }
+    }
+
     public NotificationHeaderView getContractedNotificationHeader() {
         if (mContractedChild != null) {
             return mContractedWrapper.getNotificationHeader();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
index 0a197da..fbe9c5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -23,7 +23,6 @@
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
-import androidx.annotation.Nullable;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
@@ -31,6 +30,8 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout;
 
+import androidx.annotation.Nullable;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
@@ -98,6 +99,11 @@
          * Return whether something changed and needs to be saved, possibly requiring a bouncer.
          */
         boolean shouldBeSaved();
+
+        /**
+         * Called when the guts view has finished its close animation.
+         */
+        default void onFinishedClosing() {}
     }
 
     public interface OnGutsClosedListener {
@@ -304,7 +310,7 @@
                         x, y, r, 0);
                 a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
                 a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
-                a.addListener(new AnimateCloseListener(this /* view */));
+                a.addListener(new AnimateCloseListener(this /* view */, mGutsContent));
                 a.start();
             } else {
                 // Fade in the blocking helper.
@@ -312,11 +318,12 @@
                         .alpha(0f)
                         .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
                         .setInterpolator(Interpolators.ALPHA_OUT)
-                        .setListener(new AnimateCloseListener(this /* view */))
+                        .setListener(new AnimateCloseListener(this, /* view */mGutsContent))
                         .start();
             }
         } else {
             Log.w(TAG, "Failed to animate guts close");
+            mGutsContent.onFinishedClosing();
         }
     }
 
@@ -414,15 +421,18 @@
     /** Listener for animations executed in {@link #animateClose(int, int, boolean)}. */
     private static class AnimateCloseListener extends AnimatorListenerAdapter {
         final View mView;
+        private final GutsContent mGutsContent;
 
-        private AnimateCloseListener(View view) {
+        private AnimateCloseListener(View view, GutsContent gutsContent) {
             mView = view;
+            mGutsContent = gutsContent;
         }
 
         @Override
         public void onAnimationEnd(Animator animation) {
             super.onAnimationEnd(animation);
             mView.setVisibility(View.GONE);
+            mGutsContent.onFinishedClosing();
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 2499952..37bf06e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -21,6 +21,8 @@
 import static android.service.notification.NotificationListenerService.Ranking
         .USER_SENTIMENT_NEGATIVE;
 
+import static com.android.systemui.statusbar.notification.row.NotificationInfo.ACTION_NONE;
+
 import android.app.INotificationManager;
 import android.app.NotificationChannel;
 import android.content.Context;
@@ -28,7 +30,6 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.net.Uri;
-import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -46,15 +47,13 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
 import com.android.systemui.statusbar.NotificationLifetimeExtender;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -192,7 +191,13 @@
             } else if (gutsView instanceof AppOpsInfo) {
                 initializeAppOpsInfo(row, (AppOpsInfo) gutsView);
             } else if (gutsView instanceof NotificationInfo) {
-                initializeNotificationInfo(row, (NotificationInfo) gutsView);
+                int action;
+                if (item instanceof NotificationMenuRow.NotificationInfoMenuItem) {
+                    action = ((NotificationMenuRow.NotificationInfoMenuItem) item).mAction;
+                } else {
+                    action = ACTION_NONE;
+                }
+                initializeNotificationInfo(row, (NotificationInfo) gutsView, action);
             }
             return true;
         } catch (Exception e) {
@@ -249,14 +254,15 @@
 
     /**
      * Sets up the {@link NotificationInfo} inside the notification row's guts.
-     *
      * @param row view to set up the guts for
      * @param notificationInfoView view to set up/bind within {@code row}
+     * @param action The action to take immediately upon binding, if any.
      */
     @VisibleForTesting
     void initializeNotificationInfo(
             final ExpandableNotificationRow row,
-            NotificationInfo notificationInfoView) throws Exception {
+            NotificationInfo notificationInfoView,
+            @NotificationInfo.NotificationInfoAction int action) throws Exception {
         NotificationGuts guts = row.getGuts();
         StatusBarNotification sbn = row.getStatusBarNotification();
         String packageName = sbn.getPackageName();
@@ -298,7 +304,10 @@
                 mDeviceProvisionedController.isDeviceProvisioned(),
                 row.getIsNonblockable(),
                 isForBlockingHelper,
-                row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE);
+                row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE,
+                row.getEntry().noisy,
+                row.getEntry().importance,
+                action);
 
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java
index 38d6b35..e1c2f73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java
@@ -43,10 +43,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
-import java.util.List;
 import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadFactory;
@@ -131,7 +128,6 @@
     private boolean mIsChildInGroup;
     private InflationCallback mCallback;
     private boolean mRedactAmbient;
-    private List<Notification.Action> mSmartActions;
     private final ArrayMap<Integer, RemoteViews> mCachedContentViews = new ArrayMap<>();
 
     public NotificationInflater(ExpandableNotificationRow row) {
@@ -161,10 +157,6 @@
         mUsesIncreasedHeight = usesIncreasedHeight;
     }
 
-    public void setSmartActions(List<Notification.Action> smartActions) {
-        mSmartActions = smartActions;
-    }
-
     public void setUsesIncreasedHeadsUpHeight(boolean usesIncreasedHeight) {
         mUsesIncreasedHeadsUpHeight = usesIncreasedHeight;
     }
@@ -258,8 +250,7 @@
         StatusBarNotification sbn = mRow.getEntry().notification;
         AsyncInflationTask task = new AsyncInflationTask(sbn, reInflateFlags, mCachedContentViews,
                 mRow, mIsLowPriority, mIsChildInGroup, mUsesIncreasedHeight,
-                mUsesIncreasedHeadsUpHeight, mRedactAmbient, mCallback, mRemoteViewClickHandler,
-                mSmartActions);
+                mUsesIncreasedHeadsUpHeight, mRedactAmbient, mCallback, mRemoteViewClickHandler);
         if (mCallback != null && mCallback.doInflateSynchronous()) {
             task.onPostExecute(task.doInBackground());
         } else {
@@ -765,15 +756,13 @@
         private Exception mError;
         private RemoteViews.OnClickHandler mRemoteViewClickHandler;
         private CancellationSignal mCancellationSignal;
-        private List<Notification.Action> mSmartActions;
 
         private AsyncInflationTask(StatusBarNotification notification,
                 @InflationFlag int reInflateFlags,
                 ArrayMap<Integer, RemoteViews> cachedContentViews, ExpandableNotificationRow row,
                 boolean isLowPriority, boolean isChildInGroup, boolean usesIncreasedHeight,
                 boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,
-                InflationCallback callback, RemoteViews.OnClickHandler remoteViewClickHandler,
-                List<Notification.Action> smartActions) {
+                InflationCallback callback, RemoteViews.OnClickHandler remoteViewClickHandler) {
             mRow = row;
             mSbn = notification;
             mReInflateFlags = reInflateFlags;
@@ -786,9 +775,6 @@
             mRedactAmbient = redactAmbient;
             mRemoteViewClickHandler = remoteViewClickHandler;
             mCallback = callback;
-            mSmartActions = smartActions == null
-                    ? Collections.emptyList()
-                    : new ArrayList<>(smartActions);
             NotificationData.Entry entry = row.getEntry();
             entry.setInflationTask(this);
         }
@@ -806,8 +792,6 @@
                         = Notification.Builder.recoverBuilder(mContext,
                         mSbn.getNotification());
 
-                applyChanges(recoveredBuilder);
-
                 Context packageContext = mSbn.getPackageContext(mContext);
                 Notification notification = mSbn.getNotification();
                 if (notification.isMediaNotification()) {
@@ -834,18 +818,6 @@
             }
         }
 
-        /**
-         * Apply changes to the given notification builder, like adding smart actions suggested by
-         * a {@link android.service.notification.NotificationAssistantService}.
-         */
-        private void applyChanges(Notification.Builder builder) {
-            if (mSmartActions != null) {
-                for (Notification.Action smartAction : mSmartActions) {
-                    builder.addAction(smartAction);
-                }
-            }
-        }
-
         private void handleError(Exception e) {
             mRow.getEntry().onInflationTaskFinished();
             StatusBarNotification sbn = mRow.getStatusBarNotification();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 903c272..3a7091b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -16,13 +16,18 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.INotificationManager;
 import android.app.Notification;
@@ -54,6 +59,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.logging.NotificationCounters;
 
 import java.util.List;
@@ -65,6 +71,20 @@
 public class NotificationInfo extends LinearLayout implements NotificationGuts.GutsContent {
     private static final String TAG = "InfoGuts";
 
+    @IntDef(prefix = { "ACTION_" }, value = {
+            ACTION_NONE,
+            ACTION_UNDO,
+            ACTION_TOGGLE_SILENT,
+            ACTION_BLOCK,
+    })
+    public @interface NotificationInfoAction {
+    }
+
+    public static final int ACTION_NONE = 0;
+    public static final int ACTION_UNDO = 1;
+    public static final int ACTION_TOGGLE_SILENT = 2;
+    public static final int ACTION_BLOCK = 3;
+
     private INotificationManager mINotificationManager;
     private PackageManager mPm;
     private MetricsLogger mMetricsLogger;
@@ -74,7 +94,8 @@
     private int mAppUid;
     private int mNumUniqueChannelsInRow;
     private NotificationChannel mSingleNotificationChannel;
-    private int mStartingUserImportance;
+    private int mStartingChannelImportance;
+    private int mStartingChannelOrNotificationImportance;
     private int mChosenImportance;
     private boolean mIsSingleDefaultChannel;
     private boolean mIsNonblockable;
@@ -82,6 +103,7 @@
     private AnimatorSet mExpandAnimation;
     private boolean mIsForeground;
     private boolean mIsDeviceProvisioned;
+    private boolean mIsNoisy;
 
     private CheckSaveListener mCheckSaveListener;
     private OnSettingsClickListener mOnSettingsClickListener;
@@ -102,10 +124,20 @@
         closeControls(v);
     };
 
+    private OnClickListener mOnToggleSilent = v -> {
+        Runnable saveImportance = () -> {
+            swapContent(ACTION_TOGGLE_SILENT, true /* animate */);
+        };
+        if (mCheckSaveListener != null) {
+            mCheckSaveListener.checkSave(saveImportance, mSbn);
+        } else {
+            saveImportance.run();
+        }
+    };
+
     private OnClickListener mOnStopOrMinimizeNotifications = v -> {
         Runnable saveImportance = () -> {
-            mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
-            swapContent(false);
+            swapContent(ACTION_BLOCK, true /* animate */);
         };
         if (mCheckSaveListener != null) {
             mCheckSaveListener.checkSave(saveImportance, mSbn);
@@ -118,7 +150,7 @@
         // Reset exit counter that we'll log and record an undo event separately (not an exit event)
         mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
         logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
-        swapContent(true);
+        swapContent(ACTION_UNDO, true /* animate */);
     };
 
     public NotificationInfo(Context context, AttributeSet attrs) {
@@ -152,12 +184,16 @@
             final OnSettingsClickListener onSettingsClick,
             final OnAppSettingsClickListener onAppSettingsClick,
             boolean isDeviceProvisioned,
-            boolean isNonblockable)
+            boolean isNonblockable,
+            boolean isNoisy,
+            int importance,
+            @NotificationInfoAction int action)
             throws RemoteException {
         bindNotification(pm, iNotificationManager, pkg, notificationChannel,
                 numUniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
                 onAppSettingsClick, isDeviceProvisioned, isNonblockable,
-                false /* isBlockingHelper */, false /* isUserSentimentNegative */);
+                false /* isBlockingHelper */, false /* isUserSentimentNegative */, isNoisy,
+                importance, action);
     }
 
     public void bindNotification(
@@ -173,7 +209,10 @@
             boolean isDeviceProvisioned,
             boolean isNonblockable,
             boolean isForBlockingHelper,
-            boolean isUserSentimentNegative)
+            boolean isUserSentimentNegative,
+            boolean isNoisy,
+            int importance,
+            @NotificationInfoAction int action)
             throws RemoteException {
         mINotificationManager = iNotificationManager;
         mMetricsLogger = Dependency.get(MetricsLogger.class);
@@ -186,7 +225,10 @@
         mCheckSaveListener = checkSaveListener;
         mOnSettingsClickListener = onSettingsClick;
         mSingleNotificationChannel = notificationChannel;
-        mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
+        int channelImportance = mSingleNotificationChannel.getImportance();
+        mStartingChannelImportance = mChosenImportance = channelImportance;
+        mStartingChannelOrNotificationImportance =
+                channelImportance == IMPORTANCE_UNSPECIFIED ? importance : channelImportance;
         mNegativeUserSentiment = isUserSentimentNegative;
         mIsNonblockable = isNonblockable;
         mIsForeground =
@@ -194,6 +236,7 @@
         mIsForBlockingHelper = isForBlockingHelper;
         mAppUid = mSbn.getUid();
         mIsDeviceProvisioned = isDeviceProvisioned;
+        mIsNoisy = isNoisy;
 
         int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
                 pkg, mAppUid, false /* includeDeleted */);
@@ -210,6 +253,10 @@
         bindHeader();
         bindPrompt();
         bindButtons();
+
+        if (action != ACTION_NONE) {
+            swapContent(action, false /* don't animate */);
+        }
     }
 
     private void bindHeader() throws RemoteException {
@@ -306,11 +353,13 @@
     }
 
     private boolean hasImportanceChanged() {
-        return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
+        return mSingleNotificationChannel != null
+                && mStartingChannelImportance != mChosenImportance;
     }
 
     private void saveImportance() {
-        if (!mIsNonblockable) {
+        if (!mIsNonblockable
+                || mExitReason != NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS) {
             updateImportance();
         }
     }
@@ -320,34 +369,46 @@
      */
     private void updateImportance() {
         MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
-                mChosenImportance - mStartingUserImportance);
+                mChosenImportance - mStartingChannelImportance);
 
         Handler bgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
         bgHandler.post(new UpdateImportanceRunnable(mINotificationManager, mPackageName, mAppUid,
                 mNumUniqueChannelsInRow == 1 ? mSingleNotificationChannel : null,
-                mStartingUserImportance, mChosenImportance));
+                mStartingChannelImportance, mChosenImportance));
     }
 
     private void bindButtons() {
         // Set up stay-in-notification actions
         View block =  findViewById(R.id.block);
         TextView keep = findViewById(R.id.keep);
+        TextView silent = findViewById(R.id.toggle_silent);
         View minimize = findViewById(R.id.minimize);
 
         findViewById(R.id.undo).setOnClickListener(mOnUndo);
         block.setOnClickListener(mOnStopOrMinimizeNotifications);
         keep.setOnClickListener(mOnKeepShowing);
+        silent.setOnClickListener(mOnToggleSilent);
         minimize.setOnClickListener(mOnStopOrMinimizeNotifications);
 
         if (mIsNonblockable) {
             keep.setText(android.R.string.ok);
             block.setVisibility(GONE);
+            silent.setVisibility(GONE);
             minimize.setVisibility(GONE);
         } else if (mIsForeground) {
             block.setVisibility(GONE);
+            silent.setVisibility(GONE);
             minimize.setVisibility(VISIBLE);
-        } else if (!mIsForeground) {
+        } else {
             block.setVisibility(VISIBLE);
+            boolean showToggleSilent = mIsNoisy
+                    && NotificationUtils.useNewInterruptionModel(mContext);
+            silent.setVisibility(showToggleSilent ? VISIBLE : GONE);
+            boolean isCurrentlyAlerting =
+                    mStartingChannelOrNotificationImportance >= IMPORTANCE_DEFAULT;
+            silent.setText(isCurrentlyAlerting
+                    ? R.string.inline_silent_button_silent
+                    : R.string.inline_silent_button_alert);
             minimize.setVisibility(GONE);
         }
 
@@ -368,7 +429,7 @@
         }
     }
 
-    private void swapContent(boolean showPrompt) {
+    private void swapContent(@NotificationInfoAction int action, boolean animate) {
         if (mExpandAnimation != null) {
             mExpandAnimation.cancel();
         }
@@ -378,47 +439,69 @@
         TextView confirmationText = findViewById(R.id.confirmation_text);
         View header = findViewById(R.id.header);
 
-        if (showPrompt) {
-            mChosenImportance = mStartingUserImportance;
-        } else if (mIsForeground) {
-            mChosenImportance = IMPORTANCE_MIN;
-            confirmationText.setText(R.string.notification_channel_minimized);
-        } else {
-            mChosenImportance = IMPORTANCE_NONE;
-            confirmationText.setText(R.string.notification_channel_disabled);
+        switch (action) {
+            case ACTION_UNDO:
+                mChosenImportance = mStartingChannelImportance;
+                break;
+            case ACTION_TOGGLE_SILENT:
+                mExitReason = NotificationCounters.BLOCKING_HELPER_TOGGLE_SILENT;
+                if (mStartingChannelOrNotificationImportance >= IMPORTANCE_DEFAULT) {
+                    mChosenImportance = IMPORTANCE_LOW;
+                    confirmationText.setText(R.string.notification_channel_silenced);
+                } else {
+                    mChosenImportance = IMPORTANCE_HIGH;
+                    confirmationText.setText(R.string.notification_channel_unsilenced);
+                }
+                break;
+            case ACTION_BLOCK:
+                mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
+                if (mIsForeground) {
+                    mChosenImportance = IMPORTANCE_MIN;
+                    confirmationText.setText(R.string.notification_channel_minimized);
+                } else {
+                    mChosenImportance = IMPORTANCE_NONE;
+                    confirmationText.setText(R.string.notification_channel_disabled);
+                }
+                break;
+            default:
+                throw new IllegalArgumentException();
         }
 
-        ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
-                prompt.getAlpha(), showPrompt ? 1f : 0f);
-        promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
-        ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
-                confirmation.getAlpha(), showPrompt ? 0f : 1f);
-        confirmAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
+        boolean isUndo = action == ACTION_UNDO;
 
-        prompt.setVisibility(showPrompt ? VISIBLE : GONE);
-        confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
-        header.setVisibility(showPrompt ? VISIBLE : GONE);
+        prompt.setVisibility(isUndo ? VISIBLE : GONE);
+        confirmation.setVisibility(isUndo ? GONE : VISIBLE);
+        header.setVisibility(isUndo ? VISIBLE : GONE);
 
-        mExpandAnimation = new AnimatorSet();
-        mExpandAnimation.playTogether(promptAnim, confirmAnim);
-        mExpandAnimation.setDuration(150);
-        mExpandAnimation.addListener(new AnimatorListenerAdapter() {
-            boolean cancelled = false;
+        if (animate) {
+            ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
+                    prompt.getAlpha(), isUndo ? 1f : 0f);
+            promptAnim.setInterpolator(isUndo ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+            ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
+                    confirmation.getAlpha(), isUndo ? 0f : 1f);
+            confirmAnim.setInterpolator(isUndo ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
 
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                cancelled = true;
-            }
+            mExpandAnimation = new AnimatorSet();
+            mExpandAnimation.playTogether(promptAnim, confirmAnim);
+            mExpandAnimation.setDuration(150);
+            mExpandAnimation.addListener(new AnimatorListenerAdapter() {
+                boolean mCancelled = false;
 
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                if (!cancelled) {
-                    prompt.setVisibility(showPrompt ? VISIBLE : GONE);
-                    confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    mCancelled = true;
                 }
-            }
-        });
-        mExpandAnimation.start();
+
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    if (!mCancelled) {
+                        prompt.setVisibility(isUndo ? VISIBLE : GONE);
+                        confirmation.setVisibility(isUndo ? GONE : VISIBLE);
+                    }
+                }
+            });
+            mExpandAnimation.start();
+        }
 
         // Since we're swapping/update the content, reset the timeout so the UI can't close
         // immediately after the update.
@@ -428,6 +511,25 @@
     }
 
     @Override
+    public void onFinishedClosing() {
+        mStartingChannelImportance = mChosenImportance;
+        if (mChosenImportance != IMPORTANCE_UNSPECIFIED) {
+            mStartingChannelOrNotificationImportance = mChosenImportance;
+        }
+        mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
+
+        View prompt = findViewById(R.id.prompt);
+        ViewGroup confirmation = findViewById(R.id.confirmation);
+        View header = findViewById(R.id.header);
+        prompt.setVisibility(VISIBLE);
+        prompt.setAlpha(1f);
+        confirmation.setVisibility(GONE);
+        confirmation.setAlpha(1f);
+        header.setVisibility(VISIBLE);
+        header.setAlpha(1f);
+    }
+
+    @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
         if (mGutsContainer != null &&
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index 7e60c4b..c16b28f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -16,22 +16,17 @@
 
 package com.android.systemui.statusbar.notification.row;
 
-import java.util.ArrayList;
-
 import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.AlphaOptimizedImageView;
-import com.android.systemui.statusbar.notification.row.NotificationGuts.GutsContent;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import static com.android.systemui.statusbar.notification.row.NotificationInfo.ACTION_BLOCK;
+import static com.android.systemui.statusbar.notification.row.NotificationInfo.ACTION_NONE;
+import static com.android.systemui.statusbar.notification.row.NotificationInfo.ACTION_TOGGLE_SILENT;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.annotation.Nullable;
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
@@ -45,6 +40,17 @@
 import android.widget.FrameLayout.LayoutParams;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.statusbar.AlphaOptimizedImageView;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.row.NotificationGuts.GutsContent;
+import com.android.systemui.statusbar.notification.row.NotificationInfo.NotificationInfoAction;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+
+import java.util.ArrayList;
+import java.util.List;
 
 public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnClickListener,
         ExpandableNotificationRow.LayoutListener {
@@ -67,10 +73,11 @@
 
     private Context mContext;
     private FrameLayout mMenuContainer;
-    private MenuItem mInfoItem;
+    private NotificationInfoMenuItem mInfoItem;
     private MenuItem mAppOpsItem;
     private MenuItem mSnoozeItem;
-    private ArrayList<MenuItem> mMenuItems;
+    private ArrayList<MenuItem> mLeftMenuItems;
+    private ArrayList<MenuItem> mRightMenuItems;
     private OnMenuEventListener mMenuListener;
 
     private ValueAnimator mFadeAnimator;
@@ -107,12 +114,13 @@
         mContext = context;
         mShouldShowMenu = context.getResources().getBoolean(R.bool.config_showNotificationGear);
         mHandler = new Handler(Looper.getMainLooper());
-        mMenuItems = new ArrayList<>();
+        mLeftMenuItems = new ArrayList<>();
+        mRightMenuItems = new ArrayList<>();
     }
 
     @Override
     public ArrayList<MenuItem> getMenuItems(Context context) {
-        return mMenuItems;
+        return mOnLeft ? mLeftMenuItems : mRightMenuItems;
     }
 
     @Override
@@ -168,7 +176,9 @@
     @Override
     public void createMenu(ViewGroup parent, StatusBarNotification sbn) {
         mParent = (ExpandableNotificationRow) parent;
-        createMenuViews(true /* resetState */);
+        createMenuViews(true /* resetState */,
+                sbn != null && (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE)
+                        != 0);
     }
 
     @Override
@@ -212,7 +222,8 @@
             // Menu hasn't been created yet, no need to do anything.
             return;
         }
-        createMenuViews(!isMenuVisible() /* resetState */);
+        createMenuViews(!isMenuVisible() /* resetState */,
+                (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0);
     }
 
     @Override
@@ -227,36 +238,49 @@
         mParent.removeListener();
     }
 
-    private void createMenuViews(boolean resetState) {
+    private void createMenuViews(boolean resetState, final boolean isForeground) {
         final Resources res = mContext.getResources();
         mHorizSpaceForIcon = res.getDimensionPixelSize(R.dimen.notification_menu_icon_size);
         mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
-        mMenuItems.clear();
+        mLeftMenuItems.clear();
+        mRightMenuItems.clear();
         // Construct the menu items based on the notification
-        if (mParent != null && mParent.getStatusBarNotification() != null) {
-            int flags = mParent.getStatusBarNotification().getNotification().flags;
-            boolean isForeground = (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
-            if (!isForeground) {
-                // Only show snooze for non-foreground notifications
-                mSnoozeItem = createSnoozeItem(mContext);
-                mMenuItems.add(mSnoozeItem);
-            }
+        if (!isForeground) {
+            // Only show snooze for non-foreground notifications
+            mSnoozeItem = createSnoozeItem(mContext);
+            mLeftMenuItems.add(mSnoozeItem);
         }
         mInfoItem = createInfoItem(mContext);
-        mMenuItems.add(mInfoItem);
+        if (!NotificationUtils.useNewInterruptionModel(mContext)) {
+            mLeftMenuItems.add(mInfoItem);
+        }
 
         mAppOpsItem = createAppOpsItem(mContext);
-        mMenuItems.add(mAppOpsItem);
+        mLeftMenuItems.add(mAppOpsItem);
 
-        // Construct the menu views
-        if (mMenuContainer != null) {
-            mMenuContainer.removeAllViews();
+        if (NotificationUtils.useNewInterruptionModel(mContext)) {
+            if (!mParent.getIsNonblockable()) {
+                mRightMenuItems.add(createBlockItem(mContext, mInfoItem.getGutsView()));
+            }
+            // TODO(kprevas): this is duplicated logic
+            // but it's currently spread across NotificationGutsManager and NotificationInfo.
+            // Try to consolidate and reuse here.
+            boolean canToggleSilent = !mParent.getIsNonblockable()
+                    && !isForeground
+                    && mParent.getEntry().noisy;
+            if (canToggleSilent) {
+                int channelImportance = mParent.getEntry().channel.getImportance();
+                int effectiveImportance =
+                        channelImportance == NotificationManager.IMPORTANCE_UNSPECIFIED
+                                ? mParent.getEntry().importance : channelImportance;
+                mRightMenuItems.add(createToggleSilentItem(mContext, mInfoItem.getGutsView(),
+                        effectiveImportance < NotificationManager.IMPORTANCE_DEFAULT));
+            }
         } else {
-            mMenuContainer = new FrameLayout(mContext);
+            mRightMenuItems.addAll(mLeftMenuItems);
         }
-        for (int i = 0; i < mMenuItems.size(); i++) {
-            addMenuView(mMenuItems.get(i), mMenuContainer);
-        }
+
+        populateMenuViews();
         if (resetState) {
             resetState(false /* notify */);
         } else {
@@ -268,6 +292,18 @@
         }
     }
 
+    private void populateMenuViews() {
+        if (mMenuContainer != null) {
+            mMenuContainer.removeAllViews();
+        } else {
+            mMenuContainer = new FrameLayout(mContext);
+        }
+        List<MenuItem> menuItems = mOnLeft ? mLeftMenuItems : mRightMenuItems;
+        for (int i = 0; i < menuItems.size(); i++) {
+            addMenuView(menuItems.get(i), mMenuContainer);
+        }
+    }
+
     private void resetState(boolean notify) {
         setMenuAlpha(0f);
         mIconsPlaced = false;
@@ -386,10 +422,16 @@
         if (appName == null) {
             return;
         }
+        setAppName(appName, mLeftMenuItems);
+        setAppName(appName, mRightMenuItems);
+    }
+
+    private void setAppName(String appName,
+            ArrayList<MenuItem> menuItems) {
         Resources res = mContext.getResources();
-        final int count = mMenuItems.size();
+        final int count = menuItems.size();
         for (int i = 0; i < count; i++) {
-            MenuItem item = mMenuItems.get(i);
+            MenuItem item = menuItems.get(i);
             String description = String.format(
                     res.getString(R.string.notification_menu_accessibility),
                     appName, item.getContentDescription());
@@ -402,7 +444,9 @@
 
     @Override
     public void onParentHeightUpdate() {
-        if (mParent == null || mMenuItems.size() == 0 || mMenuContainer == null) {
+        if (mParent == null
+                || (mLeftMenuItems.isEmpty() && mRightMenuItems.isEmpty())
+                || mMenuContainer == null) {
             return;
         }
         int parentHeight = mParent.getActualHeight();
@@ -443,13 +487,14 @@
         }
         v.getLocationOnScreen(mIconLocation);
         mParent.getLocationOnScreen(mParentLocation);
-        final int centerX = (int) (mHorizSpaceForIcon / 2);
+        final int centerX = mHorizSpaceForIcon / 2;
         final int centerY = v.getHeight() / 2;
         final int x = mIconLocation[0] - mParentLocation[0] + centerX;
         final int y = mIconLocation[1] - mParentLocation[1] + centerY;
         final int index = mMenuContainer.indexOfChild(v);
         if (mMenuListener != null) {
-            mMenuListener.onMenuClicked(mParent, x, y, mMenuItems.get(index));
+            mMenuListener.onMenuClicked(mParent, x, y,
+                    (mOnLeft ? mLeftMenuItems : mRightMenuItems).get(index));
         }
     }
 
@@ -469,6 +514,11 @@
             // Do nothing
             return;
         }
+        boolean wasOnLeft = mOnLeft;
+        mOnLeft = showOnLeft;
+        if (wasOnLeft != showOnLeft) {
+            populateMenuViews();
+        }
         final int count = mMenuContainer.getChildCount();
         for (int i = 0; i < count; i++) {
             final View v = mMenuContainer.getChildAt(i);
@@ -476,7 +526,6 @@
             final float right = mParent.getWidth() - (mHorizSpaceForIcon * (i + 1));
             v.setX(showOnLeft ? left : right);
         }
-        mOnLeft = showOnLeft;
         mIconsPlaced = true;
     }
 
@@ -572,7 +621,7 @@
         // TODO -- handle / allow custom menu items!
     }
 
-    public static MenuItem createSnoozeItem(Context context) {
+    static MenuItem createSnoozeItem(Context context) {
         Resources res = context.getResources();
         NotificationSnooze content = (NotificationSnooze) LayoutInflater.from(context)
                 .inflate(R.layout.notification_snooze, null, false);
@@ -582,17 +631,16 @@
         return snooze;
     }
 
-    public static MenuItem createInfoItem(Context context) {
+    static NotificationInfoMenuItem createInfoItem(Context context) {
         Resources res = context.getResources();
         String infoDescription = res.getString(R.string.notification_menu_gear_description);
         NotificationInfo infoContent = (NotificationInfo) LayoutInflater.from(context).inflate(
                 R.layout.notification_info, null, false);
-        MenuItem info = new NotificationMenuItem(context, infoDescription, infoContent,
-                R.drawable.ic_settings);
-        return info;
+        return new NotificationInfoMenuItem(context, infoDescription, infoContent,
+                R.drawable.ic_settings, ACTION_NONE);
     }
 
-    public static MenuItem createAppOpsItem(Context context) {
+    static MenuItem createAppOpsItem(Context context) {
         AppOpsInfo appOpsContent = (AppOpsInfo) LayoutInflater.from(context).inflate(
                 R.layout.app_ops_info, null, false);
         MenuItem info = new NotificationMenuItem(context, null, appOpsContent,
@@ -600,9 +648,33 @@
         return info;
     }
 
+    private static MenuItem createBlockItem(Context context, NotificationInfo gutsView) {
+        return new NotificationInfoMenuItem(
+                context,
+                context.getResources().getString(R.string.inline_stop_button),
+                gutsView,
+                R.drawable.ic_notification_block,
+                ACTION_BLOCK);
+    }
+
+    private static MenuItem createToggleSilentItem(Context context, NotificationInfo gutsView,
+            boolean isCurrentlySilent) {
+        return new NotificationInfoMenuItem(
+                context,
+                isCurrentlySilent
+                        ? context.getResources().getString(R.string.inline_silent_button_alert)
+                        : context.getResources().getString(R.string.inline_silent_button_silent),
+                gutsView,
+                isCurrentlySilent
+                        ? R.drawable.ic_notifications_alert
+                        : R.drawable.ic_notifications_silence,
+                ACTION_TOGGLE_SILENT);
+    }
+
     private void addMenuView(MenuItem item, ViewGroup parent) {
         View menuView = item.getMenuView();
         if (menuView != null) {
+            menuView.setAlpha(mAlpha);
             parent.addView(menuView);
             menuView.setOnClickListener(this);
             FrameLayout.LayoutParams lp = (LayoutParams) menuView.getLayoutParams();
@@ -680,7 +752,8 @@
          * Add a new 'guts' panel. If iconResId < 0 it will not appear in the slow swipe menu
          * but can still be exposed via other affordances.
          */
-        public NotificationMenuItem(Context context, String s, GutsContent content, int iconResId) {
+        public NotificationMenuItem(Context context, String contentDescription, GutsContent content,
+                int iconResId) {
             Resources res = context.getResources();
             int padding = res.getDimensionPixelSize(R.dimen.notification_menu_icon_padding);
             int tint = res.getColor(R.color.notification_gear_color);
@@ -693,7 +766,7 @@
                 iv.setAlpha(1f);
                 mMenuView = iv;
             }
-            mContentDescription = s;
+            mContentDescription = contentDescription;
             mGutsContent = content;
         }
 
@@ -713,4 +786,23 @@
             return mContentDescription;
         }
     }
+
+    /** A {@link NotificationMenuItem} with an associated {@link NotificationInfoAction}. */
+    public static class NotificationInfoMenuItem extends NotificationMenuItem {
+
+        @NotificationInfoAction
+        int mAction;
+
+        public NotificationInfoMenuItem(Context context, String contentDescription,
+                NotificationInfo content, int iconResId,
+                @NotificationInfoAction int action) {
+            super(context, contentDescription, content, iconResId);
+            this.mAction = action;
+        }
+
+        @Override
+        public NotificationInfo getGutsView() {
+            return (NotificationInfo) super.getGutsView();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
index 75b05c2..d65f2c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
@@ -16,16 +16,6 @@
 
 package com.android.systemui.statusbar.notification.row;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -53,8 +43,17 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 public class NotificationSnooze extends LinearLayout
         implements NotificationGuts.GutsContent, View.OnClickListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
index a21794b..1741a0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
@@ -17,11 +17,12 @@
 package com.android.systemui.statusbar.notification.row;
 
 import android.content.Context;
-import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
+
 import com.android.systemui.R;
 import com.android.systemui.statusbar.InflationTask;
 import com.android.systemui.statusbar.notification.NotificationData;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
index 8a061a6..1b40c06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
@@ -24,7 +24,6 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Interpolators;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
 
 /**
  * A common base class for all views in the notification stack scroller which don't have a
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
index 133df3c..4261df3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
@@ -21,8 +21,8 @@
 import android.view.View;
 
 import com.android.internal.widget.ImageFloatingTextView;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
  * Wraps a notification containing a big text template
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 6ca07ed..1be2afe7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -16,9 +16,9 @@
 
 package com.android.systemui.statusbar.notification.row.wrapper;
 
+import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
 import static com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
         .DEFAULT_HEADER_VISIBLE_AMOUNT;
-import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
 
 import android.app.Notification;
 import android.content.Context;
@@ -34,12 +34,13 @@
 import com.android.internal.widget.NotificationExpandButton;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.CustomInterpolatorTransformation;
-import com.android.systemui.statusbar.notification.ImageTransformState;
-import com.android.systemui.statusbar.notification.TransformState;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.ViewTransformationHelper;
+import com.android.systemui.statusbar.notification.CustomInterpolatorTransformation;
+import com.android.systemui.statusbar.notification.ImageTransformState;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.TransformState;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 import java.util.Stack;
 
@@ -69,7 +70,8 @@
     protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
         super(ctx, view, row);
         mShowExpandButtonAtEnd = ctx.getResources().getBoolean(
-                R.bool.config_showNotificationExpandButtonAtEnd);
+                R.bool.config_showNotificationExpandButtonAtEnd)
+                || NotificationUtils.useNewInterruptionModel(ctx);
         mTransformationHelper = new ViewTransformationHelper();
 
         // we want to avoid that the header clashes with the other text when transforming
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 37d2f6b..5a9a568 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -19,8 +19,8 @@
 import android.content.Context;
 import android.view.View;
 
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
  * Wraps a notification containing a media template
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
index 13c5960..c9a2742 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
@@ -16,15 +16,15 @@
 
 package com.android.systemui.statusbar.notification.row.wrapper;
 
+import android.content.Context;
+import android.view.View;
+
 import com.android.internal.widget.MessagingLayout;
 import com.android.internal.widget.MessagingLinearLayout;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
-import android.content.Context;
-import android.view.View;
-
 /**
  * Wraps a notification containing a messaging template
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index d934902..ff5e15b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -37,11 +37,11 @@
 import com.android.systemui.R;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.ViewTransformationHelper;
 import com.android.systemui.statusbar.notification.ImageTransformState;
 import com.android.systemui.statusbar.notification.TransformState;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
-import com.android.systemui.statusbar.ViewTransformationHelper;
 import com.android.systemui.statusbar.notification.row.HybridNotificationView;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index f76284d..1efdc56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -24,9 +24,9 @@
 import android.view.View;
 
 import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.notification.TransformState;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
 
 /**
  * Wraps the actual notification content view; used to implement behaviors which are different for
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index 0577841..ff1a6fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -22,27 +22,32 @@
 
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.AmbientPulseManager;
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.NotificationShelf;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * A global state to track all input states for the algorithm.
  */
 public class AmbientState {
-    private ArrayList<View> mDraggedViews = new ArrayList<View>();
+
+    private static final int NO_SECTION_BOUNDARY = -1;
+
+    private ArrayList<View> mDraggedViews = new ArrayList<>();
     private int mScrollY;
     private boolean mDimmed;
     private ActivatableNotificationView mActivatedChild;
     private float mOverScrollTopAmount;
     private float mOverScrollBottomAmount;
     private int mSpeedBumpIndex = -1;
+    private final List<Integer> mSectionBoundaryIndices = new ArrayList<>();
     private boolean mDark;
     private boolean mHideSensitive;
     private AmbientPulseManager mAmbientPulseManager = Dependency.get(AmbientPulseManager.class);
@@ -75,6 +80,7 @@
     private boolean mAppearing;
 
     public AmbientState(Context context) {
+        mSectionBoundaryIndices.add(NO_SECTION_BOUNDARY);
         reload(context);
     }
 
@@ -208,6 +214,27 @@
         mSpeedBumpIndex = shelfIndex;
     }
 
+    /**
+     * Returns the index of the boundary between two sections, where the first section is at index
+     * {@code boundaryNum}.
+     */
+    public int getSectionBoundaryIndex(int boundaryNum) {
+        return mSectionBoundaryIndices.get(boundaryNum);
+    }
+
+    /** Returns true if the item at {@code index} is directly below a section boundary. */
+    public boolean beginsNewSection(int index) {
+        return mSectionBoundaryIndices.contains(index);
+    }
+
+    /**
+     * Sets the index of the boundary between the section at {@code boundaryNum} and the following
+     * section to {@code boundaryIndex}.
+     */
+    public void setSectionBoundaryIndex(int boundaryNum, int boundaryIndex) {
+        mSectionBoundaryIndices.set(boundaryNum, boundaryIndex);
+    }
+
     public float getStackTranslation() {
         return mStackTranslation;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
index c6f953c..ba56a94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
@@ -16,10 +16,11 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
-import androidx.collection.ArraySet;
 import android.util.Property;
 import android.view.View;
 
+import androidx.collection.ArraySet;
+
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index da089b3..74b4aa2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -33,13 +33,13 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationHeaderUtil;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.HybridGroupManager;
 import com.android.systemui.statusbar.notification.row.HybridNotificationView;
-import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
index cfb6d99..4d100a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
@@ -16,17 +16,18 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
-import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
+import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
+        .ExpandAnimationParameters;
 
 import android.view.View;
 import android.view.ViewGroup;
 
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 
 /**
  * Interface representing the entity that contains notifications. It can have
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
index e32df42..c867a41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
+        .NUM_SECTIONS;
+
 import android.view.View;
 
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -30,46 +33,92 @@
 class NotificationRoundnessManager implements OnHeadsUpChangedListener {
 
     private boolean mExpanded;
-    private ActivatableNotificationView mFirst;
-    private ActivatableNotificationView mLast;
+    private ActivatableNotificationView[] mFirstInSectionViews;
+    private ActivatableNotificationView[] mLastInSectionViews;
+    private ActivatableNotificationView[] mTmpFirstInSectionViews;
+    private ActivatableNotificationView[] mTmpLastInSectionViews;
     private HashSet<View> mAnimatedChildren;
     private Runnable mRoundingChangedCallback;
     private ExpandableNotificationRow mTrackedHeadsUp;
     private float mAppearFraction;
 
+    NotificationRoundnessManager() {
+        mFirstInSectionViews = new ActivatableNotificationView[NUM_SECTIONS];
+        mLastInSectionViews = new ActivatableNotificationView[NUM_SECTIONS];
+        mTmpFirstInSectionViews = new ActivatableNotificationView[NUM_SECTIONS];
+        mTmpLastInSectionViews = new ActivatableNotificationView[NUM_SECTIONS];
+    }
+
     @Override
     public void onHeadsUpPinned(ExpandableNotificationRow headsUp) {
-        updateRounding(headsUp, false /* animate */);
+        updateView(headsUp, false /* animate */);
     }
 
     @Override
     public void onHeadsUpUnPinned(ExpandableNotificationRow headsUp) {
-        updateRounding(headsUp, true /* animate */);
+        updateView(headsUp, true /* animate */);
     }
 
     public void onHeadsupAnimatingAwayChanged(ExpandableNotificationRow row,
             boolean isAnimatingAway) {
-        updateRounding(row, false /* animate */);
+        updateView(row, false /* animate */);
     }
 
-    private void updateRounding(ActivatableNotificationView view, boolean animate) {
-        float topRoundness = getRoundness(view, true /* top */);
-        float bottomRoundness = getRoundness(view, false /* top */);
-        boolean firstChanged = view.setTopRoundness(topRoundness, animate);
-        boolean secondChanged = view.setBottomRoundness(bottomRoundness, animate);
-        if ((view == mFirst || view == mLast) && (firstChanged || secondChanged)) {
+    private void updateView(ActivatableNotificationView view, boolean animate) {
+        boolean changed = updateViewWithoutCallback(view, animate);
+        if (changed) {
             mRoundingChangedCallback.run();
         }
     }
 
+    private boolean updateViewWithoutCallback(ActivatableNotificationView view,
+            boolean animate) {
+        float topRoundness = getRoundness(view, true /* top */);
+        float bottomRoundness = getRoundness(view, false /* top */);
+        boolean topChanged = view.setTopRoundness(topRoundness, animate);
+        boolean bottomChanged = view.setBottomRoundness(bottomRoundness, animate);
+        boolean firstInSection = isFirstInSection(view, false /* exclude first section */);
+        boolean lastInSection = isLastInSection(view, false /* exclude last section */);
+        view.setFirstInSection(firstInSection);
+        view.setLastInSection(lastInSection);
+        return (firstInSection || lastInSection) && (topChanged || bottomChanged);
+    }
+
+    private boolean isFirstInSection(ActivatableNotificationView view,
+            boolean includeFirstSection) {
+        int numNonEmptySections = 0;
+        for (int i = 0; i < mFirstInSectionViews.length; i++) {
+            if (view == mFirstInSectionViews[i]) {
+                return includeFirstSection || numNonEmptySections > 0;
+            }
+            if (mFirstInSectionViews[i] != null) {
+                numNonEmptySections++;
+            }
+        }
+        return false;
+    }
+
+    private boolean isLastInSection(ActivatableNotificationView view, boolean includeLastSection) {
+        int numNonEmptySections = 0;
+        for (int i = mLastInSectionViews.length - 1; i >= 0; i--) {
+            if (view == mLastInSectionViews[i]) {
+                return includeLastSection || numNonEmptySections > 0;
+            }
+            if (mLastInSectionViews[i] != null) {
+                numNonEmptySections++;
+            }
+        }
+        return false;
+    }
+
     private float getRoundness(ActivatableNotificationView view, boolean top) {
         if ((view.isPinned() || view.isHeadsUpAnimatingAway()) && !mExpanded) {
             return 1.0f;
         }
-        if (view == mFirst && top) {
+        if (isFirstInSection(view, true /* include first section */) && top) {
             return 1.0f;
         }
-        if (view == mLast && !top) {
+        if (isLastInSection(view, true /* include last section */) && !top) {
             return 1.0f;
         }
         if (view == mTrackedHeadsUp && mAppearFraction <= 0.0f) {
@@ -84,34 +133,82 @@
         mExpanded = expandedHeight != 0.0f;
         mAppearFraction = appearFraction;
         if (mTrackedHeadsUp != null) {
-            updateRounding(mTrackedHeadsUp, true);
+            updateView(mTrackedHeadsUp, true);
         }
     }
 
-    public void setFirstAndLastBackgroundChild(ActivatableNotificationView first,
-            ActivatableNotificationView last) {
-        boolean firstChanged = mFirst != first;
-        boolean lastChanged = mLast != last;
-        if (!firstChanged && !lastChanged) {
-            return;
+    public void updateRoundedChildren(NotificationSection[] sections) {
+        boolean anyChanged = false;
+        for (int i = 0; i < NUM_SECTIONS; i++) {
+            mTmpFirstInSectionViews[i] = mFirstInSectionViews[i];
+            mTmpLastInSectionViews[i] = mLastInSectionViews[i];
+            mFirstInSectionViews[i] = sections[i].getFirstVisibleChild();
+            mLastInSectionViews[i] = sections[i].getLastVisibleChild();
         }
-        ActivatableNotificationView oldFirst = mFirst;
-        ActivatableNotificationView oldLast = mLast;
-        mFirst = first;
-        mLast = last;
-        if (firstChanged && oldFirst != null && !oldFirst.isRemoved()) {
-            updateRounding(oldFirst, oldFirst.isShown());
+        anyChanged |= handleRemovedOldViews(sections, mTmpFirstInSectionViews, true);
+        anyChanged |= handleRemovedOldViews(sections, mTmpLastInSectionViews, false);
+        anyChanged |= handleAddedNewViews(sections, mTmpFirstInSectionViews, true);
+        anyChanged |= handleAddedNewViews(sections, mTmpLastInSectionViews, false);
+        if (anyChanged) {
+            mRoundingChangedCallback.run();
         }
-        if (lastChanged && oldLast != null && !oldLast.isRemoved()) {
-            updateRounding(oldLast, oldLast.isShown());
+    }
+
+    private boolean handleRemovedOldViews(NotificationSection[] sections,
+            ActivatableNotificationView[] oldViews, boolean first) {
+        boolean anyChanged = false;
+        for (ActivatableNotificationView oldView : oldViews) {
+            if (oldView != null) {
+                boolean isStillPresent = false;
+                boolean adjacentSectionChanged = false;
+                for (NotificationSection section : sections) {
+                    ActivatableNotificationView newView =
+                            (first ? section.getFirstVisibleChild()
+                                    : section.getLastVisibleChild());
+                    if (newView == oldView) {
+                        isStillPresent = true;
+                        if (oldView.isFirstInSection() != isFirstInSection(oldView,
+                                false /* exclude first section */)
+                                || oldView.isLastInSection() != isLastInSection(oldView,
+                                false /* exclude last section */)) {
+                            adjacentSectionChanged = true;
+                        }
+                        break;
+                    }
+                }
+                if (!isStillPresent || adjacentSectionChanged) {
+                    anyChanged = true;
+                    if (!oldView.isRemoved()) {
+                        updateViewWithoutCallback(oldView, oldView.isShown());
+                    }
+                }
+            }
         }
-        if (mFirst != null) {
-            updateRounding(mFirst, mFirst.isShown() && !mAnimatedChildren.contains(mFirst));
+        return anyChanged;
+    }
+
+    private boolean handleAddedNewViews(NotificationSection[] sections,
+            ActivatableNotificationView[] oldViews, boolean first) {
+        boolean anyChanged = false;
+        for (NotificationSection section : sections) {
+            ActivatableNotificationView newView =
+                    (first ? section.getFirstVisibleChild() : section.getLastVisibleChild());
+            if (newView != null) {
+                boolean wasAlreadyPresent = false;
+                for (ActivatableNotificationView oldView : oldViews) {
+                    if (oldView == newView) {
+                        wasAlreadyPresent = true;
+                        break;
+                    }
+                }
+                if (!wasAlreadyPresent) {
+                    anyChanged = true;
+                    updateViewWithoutCallback(newView,
+                            newView.isShown() && !mAnimatedChildren.contains(newView));
+                }
+            }
         }
-        if (mLast != null) {
-            updateRounding(mLast, mLast.isShown() && !mAnimatedChildren.contains(mLast));
-        }
-        mRoundingChangedCallback.run();
+        return anyChanged;
     }
 
     public void setAnimatedChildren(HashSet<View> animatedChildren) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
new file mode 100644
index 0000000..40cfd4d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.statusbar.notification.ShadeViewRefactor;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+
+/**
+ * Represents the bounds of a section of the notification shade and handles animation when the
+ * bounds change.
+ */
+class NotificationSection {
+    private View mOwningView;
+    private Rect mBounds = new Rect();
+    private Rect mCurrentBounds = new Rect(-1, -1, -1, -1);
+    private Rect mStartAnimationRect = new Rect();
+    private Rect mEndAnimationRect = new Rect();
+    private ObjectAnimator mTopAnimator = null;
+    private ObjectAnimator mBottomAnimator = null;
+    private ActivatableNotificationView mFirstVisibleChild;
+    private ActivatableNotificationView mLastVisibleChild;
+
+    NotificationSection(View owningView) {
+        mOwningView = owningView;
+    }
+
+    public void cancelAnimators() {
+        if (mBottomAnimator != null) {
+            mBottomAnimator.cancel();
+        }
+        if (mTopAnimator != null) {
+            mTopAnimator.cancel();
+        }
+    }
+
+    public Rect getCurrentBounds() {
+        return mCurrentBounds;
+    }
+
+    public Rect getBounds() {
+        return mBounds;
+    }
+
+    public boolean didBoundsChange() {
+        return !mCurrentBounds.equals(mBounds);
+    }
+
+    public boolean areBoundsAnimating() {
+        return mBottomAnimator != null || mTopAnimator != null;
+    }
+
+    public void startBackgroundAnimation(boolean animateTop, boolean animateBottom) {
+        // Left and right bounds are always applied immediately.
+        mCurrentBounds.left = mBounds.left;
+        mCurrentBounds.right = mBounds.right;
+        startBottomAnimation(animateBottom);
+        startTopAnimation(animateTop);
+    }
+
+
+    @ShadeViewRefactor(ShadeViewRefactor.RefactorComponent.STATE_RESOLVER)
+    private void startTopAnimation(boolean animate) {
+        int previousEndValue = mEndAnimationRect.top;
+        int newEndValue = mBounds.top;
+        ObjectAnimator previousAnimator = mTopAnimator;
+        if (previousAnimator != null && previousEndValue == newEndValue) {
+            return;
+        }
+        if (!animate) {
+            // just a local update was performed
+            if (previousAnimator != null) {
+                // we need to increase all animation keyframes of the previous animator by the
+                // relative change to the end value
+                int previousStartValue = mStartAnimationRect.top;
+                PropertyValuesHolder[] values = previousAnimator.getValues();
+                values[0].setIntValues(previousStartValue, newEndValue);
+                mStartAnimationRect.top = previousStartValue;
+                mEndAnimationRect.top = newEndValue;
+                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+                return;
+            } else {
+                // no new animation needed, let's just apply the value
+                setBackgroundTop(newEndValue);
+                return;
+            }
+        }
+        if (previousAnimator != null) {
+            previousAnimator.cancel();
+        }
+        ObjectAnimator animator = ObjectAnimator.ofInt(this, "backgroundTop",
+                mCurrentBounds.top, newEndValue);
+        Interpolator interpolator = Interpolators.FAST_OUT_SLOW_IN;
+        animator.setInterpolator(interpolator);
+        animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+        // remove the tag when the animation is finished
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mStartAnimationRect.top = -1;
+                mEndAnimationRect.top = -1;
+                mTopAnimator = null;
+            }
+        });
+        animator.start();
+        mStartAnimationRect.top = mCurrentBounds.top;
+        mEndAnimationRect.top = newEndValue;
+        mTopAnimator = animator;
+    }
+
+    @ShadeViewRefactor(ShadeViewRefactor.RefactorComponent.STATE_RESOLVER)
+    private void startBottomAnimation(boolean animate) {
+        int previousStartValue = mStartAnimationRect.bottom;
+        int previousEndValue = mEndAnimationRect.bottom;
+        int newEndValue = mBounds.bottom;
+        ObjectAnimator previousAnimator = mBottomAnimator;
+        if (previousAnimator != null && previousEndValue == newEndValue) {
+            return;
+        }
+        if (!animate) {
+            // just a local update was performed
+            if (previousAnimator != null) {
+                // we need to increase all animation keyframes of the previous animator by the
+                // relative change to the end value
+                PropertyValuesHolder[] values = previousAnimator.getValues();
+                values[0].setIntValues(previousStartValue, newEndValue);
+                mStartAnimationRect.bottom = previousStartValue;
+                mEndAnimationRect.bottom = newEndValue;
+                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
+                return;
+            } else {
+                // no new animation needed, let's just apply the value
+                setBackgroundBottom(newEndValue);
+                return;
+            }
+        }
+        if (previousAnimator != null) {
+            previousAnimator.cancel();
+        }
+        ObjectAnimator animator = ObjectAnimator.ofInt(this, "backgroundBottom",
+                mCurrentBounds.bottom, newEndValue);
+        Interpolator interpolator = Interpolators.FAST_OUT_SLOW_IN;
+        animator.setInterpolator(interpolator);
+        animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+        // remove the tag when the animation is finished
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mStartAnimationRect.bottom = -1;
+                mEndAnimationRect.bottom = -1;
+                mBottomAnimator = null;
+            }
+        });
+        animator.start();
+        mStartAnimationRect.bottom = mCurrentBounds.bottom;
+        mEndAnimationRect.bottom = newEndValue;
+        mBottomAnimator = animator;
+    }
+
+    @ShadeViewRefactor(ShadeViewRefactor.RefactorComponent.SHADE_VIEW)
+    private void setBackgroundTop(int top) {
+        mCurrentBounds.top = top;
+        mOwningView.invalidate();
+    }
+
+    @ShadeViewRefactor(ShadeViewRefactor.RefactorComponent.SHADE_VIEW)
+    private void setBackgroundBottom(int bottom) {
+        mCurrentBounds.bottom = bottom;
+        mOwningView.invalidate();
+    }
+
+    public ActivatableNotificationView getFirstVisibleChild() {
+        return mFirstVisibleChild;
+    }
+
+    public ActivatableNotificationView getLastVisibleChild() {
+        return mLastVisibleChild;
+    }
+
+    public void setFirstVisibleChild(ActivatableNotificationView child) {
+        mFirstVisibleChild = child;
+    }
+
+    public void setLastVisibleChild(ActivatableNotificationView child) {
+        mLastVisibleChild = child;
+    }
+
+    public void resetCurrentBounds() {
+        mCurrentBounds.set(mBounds);
+    }
+
+    /**
+     * Returns true if {@code top} is equal to the top of this section (if not currently animating)
+     * or where the top of this section will be when animation completes.
+     */
+    public boolean isTargetTop(int top) {
+        return (mTopAnimator == null && mCurrentBounds.top == top)
+                || (mTopAnimator != null && mEndAnimationRect.top == top);
+    }
+
+    /**
+     * Returns true if {@code bottom} is equal to the bottom of this section (if not currently
+     * animating) or where the bottom of this section will be when animation completes.
+     */
+    public boolean isTargetBottom(int bottom) {
+        return (mBottomAnimator == null && mCurrentBounds.bottom == bottom)
+                || (mBottomAnimator != null && mEndAnimationRect.bottom == bottom);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 003f158d..ff31b26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -22,13 +22,10 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
 import android.animation.TimeAnimator;
 import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.NotificationManager;
 import android.app.WallpaperManager;
 import android.content.Context;
 import android.content.Intent;
@@ -155,6 +152,12 @@
      * Sentinel value for no current active pointer. Used by {@link #mActivePointerId}.
      */
     private static final int INVALID_POINTER = -1;
+    static final int NUM_SECTIONS = 2;
+    /**
+     * The distance in pixels between sections when the sections are directly adjacent (no visible
+     * gap is drawn between them). In this case we don't want to round their corners.
+     */
+    private static final int DISTANCE_BETWEEN_ADJACENT_SECTIONS_PX = 1;
 
     private ExpandHelper mExpandHelper;
     private final NotificationSwipeHelper mSwipeHelper;
@@ -328,16 +331,10 @@
             return true;
         }
     };
-    private Rect mBackgroundBounds = new Rect();
-    private Rect mStartAnimationRect = new Rect();
-    private Rect mEndAnimationRect = new Rect();
-    private Rect mCurrentBounds = new Rect(-1, -1, -1, -1);
-    private boolean mAnimateNextBackgroundBottom;
+    private NotificationSection[] mSections = new NotificationSection[NUM_SECTIONS];
     private boolean mAnimateNextBackgroundTop;
-    private ObjectAnimator mBottomAnimator = null;
-    private ObjectAnimator mTopAnimator = null;
-    private ActivatableNotificationView mFirstVisibleBackgroundChild = null;
-    private ActivatableNotificationView mLastVisibleBackgroundChild = null;
+    private boolean mAnimateNextBackgroundBottom;
+    private boolean mAnimateNextSectionBoundsChange;
     private int mBgColor;
     private float mDimAmount;
     private ValueAnimator mDimAnimator;
@@ -404,6 +401,8 @@
      */
     private float mBackgroundXFactor = 1f;
 
+    private boolean mSwipingInProgress;
+
     private boolean mUsingLightTheme;
     private boolean mQsExpanded;
     private boolean mForwardScrollable;
@@ -480,6 +479,10 @@
         super(context, attrs, defStyleAttr, defStyleRes);
         Resources res = getResources();
 
+        for (int i = 0; i < NUM_SECTIONS; i++) {
+            mSections[i] = new NotificationSection(this);
+        }
+
         mAmbientState = new AmbientState(context);
         mBgColor = context.getColor(R.color.notification_shade_background_color);
         int minHeight = res.getDimensionPixelSize(R.dimen.notification_min_height);
@@ -656,7 +659,9 @@
     @ShadeViewRefactor(RefactorComponent.DECORATOR)
     protected void onDraw(Canvas canvas) {
         if (mShouldDrawNotificationBackground
-                && (mCurrentBounds.top < mCurrentBounds.bottom || mAmbientState.isDark())) {
+                && (mSections[0].getCurrentBounds().top
+                < mSections[NUM_SECTIONS - 1].getCurrentBounds().bottom
+                || mAmbientState.isDark())) {
             drawBackground(canvas);
         }
 
@@ -674,8 +679,8 @@
     private void drawBackground(Canvas canvas) {
         int lockScreenLeft = mSidePaddings;
         int lockScreenRight = getWidth() - mSidePaddings;
-        int lockScreenTop = mCurrentBounds.top;
-        int lockScreenBottom = mCurrentBounds.bottom;
+        int lockScreenTop = mSections[0].getCurrentBounds().top;
+        int lockScreenBottom = mSections[NUM_SECTIONS - 1].getCurrentBounds().bottom;
         int darkLeft = getWidth() / 2;
         int darkTop = mRegularTopPadding;
 
@@ -683,21 +688,79 @@
         float xProgress = mDarkXInterpolator.getInterpolation(
                 (1 - mLinearDarkAmount) * mBackgroundXFactor);
 
+        int left = (int) MathUtils.lerp(darkLeft, lockScreenLeft, xProgress);
+        int right = (int) MathUtils.lerp(darkLeft, lockScreenRight, xProgress);
+        int top = (int) MathUtils.lerp(darkTop, lockScreenTop, yProgress);
+        int bottom = (int) MathUtils.lerp(darkTop, lockScreenBottom, yProgress);
         mBackgroundAnimationRect.set(
-                (int) MathUtils.lerp(darkLeft, lockScreenLeft, xProgress),
-                (int) MathUtils.lerp(darkTop, lockScreenTop, yProgress),
-                (int) MathUtils.lerp(darkLeft, lockScreenRight, xProgress),
-                (int) MathUtils.lerp(darkTop, lockScreenBottom, yProgress));
+                left,
+                top,
+                right,
+                bottom);
 
-        if (!mAmbientState.isDark() || mFirstVisibleBackgroundChild != null) {
-            canvas.drawRoundRect(mBackgroundAnimationRect.left, mBackgroundAnimationRect.top,
-                    mBackgroundAnimationRect.right, mBackgroundAnimationRect.bottom,
-                    mCornerRadius, mCornerRadius, mBackgroundPaint);
+        int backgroundTopAnimationOffset = top - lockScreenTop;
+        // TODO(kprevas): this may not be necessary any more since we don't display the shelf in AOD
+        boolean anySectionHasVisibleChild = false;
+        for (NotificationSection section : mSections) {
+            if (section.getFirstVisibleChild() != null) {
+                anySectionHasVisibleChild = true;
+                break;
+            }
+        }
+        if (!mAmbientState.isDark() || anySectionHasVisibleChild) {
+            drawBackgroundRects(canvas, left, right, top, backgroundTopAnimationOffset);
         }
 
         updateClipping();
     }
 
+    /**
+     * Draws round rects for each background section.
+     *
+     * We want to draw a round rect for each background section as defined by {@link #mSections}.
+     * However, if two sections are directly adjacent with no gap between them (e.g. on the
+     * lockscreen where the shelf can appear directly below the high priority section, or while
+     * scrolling the shade so that the top of the shelf is right at the bottom of the high priority
+     * section), we don't want to round the adjacent corners.
+     *
+     * Since {@link Canvas} doesn't provide a way to draw a half-rounded rect, this means that we
+     * need to coalesce the backgrounds for adjacent sections and draw them as a single round rect.
+     * This method tracks the top of each rect we need to draw, then iterates through the visible
+     * sections.  If a section is not adjacent to the previous section, we draw the previous rect
+     * behind the sections we've accumulated up to that point, then start a new rect at the top of
+     * the current section.  When we're done iterating we will always have one rect left to draw.
+     */
+    private void drawBackgroundRects(Canvas canvas, int left, int right, int top,
+            int animationYOffset) {
+        int backgroundRectTop = top;
+        int lastSectionBottom =
+                mSections[0].getCurrentBounds().bottom + animationYOffset;
+        for (NotificationSection section : mSections) {
+            if (section.getFirstVisibleChild() == null) {
+                continue;
+            }
+            int sectionTop = section.getCurrentBounds().top + animationYOffset;
+            // If sections are directly adjacent to each other, we don't want to draw them
+            // as separate roundrects, as the rounded corners right next to each other look
+            // bad.
+            if (sectionTop - lastSectionBottom > DISTANCE_BETWEEN_ADJACENT_SECTIONS_PX) {
+                canvas.drawRoundRect(left,
+                        backgroundRectTop,
+                        right,
+                        lastSectionBottom,
+                        mCornerRadius, mCornerRadius, mBackgroundPaint);
+                backgroundRectTop = sectionTop;
+            }
+            lastSectionBottom =
+                    section.getCurrentBounds().bottom + animationYOffset;
+        }
+        canvas.drawRoundRect(left,
+                backgroundRectTop,
+                right,
+                lastSectionBottom,
+                mCornerRadius, mCornerRadius, mBackgroundPaint);
+    }
+
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void updateBackgroundDimming() {
         // No need to update the background color if it's not being drawn.
@@ -1067,7 +1130,8 @@
                 translationY = height - appearStartPosition + getExpandTranslationStart();
             }
             if (isHeadsUpTransition()) {
-                stackHeight = mFirstVisibleBackgroundChild.getPinnedHeadsUpHeight();
+                stackHeight =
+                        getFirstVisibleSection().getFirstVisibleChild().getPinnedHeadsUpHeight();
                 translationY = MathUtils.lerp(mHeadsUpInset - mTopPadding, 0, appearFraction);
             } else {
                 stackHeight = (int) (height - translationY);
@@ -1107,7 +1171,9 @@
             mIsClipped = clipped;
         }
 
-        if (mAmbientState.isDarkAtAll()) {
+        if (mPulsing) {
+            setClipBounds(null);
+        } else if (mAmbientState.isDarkAtAll()) {
             setClipBounds(mBackgroundAnimationRect);
         } else if (clipped) {
             setClipBounds(mRequestedClipBounds);
@@ -1122,7 +1188,7 @@
      */
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private float getExpandTranslationStart() {
-        return -mTopPadding + getMinExpansionHeight();
+        return -mTopPadding + getMinExpansionHeight() - mShelf.getIntrinsicHeight();
     }
 
     /**
@@ -1132,7 +1198,8 @@
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private float getAppearStartPosition() {
         if (isHeadsUpTransition()) {
-            return mHeadsUpInset + mFirstVisibleBackgroundChild.getPinnedHeadsUpHeight();
+            return mHeadsUpInset
+                    + getFirstVisibleSection().getFirstVisibleChild().getPinnedHeadsUpHeight();
         }
         return getMinExpansionHeight();
     }
@@ -1185,8 +1252,9 @@
 
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private boolean isHeadsUpTransition() {
-        return mTrackingHeadsUp && mFirstVisibleBackgroundChild != null
-                && mAmbientState.isAboveShelf(mFirstVisibleBackgroundChild);
+        NotificationSection firstVisibleSection = getFirstVisibleSection();
+        return mTrackingHeadsUp && firstVisibleSection != null
+                && mAmbientState.isAboveShelf(firstVisibleSection.getFirstVisibleChild());
     }
 
     /**
@@ -2011,9 +2079,9 @@
         }
 
         updateBackgroundBounds();
-        if (!mCurrentBounds.equals(mBackgroundBounds)) {
-            boolean animate = mAnimateNextBackgroundTop || mAnimateNextBackgroundBottom
-                    || areBoundsAnimating();
+        if (didSectionBoundsChange()) {
+            boolean animate = mAnimateNextSectionBoundsChange || mAnimateNextBackgroundTop
+                    || mAnimateNextBackgroundBottom || areSectionBoundsAnimating();
             if (!isExpanded()) {
                 abortBackgroundAnimators();
                 animate = false;
@@ -2021,148 +2089,60 @@
             if (animate) {
                 startBackgroundAnimation();
             } else {
-                mCurrentBounds.set(mBackgroundBounds);
+                for (NotificationSection section : mSections) {
+                    section.resetCurrentBounds();
+                }
                 invalidate();
             }
         } else {
             abortBackgroundAnimators();
         }
-        mAnimateNextBackgroundBottom = false;
         mAnimateNextBackgroundTop = false;
+        mAnimateNextBackgroundBottom = false;
+        mAnimateNextSectionBoundsChange = false;
     }
 
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void abortBackgroundAnimators() {
-        if (mBottomAnimator != null) {
-            mBottomAnimator.cancel();
-        }
-        if (mTopAnimator != null) {
-            mTopAnimator.cancel();
+        for (NotificationSection section : mSections) {
+            section.cancelAnimators();
         }
     }
 
+    private boolean didSectionBoundsChange() {
+        for (NotificationSection section : mSections) {
+            if (section.didBoundsChange()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
-    private boolean areBoundsAnimating() {
-        return mBottomAnimator != null || mTopAnimator != null;
+    private boolean areSectionBoundsAnimating() {
+        for (NotificationSection section : mSections) {
+            if (section.areBoundsAnimating()) {
+                return true;
+            }
+        }
+        return false;
     }
 
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void startBackgroundAnimation() {
-        // left and right are always instantly applied
-        mCurrentBounds.left = mBackgroundBounds.left;
-        mCurrentBounds.right = mBackgroundBounds.right;
-        startBottomAnimation();
-        startTopAnimation();
-    }
-
-    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
-    private void startTopAnimation() {
-        int previousEndValue = mEndAnimationRect.top;
-        int newEndValue = mBackgroundBounds.top;
-        ObjectAnimator previousAnimator = mTopAnimator;
-        if (previousAnimator != null && previousEndValue == newEndValue) {
-            return;
+        // TODO(kprevas): do we still need separate fields for top/bottom?
+        // or can each section manage its own animation state?
+        NotificationSection firstVisibleSection = getFirstVisibleSection();
+        NotificationSection lastVisibleSection = getLastVisibleSection();
+        for (NotificationSection section : mSections) {
+            section.startBackgroundAnimation(
+                    section == firstVisibleSection
+                            ? mAnimateNextBackgroundTop
+                            : mAnimateNextSectionBoundsChange,
+                    section == lastVisibleSection
+                            ? mAnimateNextBackgroundBottom
+                            : mAnimateNextSectionBoundsChange);
         }
-        if (!mAnimateNextBackgroundTop) {
-            // just a local update was performed
-            if (previousAnimator != null) {
-                // we need to increase all animation keyframes of the previous animator by the
-                // relative change to the end value
-                int previousStartValue = mStartAnimationRect.top;
-                PropertyValuesHolder[] values = previousAnimator.getValues();
-                values[0].setIntValues(previousStartValue, newEndValue);
-                mStartAnimationRect.top = previousStartValue;
-                mEndAnimationRect.top = newEndValue;
-                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-                return;
-            } else {
-                // no new animation needed, let's just apply the value
-                setBackgroundTop(newEndValue);
-                return;
-            }
-        }
-        if (previousAnimator != null) {
-            previousAnimator.cancel();
-        }
-        ObjectAnimator animator = ObjectAnimator.ofInt(this, "backgroundTop",
-                mCurrentBounds.top, newEndValue);
-        Interpolator interpolator = Interpolators.FAST_OUT_SLOW_IN;
-        animator.setInterpolator(interpolator);
-        animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-        // remove the tag when the animation is finished
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mStartAnimationRect.top = -1;
-                mEndAnimationRect.top = -1;
-                mTopAnimator = null;
-            }
-        });
-        animator.start();
-        mStartAnimationRect.top = mCurrentBounds.top;
-        mEndAnimationRect.top = newEndValue;
-        mTopAnimator = animator;
-    }
-
-    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
-    private void startBottomAnimation() {
-        int previousStartValue = mStartAnimationRect.bottom;
-        int previousEndValue = mEndAnimationRect.bottom;
-        int newEndValue = mBackgroundBounds.bottom;
-        ObjectAnimator previousAnimator = mBottomAnimator;
-        if (previousAnimator != null && previousEndValue == newEndValue) {
-            return;
-        }
-        if (!mAnimateNextBackgroundBottom) {
-            // just a local update was performed
-            if (previousAnimator != null) {
-                // we need to increase all animation keyframes of the previous animator by the
-                // relative change to the end value
-                PropertyValuesHolder[] values = previousAnimator.getValues();
-                values[0].setIntValues(previousStartValue, newEndValue);
-                mStartAnimationRect.bottom = previousStartValue;
-                mEndAnimationRect.bottom = newEndValue;
-                previousAnimator.setCurrentPlayTime(previousAnimator.getCurrentPlayTime());
-                return;
-            } else {
-                // no new animation needed, let's just apply the value
-                setBackgroundBottom(newEndValue);
-                return;
-            }
-        }
-        if (previousAnimator != null) {
-            previousAnimator.cancel();
-        }
-        ObjectAnimator animator = ObjectAnimator.ofInt(this, "backgroundBottom",
-                mCurrentBounds.bottom, newEndValue);
-        Interpolator interpolator = Interpolators.FAST_OUT_SLOW_IN;
-        animator.setInterpolator(interpolator);
-        animator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-        // remove the tag when the animation is finished
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mStartAnimationRect.bottom = -1;
-                mEndAnimationRect.bottom = -1;
-                mBottomAnimator = null;
-            }
-        });
-        animator.start();
-        mStartAnimationRect.bottom = mCurrentBounds.bottom;
-        mEndAnimationRect.bottom = newEndValue;
-        mBottomAnimator = animator;
-    }
-
-    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-    private void setBackgroundTop(int top) {
-        mCurrentBounds.top = top;
-        invalidate();
-    }
-
-    @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-    public void setBackgroundBottom(int bottom) {
-        mCurrentBounds.bottom = bottom;
-        invalidate();
     }
 
     /**
@@ -2171,32 +2151,38 @@
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void updateBackgroundBounds() {
         getLocationInWindow(mTempInt2);
-        mBackgroundBounds.left = mTempInt2[0] + mSidePaddings;
-        mBackgroundBounds.right = mTempInt2[0] + getWidth() - mSidePaddings;
+        int left = mTempInt2[0] + mSidePaddings;
+        int right = mTempInt2[0] + getWidth() - mSidePaddings;
+        for (NotificationSection section : mSections) {
+            section.getBounds().left = left;
+            section.getBounds().right = right;
+        }
 
         if (!mIsExpanded) {
-            mBackgroundBounds.top = 0;
-            mBackgroundBounds.bottom = 0;
+            for (NotificationSection section : mSections) {
+                section.getBounds().top = 0;
+                section.getBounds().bottom = 0;
+            }
             return;
         }
-        ActivatableNotificationView firstView = mFirstVisibleBackgroundChild;
+        NotificationSection firstSection = getFirstVisibleSection();
         int top = 0;
-        if (firstView != null) {
+        if (firstSection != null) {
+            ActivatableNotificationView firstView = firstSection.getFirstVisibleChild();
             // Round Y up to avoid seeing the background during animation
             int finalTranslationY = (int) Math.ceil(ViewState.getFinalTranslationY(firstView));
-            if (mAnimateNextBackgroundTop
-                    || mTopAnimator == null && mCurrentBounds.top == finalTranslationY
-                    || mTopAnimator != null && mEndAnimationRect.top == finalTranslationY) {
+            if (mAnimateNextBackgroundTop || firstSection.isTargetTop(finalTranslationY)) {
                 // we're ending up at the same location as we are now, lets just skip the animation
                 top = finalTranslationY;
             } else {
                 top = (int) Math.ceil(firstView.getTranslationY());
             }
         }
+        NotificationSection lastSection = getLastVisibleSection();
         ActivatableNotificationView lastView =
                 mShelf.hasItemsInStableShelf() && mShelf.getVisibility() != GONE
                         ? mShelf
-                        : mLastVisibleBackgroundChild;
+                        : lastSection == null ? null : lastSection.getLastVisibleChild();
         int bottom;
         if (lastView != null) {
             int finalTranslationY;
@@ -2207,9 +2193,7 @@
             }
             int finalHeight = ExpandableViewState.getFinalActualHeight(lastView);
             int finalBottom = finalTranslationY + finalHeight - lastView.getClipBottomAmount();
-            if (mAnimateNextBackgroundBottom
-                    || mBottomAnimator == null && mCurrentBounds.bottom == finalBottom
-                    || mBottomAnimator != null && mEndAnimationRect.bottom == finalBottom) {
+            if (mAnimateNextBackgroundBottom || lastSection.isTargetBottom(finalBottom)) {
                 // we're ending up at the same location as we are now, lets just skip the animation
                 bottom = finalBottom;
             } else {
@@ -2226,8 +2210,38 @@
             // otherwise the animation from the shade to the keyguard will jump as it's maxed
             top = Math.max(0, top);
         }
-        mBackgroundBounds.top = top;
-        mBackgroundBounds.bottom = Math.max(bottom, top);
+        bottom = Math.max(bottom, top);
+
+        setSectionBoundsByPriority(left, right, top, bottom, mSections[0], mSections[1]);
+    }
+
+    private void setSectionBoundsByPriority(int left, int right, int top, int bottom,
+            NotificationSection highPrioritySection, NotificationSection lowPrioritySection) {
+        if (NotificationUtils.useNewInterruptionModel(mContext)) {
+            // TODO(kprevas): can we use section boundary indices from mAmbientState instead?
+            ActivatableNotificationView lastChildAboveGap = getLastHighPriorityChild();
+            ActivatableNotificationView firstChildBelowGap = getFirstLowPriorityChild();
+            if (lastChildAboveGap != null && firstChildBelowGap != null) {
+                int gapTop =
+                        (int) Math.max(top,
+                                Math.min(lastChildAboveGap.getTranslationY()
+                                                + lastChildAboveGap.getActualHeight(),
+                                        bottom));
+                int gapBottom = (int) Math.max(top,
+                        Math.min(firstChildBelowGap.getTranslationY(), bottom));
+                highPrioritySection.getBounds().set(left, top, right, gapTop);
+                lowPrioritySection.getBounds().set(left, gapBottom, right, bottom);
+            } else if (lastChildAboveGap != null) {
+                highPrioritySection.getBounds().set(left, top, right, bottom);
+                lowPrioritySection.getBounds().set(left, bottom, right, bottom);
+            } else {
+                highPrioritySection.getBounds().set(left, top, right, top);
+                lowPrioritySection.getBounds().set(left, top, right, bottom);
+            }
+        } else {
+            highPrioritySection.getBounds().set(left, top, right, bottom);
+            lowPrioritySection.getBounds().set(left, bottom, right, bottom);
+        }
     }
 
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
@@ -2246,6 +2260,25 @@
         return null;
     }
 
+    private NotificationSection getFirstVisibleSection() {
+        for (NotificationSection section : mSections) {
+            if (section.getFirstVisibleChild() != null) {
+                return section;
+            }
+        }
+        return null;
+    }
+
+    private NotificationSection getLastVisibleSection() {
+        for (int i = mSections.length - 1; i >= 0; i--) {
+            NotificationSection section = mSections[i];
+            if (section.getLastVisibleChild() != null) {
+                return section;
+            }
+        }
+        return null;
+    }
+
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private ActivatableNotificationView getLastChildWithBackground() {
         int childCount = getChildCount();
@@ -2272,6 +2305,43 @@
         return null;
     }
 
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
+    @Nullable
+    private ActivatableNotificationView getLastHighPriorityChild() {
+        ActivatableNotificationView lastChildBeforeGap = null;
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != View.GONE && child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                if (!mEntryManager.getNotificationData().isHighPriority(
+                        row.getStatusBarNotification())) {
+                    break;
+                } else {
+                    lastChildBeforeGap = row;
+                }
+            }
+        }
+        return lastChildBeforeGap;
+    }
+
+    @ShadeViewRefactor(RefactorComponent.COORDINATOR)
+    @Nullable
+    private ActivatableNotificationView getFirstLowPriorityChild() {
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != View.GONE && child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                if (!mEntryManager.getNotificationData().isHighPriority(
+                        row.getStatusBarNotification())) {
+                    return row;
+                }
+            }
+        }
+        return null;
+    }
+
     /**
      * Fling the scroll view
      *
@@ -2389,7 +2459,7 @@
         final int firstChildMinHeight = firstChild != null ? firstChild.getCollapsedHeight()
                 : mCollapsedSize;
         int shelfHeight = 0;
-        if (mLastVisibleBackgroundChild != null && mShelf.getVisibility() != GONE) {
+        if (getLastVisibleSection() != null && mShelf.getVisibility() != GONE) {
             shelfHeight = mShelf.getIntrinsicHeight();
         }
         return mIntrinsicPadding + firstChildMinHeight + shelfHeight;
@@ -2698,23 +2768,68 @@
 
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateFirstAndLastBackgroundViews() {
+        NotificationSection firstSection = getFirstVisibleSection();
+        NotificationSection lastSection = getLastVisibleSection();
+
         ActivatableNotificationView firstChild = getFirstChildWithBackground();
         ActivatableNotificationView lastChild = getLastChildWithBackground();
+        boolean sectionViewsChanged = updateFirstAndLastViewsInSectionsByPriority(
+                mSections[0], mSections[1], firstChild, lastChild);
+
         if (mAnimationsEnabled && mIsExpanded) {
-            mAnimateNextBackgroundTop = firstChild != mFirstVisibleBackgroundChild;
-            mAnimateNextBackgroundBottom = lastChild != mLastVisibleBackgroundChild;
+            mAnimateNextBackgroundTop =
+                    firstSection == null || firstChild != firstSection.getFirstVisibleChild();
+            mAnimateNextBackgroundBottom =
+                    lastSection == null || lastChild != lastSection.getLastVisibleChild();
+            mAnimateNextSectionBoundsChange = sectionViewsChanged;
         } else {
             mAnimateNextBackgroundTop = false;
             mAnimateNextBackgroundBottom = false;
+            mAnimateNextSectionBoundsChange = false;
         }
-        mFirstVisibleBackgroundChild = firstChild;
-        mLastVisibleBackgroundChild = lastChild;
         mAmbientState.setLastVisibleBackgroundChild(lastChild);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mFirstVisibleBackgroundChild,
-                mLastVisibleBackgroundChild);
+        mRoundnessManager.updateRoundedChildren(mSections);
         invalidate();
     }
 
+    /** @return {@code true} if the last view in the top section changed (so we need to animate). */
+    private boolean updateFirstAndLastViewsInSectionsByPriority(
+            final NotificationSection highPrioritySection,
+            final NotificationSection lowPrioritySection,
+            ActivatableNotificationView firstChild,
+            ActivatableNotificationView lastChild) {
+        if (NotificationUtils.useNewInterruptionModel(mContext)) {
+            ActivatableNotificationView previousLastHighPriorityChild =
+                    highPrioritySection.getLastVisibleChild();
+            ActivatableNotificationView previousFirstLowPriorityChild =
+                    lowPrioritySection.getFirstVisibleChild();
+            ActivatableNotificationView lastHighPriorityChild = getLastHighPriorityChild();
+            ActivatableNotificationView firstLowPriorityChild = getFirstLowPriorityChild();
+            if (lastHighPriorityChild != null && firstLowPriorityChild != null) {
+                highPrioritySection.setFirstVisibleChild(firstChild);
+                highPrioritySection.setLastVisibleChild(lastHighPriorityChild);
+                lowPrioritySection.setFirstVisibleChild(firstLowPriorityChild);
+                lowPrioritySection.setLastVisibleChild(lastChild);
+            } else if (lastHighPriorityChild != null) {
+                highPrioritySection.setFirstVisibleChild(firstChild);
+                highPrioritySection.setLastVisibleChild(lastChild);
+                lowPrioritySection.setFirstVisibleChild(null);
+                lowPrioritySection.setLastVisibleChild(null);
+            } else {
+                highPrioritySection.setFirstVisibleChild(null);
+                highPrioritySection.setLastVisibleChild(null);
+                lowPrioritySection.setFirstVisibleChild(firstChild);
+                lowPrioritySection.setLastVisibleChild(lastChild);
+            }
+            return lastHighPriorityChild != previousLastHighPriorityChild
+                    || firstLowPriorityChild != previousFirstLowPriorityChild;
+        } else {
+            highPrioritySection.setFirstVisibleChild(firstChild);
+            highPrioritySection.setLastVisibleChild(lastChild);
+            return false;
+        }
+    }
+
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private void onViewAddedInternal(View child) {
         updateHideSensitiveForChild(child);
@@ -3173,7 +3288,7 @@
                 || ev.getActionMasked() == MotionEvent.ACTION_UP;
         handleEmptySpaceClick(ev);
         boolean expandWantsIt = false;
-        boolean swipingInProgress = mSwipeHelper.isSwipingInProgress();
+        boolean swipingInProgress = mSwipingInProgress;
         if (mIsExpanded && !swipingInProgress && !mOnlyScrollingInThisMotion) {
             if (isCancelOrUp) {
                 mExpandHelper.onlyObserveMovements(false);
@@ -3228,7 +3343,7 @@
     @Override
     @ShadeViewRefactor(RefactorComponent.INPUT)
     public boolean onGenericMotionEvent(MotionEvent event) {
-        if (!isScrollingEnabled() || !mIsExpanded || mSwipeHelper.isSwipingInProgress() || mExpandingNotification
+        if (!isScrollingEnabled() || !mIsExpanded || mSwipingInProgress || mExpandingNotification
                 || mDisallowScrollingInThisMotion) {
             return false;
         }
@@ -3455,7 +3570,7 @@
         initDownStates(ev);
         handleEmptySpaceClick(ev);
         boolean expandWantsIt = false;
-        boolean swipingInProgress = mSwipeHelper.isSwipingInProgress();
+        boolean swipingInProgress = mSwipingInProgress;
         if (!swipingInProgress && !mOnlyScrollingInThisMotion) {
             expandWantsIt = mExpandHelper.onInterceptTouchEvent(ev);
         }
@@ -3734,6 +3849,14 @@
         }
     }
 
+    @ShadeViewRefactor(RefactorComponent.INPUT)
+    private void setSwipingInProgress(boolean swiping) {
+        mSwipingInProgress = swiping;
+        if (swiping) {
+            requestDisallowInterceptTouchEvent(true);
+        }
+    }
+
     @Override
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void onWindowFocusChanged(boolean hasWindowFocus) {
@@ -3901,9 +4024,14 @@
         ExpandableNotificationRow row = view instanceof ExpandableNotificationRow
                 ? (ExpandableNotificationRow) view
                 : null;
-        if (row != null && (row == mFirstVisibleBackgroundChild
-                || row.getNotificationParent() == mFirstVisibleBackgroundChild)) {
-            updateAlgorithmLayoutMinHeight();
+        NotificationSection firstSection = getFirstVisibleSection();
+        ActivatableNotificationView firstVisibleChild =
+                firstSection == null ? null : firstSection.getFirstVisibleChild();
+        if (row != null) {
+            if (row == firstVisibleChild
+                    || row.getNotificationParent() == firstVisibleChild) {
+                updateAlgorithmLayoutMinHeight();
+            }
         }
         if (needsAnimation) {
             requestAnimationOnViewResize(row);
@@ -3931,7 +4059,10 @@
                     endPosition += row.getNotificationParent().getTranslationY();
                 }
                 int layoutEnd = mMaxLayoutHeight + (int) mStackTranslation;
-                if (row != mLastVisibleBackgroundChild && mShelf.getVisibility() != GONE) {
+                NotificationSection lastSection = getLastVisibleSection();
+                ActivatableNotificationView lastVisibleChild =
+                        lastSection == null ? null : lastSection.getLastVisibleChild();
+                if (row != lastVisibleChild && mShelf.getVisibility() != GONE) {
                     layoutEnd -= mShelf.getIntrinsicHeight() + mPaddingBetweenElements;
                 }
                 if (endPosition > layoutEnd) {
@@ -4012,6 +4143,11 @@
         return mAmbientState.isDimmed();
     }
 
+    @VisibleForTesting
+    int getSectionBoundaryIndex(int boundaryNum) {
+        return mAmbientState.getSectionBoundaryIndex(boundaryNum);
+    }
+
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     private void setDimAmount(float dimAmount) {
         mDimAmount = dimAmount;
@@ -4273,16 +4409,6 @@
     }
 
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
-    public long getDarkAnimationDuration(boolean dark) {
-        long duration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
-        // Longer animation when sleeping with more than 1 notification
-        if (dark && getNotGoneChildCount() > 2) {
-            duration *= 1.2f;
-        }
-        return duration;
-    }
-
-    @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) {
         if (screenLocation == null || screenLocation.y < mTopPadding) {
             return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
@@ -5089,9 +5215,8 @@
                 beforeSpeedBump = !mEntryManager.getNotificationData().isAmbient(
                         row.getStatusBarNotification().getKey());
             } else {
-                beforeSpeedBump = mEntryManager.getNotificationData().getImportance(
-                        row.getStatusBarNotification().getKey())
-                        >= NotificationManager.IMPORTANCE_DEFAULT;
+                beforeSpeedBump = mEntryManager.getNotificationData().isHighPriority(
+                        row.getStatusBarNotification());
             }
             if (beforeSpeedBump) {
                 speedBumpIndex = currentIndex;
@@ -5101,6 +5226,33 @@
         updateSpeedBumpIndex(speedBumpIndex, noAmbient);
     }
 
+    /** Updates the indices of the boundaries between sections. */
+    @ShadeViewRefactor(RefactorComponent.INPUT)
+    public void updateSectionBoundaries() {
+        int gapIndex = -1;
+        if (NotificationUtils.useNewInterruptionModel(mContext)) {
+            int currentIndex = 0;
+            final int n = getChildCount();
+            for (int i = 0; i < n; i++) {
+                View view = getChildAt(i);
+                if (view.getVisibility() == View.GONE
+                        || !(view instanceof ExpandableNotificationRow)) {
+                    continue;
+                }
+                ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+                if (!mEntryManager.getNotificationData().isHighPriority(
+                        row.getStatusBarNotification())) {
+                    if (currentIndex > 0) {
+                        gapIndex = currentIndex;
+                    }
+                    break;
+                }
+                currentIndex++;
+            }
+        }
+        mAmbientState.setSectionBoundaryIndex(0, gapIndex);
+    }
+
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private void updateContinuousShadowDrawing() {
         boolean continuousShadowUpdate = mAnimationRunning
@@ -5500,6 +5652,7 @@
 
         @Override
         public void onDragCancelled(View v) {
+            setSwipingInProgress(false);
             mFalsingManager.onNotificatonStopDismissing();
         }
 
@@ -5527,6 +5680,7 @@
          */
 
         public void handleChildViewDismissed(View view) {
+            setSwipingInProgress(false);
             if (mDismissAllInProgress) {
                 return;
             }
@@ -5595,6 +5749,7 @@
         @Override
         public void onBeginDrag(View v) {
             mFalsingManager.onNotificatonStartDismissing();
+            setSwipingInProgress(true);
             mAmbientState.onBeginDrag(v);
             updateContinuousShadowDrawing();
             if (mAnimationsEnabled && (mIsExpanded || !isPinnedHeadsUp(v))) {
@@ -5641,6 +5796,17 @@
         public boolean canChildBeDismissed(View v) {
             return NotificationStackScrollLayout.this.canChildBeDismissed(v);
         }
+
+        @Override
+        public boolean canChildBeDismissedInDirection(View v, boolean isRightOrDown) {
+            boolean isValidDirection;
+            if (NotificationUtils.useNewInterruptionModel(mContext)) {
+                isValidDirection = isLayoutRtl() ? !isRightOrDown : isRightOrDown;
+            } else {
+                isValidDirection = true;
+            }
+            return isValidDirection && canChildBeDismissed(v);
+        }
     };
 
     // ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index 599da3b..f1d9549 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -165,15 +165,15 @@
 
         if (menuRow.isSnappedAndOnSameSide()) {
             // Menu was snapped to previously and we're on the same side
-            handleSwipeFromSnap(ev, animView, velocity, menuRow);
+            handleSwipeFromOpenState(ev, animView, velocity, menuRow);
         } else {
             // Menu has not been snapped, or was snapped previously but is now on
             // the opposite side.
-            handleSwipeFromNonSnap(ev, animView, velocity, menuRow);
+            handleSwipeFromClosedState(ev, animView, velocity, menuRow);
         }
     }
 
-    private void handleSwipeFromNonSnap(MotionEvent ev, View animView, float velocity,
+    private void handleSwipeFromClosedState(MotionEvent ev, View animView, float velocity,
             NotificationMenuRowPlugin menuRow) {
         boolean isDismissGesture = isDismissGesture(ev);
         final boolean gestureTowardsMenu = menuRow.isTowardsMenu(velocity);
@@ -183,10 +183,14 @@
         final boolean showMenuForSlowOnGoing = !menuRow.canBeDismissed()
                 && timeForGesture >= SWIPE_MENU_TIMING;
 
-        if (!isFalseGesture(ev)
-                && (swipedEnoughToShowMenu(menuRow)
-                && (!gestureFastEnough || showMenuForSlowOnGoing))
-                || (gestureTowardsMenu && !isDismissGesture)) {
+        boolean isNonDismissGestureTowardsMenu = gestureTowardsMenu && !isDismissGesture;
+        boolean isSlowSwipe = !gestureFastEnough || showMenuForSlowOnGoing;
+        boolean slowSwipedFarEnough = swipedEnoughToShowMenu(menuRow) && isSlowSwipe;
+        boolean isFastNonDismissGesture =
+                gestureFastEnough && !gestureTowardsMenu && !isDismissGesture;
+        boolean isMenuRevealingGestureAwayFromMenu = slowSwipedFarEnough || isFastNonDismissGesture;
+        if (isNonDismissGestureTowardsMenu
+                || (!isFalseGesture(ev) && isMenuRevealingGestureAwayFromMenu)) {
             // Menu has not been snapped to previously and this is menu revealing gesture
             snapOpen(animView, menuRow.getMenuSnapTarget(), velocity);
             menuRow.onSnapOpen();
@@ -199,7 +203,7 @@
         }
     }
 
-    private void handleSwipeFromSnap(MotionEvent ev, View animView, float velocity,
+    private void handleSwipeFromOpenState(MotionEvent ev, View animView, float velocity,
             NotificationMenuRowPlugin menuRow) {
         boolean isDismissGesture = isDismissGesture(ev);
 
@@ -227,7 +231,6 @@
         if (mCallback.isExpanded()) {
             // We don't want to quick-dismiss when it's a heads up as this might lead to closing
             // of the panel early.
-            mSwipingInProgress = false;
             mCallback.handleChildViewDismissed(view);
         }
         mCallback.onDismiss();
@@ -247,7 +250,6 @@
     @Override
     public void snapChild(final View animView, final float targetLeft, float velocity) {
         superSnapChild(animView, targetLeft, velocity);
-        mSwipingInProgress = false;
         mCallback.onDragCancelled(animView);
         if (targetLeft == 0) {
             handleMenuCoveredOrDismissed();
@@ -354,7 +356,6 @@
 
     public void onMenuShown(View animView) {
         setExposedMenuView(getTranslatingParentView());
-        mSwipingInProgress = false;
         mCallback.onDragCancelled(animView);
         Handler handler = getHandler();
 
@@ -422,4 +423,4 @@
 
         void onDismiss();
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 742d89d..8c13489 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -21,13 +21,14 @@
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
+
 import com.android.systemui.R;
 import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.notification.row.FooterView;
-import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.notification.NotificationUtils;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -44,6 +45,7 @@
 
     private int mPaddingBetweenElements;
     private int mIncreasedPaddingBetweenElements;
+    private int mGapHeight;
     private int mCollapsedSize;
 
     private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
@@ -74,6 +76,7 @@
                 R.dimen.heads_up_status_bar_padding);
         mPinnedZTranslationExtra = res.getDimensionPixelSize(
                 R.dimen.heads_up_pinned_elevation);
+        mGapHeight = res.getDimensionPixelSize(R.dimen.notification_section_divider_height);
     }
 
     public void getStackScrollState(AmbientState ambientState, StackScrollState resultState) {
@@ -387,6 +390,9 @@
         childViewState.location = ExpandableViewState.LOCATION_UNKNOWN;
         int paddingAfterChild = getPaddingAfterChild(algorithmState, child);
         int childHeight = getMaxAllowedChildHeight(child);
+        if (ambientState.beginsNewSection(i)) {
+            currentYPosition += mGapHeight;
+        }
         childViewState.yTranslation = currentYPosition;
         boolean isFooterView = child instanceof FooterView;
         boolean isEmptyShadeView = child instanceof EmptyShadeView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index da3fb66..a94401b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -26,10 +26,10 @@
 import com.android.keyguard.KeyguardSliceView;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
 
 import java.util.ArrayList;
 import java.util.HashSet;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
index a15fd70..b00068c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -28,9 +28,9 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.policy.HeadsUpUtil;
 
 import java.io.FileDescriptor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index ab58660..1d7e899 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -15,8 +15,10 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
+import android.hardware.display.ColorDisplayManager;
 import android.os.Handler;
 import android.provider.Settings.Secure;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.ColorDisplayController;
 import com.android.systemui.Dependency;
@@ -80,7 +82,7 @@
             Dependency.get(ManagedProfileController.class).addCallback(mProfileCallback);
         }
         if (!mAutoTracker.isAdded(NIGHT)
-            && ColorDisplayController.isAvailable(mContext)) {
+                && ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             Dependency.get(ColorDisplayController.class).setListener(mColorDisplayCallback);
         }
     }
@@ -93,7 +95,9 @@
         Dependency.get(HotspotController.class).removeCallback(mHotspotCallback);
         Dependency.get(DataSaverController.class).removeCallback(mDataSaverListener);
         Dependency.get(ManagedProfileController.class).removeCallback(mProfileCallback);
-        Dependency.get(ColorDisplayController.class).setListener(null);
+        if (ColorDisplayManager.isNightDisplayAvailable(mContext)) {
+            Dependency.get(ColorDisplayController.class).setListener(null);
+        }
     }
 
     public void unmarkTileAsAutoAdded(String tabSpec) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index c32dcea..3d81473 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
@@ -25,9 +24,9 @@
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
-import android.graphics.PorterDuff.Mode;
 import android.graphics.drawable.Drawable;
 import android.os.SystemClock;
 import android.util.Log;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 8325bf8..302d630 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -16,18 +16,18 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.hardware.biometrics.BiometricSourceType;
 import android.content.Context;
+import android.hardware.biometrics.BiometricSourceType;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.os.Trace;
 import android.util.Log;
 
+import com.android.internal.util.LatencyTracker;
 import com.android.keyguard.KeyguardConstants;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.internal.util.LatencyTracker;
 import com.android.systemui.Dependency;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index 4eca6bb..4ced702 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -21,8 +21,8 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.view.View;
-
 import android.view.View.AccessibilityDelegate;
+
 import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 
@@ -263,6 +263,16 @@
         }
     }
 
+    public void setTranslation(int x, int y, int z) {
+        final int N = mViews.size();
+        for (int i = 0; i < N; i++) {
+            final View view = mViews.get(i);
+            view.setTranslationX(x);
+            view.setTranslationY(y);
+            view.setTranslationZ(z);
+        }
+    }
+
     public ArrayList<View> getViews() {
         return mViews;
     }
@@ -276,6 +286,11 @@
         if (mImageDrawable != null) {
             mImageDrawable.setCallback(mCurrentView);
         }
+        if (mCurrentView != null) {
+            mCurrentView.setTranslationX(0);
+            mCurrentView.setTranslationY(0);
+            mCurrentView.setTranslationZ(0);
+        }
     }
 
     public void setVertical(boolean vertical) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index d4de8fc..3b13fe9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -46,7 +46,8 @@
  * and keyguard state. Also manages lifecycle to make sure the views it contains are being
  * updated by the StatusBarIconController and DarkIconManager while it is attached.
  */
-public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks {
+public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks,
+        StatusBarStateController.StateListener {
 
     public static final String TAG = "CollapsedStatusBarFragment";
     private static final String EXTRA_PANEL_STATE = "panel_state";
@@ -120,12 +121,14 @@
     public void onResume() {
         super.onResume();
         mCommandQueue.addCallbacks(this);
+        mStatusBarStateController.addListener(this);
     }
 
     @Override
     public void onPause() {
         super.onPause();
         mCommandQueue.removeCallbacks(this);
+        mStatusBarStateController.removeListener(this);
     }
 
     @Override
@@ -351,4 +354,14 @@
             mOperatorNameFrame = stub.inflate();
         }
     }
+
+    @Override
+    public void onStateChanged(int newState) {
+
+    }
+
+    @Override
+    public void onDozingChanged(boolean isDozing) {
+        disable(mDisabled1, mDisabled1, false /* animate */);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
index 9703043..cc8adde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
@@ -19,6 +19,7 @@
 import android.annotation.IdRes;
 import android.annotation.NonNull;
 import android.view.View;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index e052e53..3425dd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -24,20 +24,20 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.widget.LinearLayout;
 
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.DemoMode;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.StatusBarMobileView;
 import com.android.systemui.statusbar.StatusBarWifiView;
+import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
+
 import java.util.ArrayList;
 
 public class DemoStatusIcons extends StatusIconContainer implements DemoMode, DarkReceiver {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index a0597dc..94b2cde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -20,13 +20,17 @@
 import android.os.Handler;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.Dependency;
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 
 /**
  * Controller which handles all the doze animations of the scrims.
  */
-public class DozeScrimController {
+public class DozeScrimController implements StateListener {
     private static final String TAG = "DozeScrimController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -83,8 +87,11 @@
 
     public DozeScrimController(DozeParameters dozeParameters) {
         mDozeParameters = dozeParameters;
+        //Never expected to be destroyed
+        Dependency.get(StatusBarStateController.class).addListener(this);
     }
 
+    @VisibleForTesting
     public void setDozing(boolean dozing) {
         if (mDozing == dozing) return;
         mDozing = dozing;
@@ -181,4 +188,14 @@
     public ScrimController.Callback getScrimCallback() {
         return mScrimCallback;
     }
+
+    @Override
+    public void onStateChanged(int newState) {
+        // don't care
+    }
+
+    @Override
+    public void onDozingChanged(boolean isDozing) {
+        setDozing(isDozing);
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
index 8f49c85..efc2891 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
@@ -18,6 +18,7 @@
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.util.AttributeSet;
 import android.widget.ImageView;
+
 import com.android.systemui.R;
 
 public class ExpandableIndicator extends ImageView {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index c66bbb1..40f9f45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -26,12 +26,12 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.HeadsUpStatusBarView;
 import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 976327a..d05893d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -21,8 +21,6 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import androidx.collection.ArraySet;
-
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.Region.Op;
@@ -33,16 +31,18 @@
 import android.view.View;
 import android.view.ViewTreeObserver;
 
+import androidx.collection.ArraySet;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.ScreenDecorations;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index e4a5caa..be4df45 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -21,10 +21,9 @@
 import android.view.ViewConfiguration;
 
 import com.android.systemui.Gefingerpoken;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
 /**
  * A helper class to handle touches on the heads-up views.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 5439497..21c506b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -54,6 +54,7 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.MathUtils;
 import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
@@ -568,6 +569,7 @@
         mDarkAmount = darkAmount;
         mIndicationController.setDarkAmount(darkAmount);
         mLockIcon.setDarkAmount(darkAmount);
+        dozeTimeTick();
     }
 
     private static boolean isSuccessfulLaunch(int result) {
@@ -840,12 +842,10 @@
     }
 
     public void dozeTimeTick() {
-        if (mDarkAmount == 1) {
-            // Move views every minute to avoid burn-in
-            int burnInYOffset = getBurnInOffset(mBurnInYOffset * 2, false /* xAxis */)
-                    - mBurnInYOffset;
-            mLockIcon.setTranslationY(burnInYOffset);
-        }
+        // Move views every minute to avoid burn-in
+        int burnInYOffset = -getBurnInOffset(mBurnInYOffset, false /* xAxis */);
+        burnInYOffset = (int) MathUtils.lerp(0, burnInYOffset, mDarkAmount);
+        mLockIcon.setTranslationY(burnInYOffset);
     }
 
     public void setBurnInXOffset(int burnInXOffset) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 235629b..c0d1818 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -16,8 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -268,6 +268,8 @@
     }
 
     public void hide(boolean destroyView) {
+        // TODO(b/113914868): investigation log for disappearing home button
+        Log.i(TAG, "KeyguardBouncer.hide (b/113914868): destroyView=" + destroyView);
         if (isShowing()) {
             StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
                 StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 4a7bc3a..d8280ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -187,6 +187,7 @@
         if (mPulsing) {
             clockYDark -= mPulsingPadding;
         }
+        clockYDark = MathUtils.max(0, clockYDark);
 
         float clockYRegular = getExpandedClockPosition();
         float clockYBouncer = -mKeyguardStatusHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
index 462201c..b3d0bf8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java
@@ -35,7 +35,7 @@
     }
 
     /**
-     * Executes an action that requres the screen to be unlocked.
+     * Executes an action that requires the screen to be unlocked.
      *
      * <p>Must be called after {@link #setDismissHandler}.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 8cace72..e0c5516 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -16,7 +16,9 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.app.WallpaperColors;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
+
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.Rect;
@@ -32,9 +34,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
-
 /**
  * Controls how light status bar flag applies to the icons.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index b0ac6ec..b29889d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.util.MathUtils;
 import android.util.TimeUtils;
 
 import com.android.systemui.Dependency;
@@ -29,6 +30,7 @@
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
+import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
 import java.io.FileDescriptor;
@@ -37,7 +39,8 @@
 /**
  * Class to control all aspects about light bar changes.
  */
-public class LightBarTransitionsController implements Dumpable, Callbacks {
+public class LightBarTransitionsController implements Dumpable, Callbacks,
+        StatusBarStateController.StateListener {
 
     public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
     private static final String EXTRA_DARK_INTENSITY = "dark_intensity";
@@ -45,6 +48,7 @@
     private final Handler mHandler;
     private final DarkIntensityApplier mApplier;
     private final KeyguardMonitor mKeyguardMonitor;
+    private final StatusBarStateController mStatusBarStateController;
 
     private boolean mTransitionDeferring;
     private long mTransitionDeferringStartTime;
@@ -55,6 +59,7 @@
     private ValueAnimator mTintAnimator;
     private float mDarkIntensity;
     private float mNextDarkIntensity;
+    private float mDozeAmount;
     private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
         @Override
         public void run() {
@@ -66,13 +71,17 @@
         mApplier = applier;
         mHandler = new Handler();
         mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
         SysUiServiceProvider.getComponent(context, CommandQueue.class)
                 .addCallbacks(this);
+        mStatusBarStateController.addListener(this);
+        mDozeAmount = mStatusBarStateController.getDozeAmount();
     }
 
     public void destroy(Context context) {
         SysUiServiceProvider.getComponent(context, CommandQueue.class)
                 .removeCallbacks(this);
+        mStatusBarStateController.removeListener(this);
     }
 
     public void saveState(Bundle outState) {
@@ -173,7 +182,11 @@
 
     private void setIconTintInternal(float darkIntensity) {
         mDarkIntensity = darkIntensity;
-        mApplier.applyDarkIntensity(darkIntensity);
+        dispatchDark();
+    }
+
+    private void dispatchDark() {
+        mApplier.applyDarkIntensity(MathUtils.lerp(mDarkIntensity, 0f, mDozeAmount));
     }
 
     @Override
@@ -196,6 +209,15 @@
         pw.print(" mNextDarkIntensity="); pw.println(mNextDarkIntensity);
     }
 
+    @Override
+    public void onStateChanged(int newState) { }
+
+    @Override
+    public void onDozeAmountChanged(float linear, float eased) {
+        mDozeAmount = eased;
+        dispatchDark();
+    }
+
     /**
      * Interface to apply a specific dark intensity.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index d5067b5..1be3975 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -22,6 +22,7 @@
 import android.graphics.PorterDuff;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.SystemProperties;
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityNodeInfo;
 
@@ -44,6 +45,8 @@
     private static final int STATE_FACE_UNLOCK = 2;
     private static final int STATE_FINGERPRINT = 3;
     private static final int STATE_FINGERPRINT_ERROR = 4;
+    private static final boolean HOLLOW_PILL = SystemProperties
+            .getBoolean("persist.sysui.hollow_pill", false);
 
     private int mLastState = 0;
     private boolean mLastDeviceInteractive;
@@ -221,6 +224,16 @@
                 throw new IllegalArgumentException();
         }
 
+        if (HOLLOW_PILL && deviceInteractive) {
+            switch (state) {
+                case STATE_FINGERPRINT:
+                case STATE_LOCK_OPEN:
+                case STATE_LOCKED:
+                case STATE_FACE_UNLOCK:
+                    iconRes = R.drawable.ic_home_button_outline;
+            }
+        }
+
         return mContext.getDrawable(iconRes);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
index 2779820..7621887 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
@@ -19,7 +19,6 @@
 import android.metrics.LogMaker;
 import android.util.ArrayMap;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
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 673cdb7..d2023ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -20,6 +20,7 @@
 import android.app.ActivityManager;
 import android.app.IWallpaperManager;
 import android.app.IWallpaperManagerCallback;
+import android.app.WallpaperColors;
 import android.app.WallpaperManager;
 import android.content.Context;
 import android.content.res.Resources;
@@ -36,7 +37,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
-import android.app.WallpaperColors;
 import android.util.Log;
 
 import com.android.keyguard.KeyguardUpdateMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
new file mode 100644
index 0000000..1002f9e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
+
+import android.annotation.NonNull;
+import android.hardware.input.InputManager;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.view.HapticFeedbackConstants;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import com.android.systemui.recents.OverviewProxyService;
+
+/**
+ * A back action when triggered will execute a back command
+ */
+public class NavigationBackAction extends NavigationGestureAction {
+
+    private static final String PULL_HOME_GO_BACK_PROP = "quickstepcontroller_homegoesback";
+    private static final String BACK_AFTER_END_PROP =
+            "quickstepcontroller_homegoesbackwhenend";
+    private static final String NAVBAR_EXPERIMENTS_DISABLED = "navbarexperiments_disabled";
+    private static final long BACK_BUTTON_FADE_OUT_ALPHA = 60;
+    private static final long BACK_GESTURE_POLL_TIMEOUT = 1000;
+
+    private final Handler mHandler = new Handler();
+
+    private final Runnable mExecuteBackRunnable = new Runnable() {
+        @Override
+        public void run() {
+            if (isEnabled() && canPerformAction()) {
+                performBack();
+                mHandler.postDelayed(this, BACK_GESTURE_POLL_TIMEOUT);
+            }
+        }
+    };
+
+    public NavigationBackAction(@NonNull NavigationBarView navigationBarView,
+            @NonNull OverviewProxyService service) {
+        super(navigationBarView, service);
+    }
+
+    @Override
+    public int requiresTouchDownHitTarget() {
+        return HIT_TARGET_HOME;
+    }
+
+    @Override
+    public boolean requiresDragWithHitTarget() {
+        return true;
+    }
+
+    @Override
+    public boolean canPerformAction() {
+        return mProxySender.getBackButtonAlpha() > 0;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return swipeHomeGoBackGestureEnabled();
+    }
+
+    @Override
+    protected void onGestureStart(MotionEvent event) {
+        if (!QuickStepController.shouldhideBackButton(getContext())) {
+            mNavigationBarView.getBackButton().setAlpha(0 /* alpha */, true /* animate */,
+                    BACK_BUTTON_FADE_OUT_ALPHA);
+        }
+        mHandler.removeCallbacks(mExecuteBackRunnable);
+        if (!shouldExecuteBackOnUp()) {
+            performBack();
+            mHandler.postDelayed(mExecuteBackRunnable, BACK_GESTURE_POLL_TIMEOUT);
+        }
+    }
+
+    @Override
+    protected void onGestureEnd() {
+        mHandler.removeCallbacks(mExecuteBackRunnable);
+        if (!QuickStepController.shouldhideBackButton(getContext())) {
+            mNavigationBarView.getBackButton().setAlpha(
+                    mProxySender.getBackButtonAlpha(), true /* animate */);
+        }
+        if (shouldExecuteBackOnUp()) {
+            performBack();
+        }
+    }
+
+    private void performBack() {
+        sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
+        sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
+        mNavigationBarView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
+    }
+
+    private boolean swipeHomeGoBackGestureEnabled() {
+        return !getGlobalBoolean(NAVBAR_EXPERIMENTS_DISABLED)
+                && getGlobalBoolean(PULL_HOME_GO_BACK_PROP);
+    }
+
+    private boolean shouldExecuteBackOnUp() {
+        return !getGlobalBoolean(NAVBAR_EXPERIMENTS_DISABLED)
+                && getGlobalBoolean(BACK_AFTER_END_PROP);
+    }
+
+    private void sendEvent(int action, int code) {
+        long when = SystemClock.uptimeMillis();
+        final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,
+                0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
+                KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+                InputDevice.SOURCE_KEYBOARD);
+        InputManager.getInstance().injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 329a33d..0cf1b3d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -55,7 +55,8 @@
 import android.telecom.TelecomManager;
 import android.text.TextUtils;
 import android.util.Log;
-import android.view.IRotationWatcher.Stub;
+import android.view.Display;
+import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -74,12 +75,12 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.LatencyTracker;
 import com.android.systemui.Dependency;
-import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.stackdivider.Divider;
@@ -143,6 +144,7 @@
 
     private OverviewProxyService mOverviewProxyService;
 
+    private boolean mIsOnDefaultDisplay = true;
     public boolean mHomeBlockedThisTouch;
 
     private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
@@ -240,6 +242,11 @@
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
         mNavigationBarView = (NavigationBarView) view;
+        final Display display = view.getDisplay();
+        // It may not have display when running unit test.
+        if (display != null) {
+            mIsOnDefaultDisplay = display.getDisplayId() == Display.DEFAULT_DISPLAY;
+        }
 
         mNavigationBarView.setComponents(mStatusBar.getPanel());
         mNavigationBarView.setDisabledFlags(mDisabledFlags1);
@@ -252,8 +259,6 @@
         prepareNavigationBarView();
         checkNavBarModes();
 
-        setDisabled2Flags(mDisabledFlags2);
-
         IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
         filter.addAction(Intent.ACTION_SCREEN_ON);
         filter.addAction(Intent.ACTION_USER_SWITCHED);
@@ -261,16 +266,23 @@
         notifyNavigationBarScreenOn();
         mOverviewProxyService.addCallback(mOverviewProxyListener);
 
-        RotationContextButton rotationButton = mNavigationBarView.getRotateSuggestionButton();
-        rotationButton.setListener(mRotationButtonListener);
-        rotationButton.addRotationCallback(mRotationWatcher);
+        // Currently there is no accelerometer sensor on non-default display.
+        if (mIsOnDefaultDisplay) {
+            final RotationContextButton rotationButton =
+                    mNavigationBarView.getRotateSuggestionButton();
+            rotationButton.setListener(mRotationButtonListener);
+            rotationButton.addRotationCallback(mRotationWatcher);
 
-        // Reset user rotation pref to match that of the WindowManager if starting in locked mode
-        // This will automatically happen when switching from auto-rotate to locked mode
-        if (rotationButton.isRotationLocked()) {
-            final int winRotation = mWindowManager.getDefaultDisplay().getRotation();
-            rotationButton.setRotationLockedAtAngle(winRotation);
+            // Reset user rotation pref to match that of the WindowManager if starting in locked
+            // mode. This will automatically happen when switching from auto-rotate to locked mode.
+            if (display != null && rotationButton.isRotationLocked()) {
+                final int winRotation = display.getRotation();
+                rotationButton.setRotationLockedAtAngle(winRotation);
+            }
+        } else {
+            mDisabledFlags2 |= StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
         }
+        setDisabled2Flags(mDisabledFlags2);
     }
 
     @Override
@@ -388,7 +400,7 @@
 
     @Override
     public void onRotationProposal(final int rotation, boolean isValid) {
-        final int winRotation = mWindowManager.getDefaultDisplay().getRotation();
+        final int winRotation = mNavigationBarView.getDisplay().getRotation();
         final boolean rotateSuggestionsDisabled = RotationContextButton
                 .hasDisable2RotateSuggestionFlag(mDisabledFlags2);
         if (RotationContextButton.DEBUG_ROTATION) {
@@ -419,8 +431,12 @@
         }
         checkNavBarModes();
         mStatusBar.touchAutoHide();
-        mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */,
-                true /* nbModeChanged */, mNavigationBarMode);
+
+        // TODO(115978725): Support light bar controller on external nav bars.
+        if (mLightBarController != null) {
+            mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */,
+                    true /* nbModeChanged */, mNavigationBarMode);
+        }
     }
 
     @Override
@@ -452,8 +468,11 @@
             }
         }
 
-        mLightBarController.onNavigationVisibilityChanged(vis, mask, nbModeChanged,
-                mNavigationBarMode);
+        // TODO(115978725): Support light bar controller on external nav bars.
+        if (mLightBarController != null) {
+            mLightBarController.onNavigationVisibilityChanged(vis, mask, nbModeChanged,
+                    mNavigationBarMode);
+        }
     }
 
     @Override
@@ -469,10 +488,13 @@
             updateScreenPinningGestures();
         }
 
-        final int masked2 = state2 & (StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS);
-        if (masked2 != mDisabledFlags2) {
-            mDisabledFlags2 = masked2;
-            setDisabled2Flags(masked2);
+        // Only default display supports rotation suggestions.
+        if (mIsOnDefaultDisplay) {
+            final int masked2 = state2 & (StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS);
+            if (masked2 != mDisabledFlags2) {
+                mDisabledFlags2 = masked2;
+                setDisabled2Flags(masked2);
+            }
         }
     }
 
@@ -840,9 +862,17 @@
     };
 
     public static View create(Context context, FragmentListener listener) {
+        final int displayId = context.getDisplay().getDisplayId();
+        final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+        final int height = isDefaultDisplay
+                ? LayoutParams.MATCH_PARENT
+                : context.getResources().getDimensionPixelSize(R.dimen.navigation_bar_height);
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
-                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
+                LayoutParams.MATCH_PARENT, height,
+                // TODO(b/117478341): Resolve one status bar/ navigation bar assumption
+                isDefaultDisplay
+                        ? WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
+                        : WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                         | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                         | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
@@ -851,9 +881,13 @@
                         | WindowManager.LayoutParams.FLAG_SLIPPERY,
                 PixelFormat.TRANSLUCENT);
         lp.token = new Binder();
-        lp.setTitle("NavigationBar");
+        lp.setTitle("NavigationBar" + displayId);
         lp.accessibilityTitle = context.getString(R.string.nav_bar);
         lp.windowAnimations = 0;
+        if (!isDefaultDisplay) {
+            lp.flags |= LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
+            lp.gravity = Gravity.BOTTOM;
+        }
 
         View navigationBarView = LayoutInflater.from(context).inflate(
                 R.layout.navigation_bar_window, null);
@@ -861,13 +895,23 @@
         if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + navigationBarView);
         if (navigationBarView == null) return null;
 
+        final NavigationBarFragment fragment = new NavigationBarFragment();
+        navigationBarView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+            @Override
+            public void onViewAttachedToWindow(View v) {
+                final FragmentHostManager fragmentHost = FragmentHostManager.get(v);
+                fragmentHost.getFragmentManager().beginTransaction()
+                        .replace(R.id.navigation_bar_frame, fragment, TAG)
+                        .commit();
+                fragmentHost.addTagListener(TAG, listener);
+            }
+
+            @Override
+            public void onViewDetachedFromWindow(View v) {
+                FragmentHostManager.removeAndDestroy(v);
+            }
+        });
         context.getSystemService(WindowManager.class).addView(navigationBarView, lp);
-        FragmentHostManager fragmentHost = FragmentHostManager.get(navigationBarView);
-        NavigationBarFragment fragment = new NavigationBarFragment();
-        fragmentHost.getFragmentManager().beginTransaction()
-                .replace(R.id.navigation_bar_frame, fragment, TAG)
-                .commit();
-        fragmentHost.addTagListener(TAG, listener);
         return navigationBarView;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 22b6ba6..7c31dae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -14,6 +14,8 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -34,11 +36,11 @@
 import android.widget.Space;
 
 import com.android.systemui.Dependency;
-import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.phone.ReverseLinearLayout.ReverseRelativeLayout;
 import com.android.systemui.statusbar.policy.KeyButtonView;
 import com.android.systemui.tuner.TunerService;
@@ -48,8 +50,6 @@
 import java.util.List;
 import java.util.Objects;
 
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-
 public class NavigationBarInflaterView extends FrameLayout
         implements Tunable, PluginListener<NavBarButtonProvider> {
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index d58b554..12a0cc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -26,7 +26,6 @@
 import android.view.IWindowManager;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.View.OnLayoutChangeListener;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 6728f08..2f58ca1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -17,10 +17,15 @@
 package com.android.systemui.statusbar.phone;
 
 import static android.view.MotionEvent.ACTION_DOWN;
+
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION;
 
 import android.animation.LayoutTransition;
 import android.animation.LayoutTransition.TransitionListener;
@@ -38,9 +43,11 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.MotionEvent;
@@ -49,6 +56,7 @@
 import android.view.ViewGroup;
 import android.view.WindowInsets;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import android.view.inputmethod.InputMethodManager;
@@ -57,15 +65,15 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.DockedStackExistsListener;
 import com.android.systemui.Interpolators;
-import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.plugins.statusbar.phone.NavGesture;
 import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsOnboarding;
+import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.NavigationBarCompat;
 import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -76,11 +84,6 @@
 import java.io.PrintWriter;
 import java.util.function.Consumer;
 
-import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
-import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION;
-
 public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture> {
     final static boolean DEBUG = false;
     final static String TAG = "StatusBar/NavBarView";
@@ -143,6 +146,10 @@
     private RecentsOnboarding mRecentsOnboarding;
     private NotificationPanelView mPanelView;
 
+    private QuickScrubAction mQuickScrubAction;
+    private QuickStepAction mQuickStepAction;
+    private NavigationBackAction mBackAction;
+
     /**
      * Helper that is responsible for showing the right toast when a disallowed activity operation
      * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
@@ -257,8 +264,7 @@
     public NavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        mDisplay = ((WindowManager) context.getSystemService(
-                Context.WINDOW_SERVICE)).getDefaultDisplay();
+        mDisplay = context.getDisplay();
 
         mVertical = false;
         mLongClickableAccessibilityButton = false;
@@ -299,6 +305,10 @@
         mButtonDispatchers.put(R.id.rotate_suggestion, rotateSuggestionButton);
         mButtonDispatchers.put(R.id.menu_container, mContextualButtonGroup);
         mDeadZone = new DeadZone(this);
+
+        mQuickScrubAction = new QuickScrubAction(this, mOverviewProxyService);
+        mQuickStepAction = new QuickStepAction(this, mOverviewProxyService);
+        mBackAction = new NavigationBackAction(this, mOverviewProxyService);
     }
 
     public BarTransitions getBarTransitions() {
@@ -313,6 +323,8 @@
         mPanelView = panel;
         if (mGestureHelper instanceof QuickStepController) {
             ((QuickStepController) mGestureHelper).setComponents(this);
+            ((QuickStepController) mGestureHelper).setGestureActions(mQuickStepAction,
+                    null /* swipeDownAction*/, mBackAction, mQuickScrubAction);
         }
     }
 
@@ -756,24 +768,6 @@
         mRecentsOnboarding.hide(true);
     }
 
-    /**
-     * @return the button at the given {@param x} and {@param y}.
-     */
-    ButtonDispatcher getButtonAtPosition(int x, int y) {
-        for (int i = 0; i < mButtonDispatchers.size(); i++) {
-            ButtonDispatcher button = mButtonDispatchers.valueAt(i);
-            View buttonView = button.getCurrentView();
-            if (buttonView != null) {
-                buttonView.getHitRect(mTmpRect);
-                offsetDescendantRectToMyCoords(buttonView, mTmpRect);
-                if (mTmpRect.contains(x, y)) {
-                    return button;
-                }
-            }
-        }
-        return null;
-    }
-
     @Override
     public void onFinishInflate() {
         mNavigationInflaterView = findViewById(R.id.navigation_inflater);
@@ -908,7 +902,13 @@
     private void updateTaskSwitchHelper() {
         if (mGestureHelper == null) return;
         boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
-        mGestureHelper.setBarState(mVertical, isRtl);
+        int navBarPos = 0;
+        try {
+            navBarPos = WindowManagerGlobal.getWindowManagerService().getNavBarPosition();
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to get nav bar position.", e);
+        }
+        mGestureHelper.setBarState(isRtl, navBarPos);
     }
 
     @Override
@@ -1112,6 +1112,14 @@
 
         mContextualButtonGroup.dump(pw);
         if (mGestureHelper != null) {
+            pw.println("Navigation Gesture Actions {");
+            pw.print("    "); pw.println("QuickScrub Enabled=" + mQuickScrubAction.isEnabled());
+            pw.print("    "); pw.println("QuickScrub Active=" + mQuickScrubAction.isActive());
+            pw.print("    "); pw.println("QuickStep Enabled=" + mQuickStepAction.isEnabled());
+            pw.print("    "); pw.println("QuickStep Active=" + mQuickStepAction.isActive());
+            pw.print("    "); pw.println("Back Gesture Enabled=" + mBackAction.isEnabled());
+            pw.print("    "); pw.println("Back Gesture Active=" + mBackAction.isActive());
+            pw.println("}");
             mGestureHelper.dump(pw);
         }
         mRecentsOnboarding.dump(pw);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
new file mode 100644
index 0000000..83067f6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
+
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.view.MotionEvent;
+
+import com.android.systemui.recents.OverviewProxyService;
+
+/**
+ * A gesture action that would be triggered and reassigned by {@link QuickStepController}
+ */
+public abstract class NavigationGestureAction {
+
+    protected final NavigationBarView mNavigationBarView;
+    protected final OverviewProxyService mProxySender;
+
+    protected int mNavigationBarPosition;
+    protected boolean mDragHorizontalPositive;
+    protected boolean mDragVerticalPositive;
+    private boolean mIsActive;
+
+    public NavigationGestureAction(@NonNull NavigationBarView navigationBarView,
+            @NonNull OverviewProxyService service) {
+        mNavigationBarView = navigationBarView;
+        mProxySender = service;
+    }
+
+    /**
+     * Pass event that the state of the bar (such as rotation) has changed
+     * @param changed if rotation or drag positive direction (such as ltr) has changed
+     * @param navBarPos position of navigation bar
+     * @param dragHorPositive direction of positive horizontal drag, could change with ltr changes
+     * @param dragVerPositive direction of positive vertical drag, could change with ltr changes
+     */
+    public void setBarState(boolean changed, int navBarPos, boolean dragHorPositive,
+            boolean dragVerPositive) {
+        mNavigationBarPosition = navBarPos;
+        mDragHorizontalPositive = dragHorPositive;
+        mDragVerticalPositive = dragVerPositive;
+    }
+
+    /**
+     * Resets the state of the action. Called when touch down occurs over the Navigation Bar.
+     */
+    public void reset() {
+        mIsActive = false;
+    }
+
+    /**
+     * Start the gesture and the action will be active
+     * @param event the event that caused the gesture
+     */
+    public void startGesture(MotionEvent event) {
+        mIsActive = true;
+        onGestureStart(event);
+    }
+
+    /**
+     * Gesture has ended with action cancel or up and this action will not be active
+     */
+    public void endGesture() {
+        mIsActive = false;
+        onGestureEnd();
+    }
+
+    /**
+     * If the action is currently active based on the gesture that triggered it. Only one action
+     * can occur at a time
+     * @return whether or not if this action has been triggered
+     */
+    public boolean isActive() {
+        return mIsActive;
+    }
+
+    /**
+     * @return whether or not this action can run if notification shade is shown
+     */
+    public boolean canRunWhenNotificationsShowing() {
+        return true;
+    }
+
+    /**
+     * @return whether or not this action triggers when starting a gesture from a certain hit target
+     * If {@link HIT_TARGET_NONE} is specified then action does not need to be triggered by button
+     */
+    public int requiresTouchDownHitTarget() {
+        return HIT_TARGET_NONE;
+    }
+
+    /**
+     * @return whether or not to move the button that started gesture over with user input drag
+     */
+    public boolean requiresDragWithHitTarget() {
+        return false;
+    }
+
+    /**
+     * Tell if the action is able to execute. Note that {@link #isEnabled()} must be true for this
+     * to be checked. The difference between this and {@link #isEnabled()} is that this dependent
+     * on the state of the navigation bar
+     * @return true if action can execute after gesture activates based on current states
+     */
+    public boolean canPerformAction() {
+        return true;
+    }
+
+    /**
+     * Tell if action is enabled. Compared to {@link #canPerformAction()} this is based on settings
+     * if the action is disabled for a particular gesture. For example a back action can be enabled
+     * however if there is nothing to back to then {@link #canPerformAction()} should return false.
+     * In this way if the action requires {@link #requiresDragWithHitTarget()} then if enabled, the
+     * button can be dragged with a large dampening factor during the gesture but will not activate
+     * the action.
+     * @return true if this action is enabled and can run
+     */
+    public abstract boolean isEnabled();
+
+    protected void onDarkIntensityChange(float intensity) {
+    }
+
+    protected void onDraw(Canvas canvas) {
+    }
+
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+    }
+
+    /**
+     * When gesture starts, this will run to execute the action
+     * @param event the event that triggered the gesture
+     */
+    protected abstract void onGestureStart(MotionEvent event);
+
+    /**
+     * Channels motion move events to the action to track the user inputs
+     * @param x the x position
+     * @param y the y position
+     */
+    public void onGestureMove(int x, int y) {
+    }
+
+    /**
+     * When gesture ends, this will run from action up or cancel
+     */
+    protected void onGestureEnd() {
+    }
+
+    protected Context getContext() {
+        return mNavigationBarView.getContext();
+    }
+
+    protected boolean isNavBarVertical() {
+        return mNavigationBarPosition == NAV_BAR_LEFT || mNavigationBarPosition == NAV_BAR_RIGHT;
+    }
+
+    protected boolean getGlobalBoolean(@NonNull String key) {
+        return QuickStepController.getBoolGlobalSetting(getContext(), key);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
index 1524f80..2a11c26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
@@ -16,17 +16,14 @@
 
 import android.content.Context;
 import android.content.res.Configuration;
-import android.graphics.Rect;
-import androidx.annotation.VisibleForTesting;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.Pair;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
-import com.android.systemui.R;
+import androidx.annotation.VisibleForTesting;
 
 import java.util.ArrayList;
 import java.util.Comparator;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index c08366a..6b12dd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -16,22 +16,24 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.annotation.NonNull;
 import android.app.Notification;
 import android.os.SystemClock;
 import android.service.notification.StatusBarNotification;
-import androidx.annotation.Nullable;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.AlertingNotificationManager;
 import com.android.systemui.statusbar.AmbientPulseManager;
 import com.android.systemui.statusbar.AmbientPulseManager.OnAmbientChangedListener;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 
@@ -48,7 +50,7 @@
  * A class to handle notifications and their corresponding groups.
  */
 public class NotificationGroupManager implements OnHeadsUpChangedListener,
-        OnAmbientChangedListener {
+        OnAmbientChangedListener, StateListener {
 
     private static final String TAG = "NotificationGroupManager";
     private static final long ALERT_TRANSFER_TIMEOUT = 300;
@@ -62,10 +64,8 @@
     private boolean mIsUpdatingUnchangedGroup;
     private HashMap<String, NotificationData.Entry> mPendingNotifications;
 
-    private final StateListener mStateListener = this::setStatusBarState;
-
     public NotificationGroupManager() {
-        Dependency.get(StatusBarStateController.class).addListener(mStateListener);
+        Dependency.get(StatusBarStateController.class).addListener(this);
     }
 
     public void setOnGroupChangeListener(OnGroupChangeListener listener) {
@@ -185,6 +185,7 @@
      * specific alert state logic based off when the state changes.
      * @param isDozing if the device is dozing.
      */
+    @VisibleForTesting
     public void setDozing(boolean isDozing) {
         if (mIsDozing != isDozing) {
             for (NotificationGroup group : mGroupMap.values()) {
@@ -732,6 +733,16 @@
         mPendingNotifications = pendingNotifications;
     }
 
+    @Override
+    public void onStateChanged(int newState) {
+        setStatusBarState(newState);
+    }
+
+    @Override
+    public void onDozingChanged(boolean isDozing) {
+        setDozing(isDozing);
+    }
+
     public static class NotificationGroup {
         public final HashMap<String, NotificationData.Entry> children = new HashMap<>();
         public NotificationData.Entry summary;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index f50e9a2..184766c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -2,7 +2,6 @@
 
 import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
 
-import android.app.NotificationManager;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Color;
@@ -20,7 +19,6 @@
 import com.android.internal.widget.ViewClippingUtil;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.notification.NotificationData;
@@ -50,7 +48,7 @@
         public void onTuningChanged(String key, String newValue) {
             if (key.equals(LOW_PRIORITY)) {
                 mShowLowPriority = "1".equals(newValue)
-                        || !NotificationLockscreenUserManager.AUTO_DEMOTE_NOTIFICATIONS;
+                        || !NotificationUtils.useNewInterruptionModel(mContext);
                 if (mNotificationScrollLayout != null) {
                     updateStatusBarIcons();
                 }
@@ -191,8 +189,7 @@
             return false;
         }
         if (!showLowPriority
-                && mEntryManager.getNotificationData().getImportance(entry.key)
-                < NotificationManager.IMPORTANCE_DEFAULT) {
+                && !mEntryManager.getNotificationData().isHighPriority(entry.notification)) {
             return false;
         }
         if (!StatusBar.isTopLevelChild(entry)) {
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 31facb7..851e6d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -22,7 +22,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.app.ActivityManager;
 import android.app.Fragment;
@@ -41,7 +40,6 @@
 import android.os.PowerManager;
 import android.os.SystemProperties;
 import android.util.AttributeSet;
-import android.util.FloatProperty;
 import android.util.Log;
 import android.util.MathUtils;
 import android.view.LayoutInflater;
@@ -51,7 +49,6 @@
 import android.view.ViewGroup;
 import android.view.WindowInsets;
 import android.view.accessibility.AccessibilityManager;
-import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
 
 import com.android.internal.logging.MetricsLogger;
@@ -104,7 +101,7 @@
         View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
         KeyguardAffordanceHelper.Callback, NotificationStackScrollLayout.OnEmptySpaceClickListener,
         OnHeadsUpChangedListener, QS.HeightListener, ZenModeController.Callback,
-        ConfigurationController.ConfigurationListener {
+        ConfigurationController.ConfigurationListener, StateListener {
 
     private static final boolean DEBUG = false;
 
@@ -139,25 +136,9 @@
 
     private static final Rect mDummyDirtyRect = new Rect(0, 0, 1, 1);
 
-    public static final long DOZE_ANIMATION_DURATION = 700;
-
     private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties()
             .setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-    private static final FloatProperty<NotificationPanelView> SET_DARK_AMOUNT_PROPERTY =
-            new FloatProperty<NotificationPanelView>("mInterpolatedDarkAmount") {
 
-                @Override
-                public void setValue(NotificationPanelView object, float value) {
-                    object.setDarkAmount(value, object.mDarkInterpolator.getInterpolation(value));
-                }
-
-                @Override
-                public Float get(NotificationPanelView object) {
-                    return object.mLinearDarkAmount;
-                }
-            };
-
-    private Interpolator mDarkInterpolator;
     private final PowerManager mPowerManager;
     private final AccessibilityManager mAccessibilityManager;
 
@@ -295,11 +276,9 @@
      */
     private boolean mSemiAwake;
 
-    private float mDarkAmountTarget;
     private boolean mPulsing;
     private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
     private boolean mNoVisibleNotifications = true;
-    private ValueAnimator mDarkAnimator;
     private boolean mUserSetupComplete;
     private int mQsNotificationTopPadding;
     private float mExpandOffset;
@@ -339,7 +318,6 @@
     private final NotificationEntryManager mEntryManager =
             Dependency.get(NotificationEntryManager.class);
 
-    private final StateListener mListener = this::setBarState;
     private final CommandQueue mCommandQueue;
     private final NotificationLockscreenUserManager mLockscreenUserManager =
             Dependency.get(NotificationLockscreenUserManager.class);
@@ -388,7 +366,7 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         FragmentHostManager.get(this).addTagListener(QS.TAG, mFragmentListener);
-        Dependency.get(StatusBarStateController.class).addListener(mListener);
+        Dependency.get(StatusBarStateController.class).addListener(this);
         Dependency.get(ZenModeController.class).addCallback(this);
         Dependency.get(ConfigurationController.class).addCallback(this);
     }
@@ -397,7 +375,7 @@
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         FragmentHostManager.get(this).removeTagListener(QS.TAG, mFragmentListener);
-        Dependency.get(StatusBarStateController.class).removeListener(mListener);
+        Dependency.get(StatusBarStateController.class).removeListener(this);
         Dependency.get(ZenModeController.class).removeCallback(this);
         Dependency.get(ConfigurationController.class).removeCallback(this);
     }
@@ -475,7 +453,8 @@
         mKeyguardBottomArea.initFrom(oldBottomArea);
         addView(mKeyguardBottomArea, index);
         initBottomArea();
-        setDarkAmount(mLinearDarkAmount, mInterpolatedDarkAmount);
+        onDozeAmountChanged(mStatusBarStateController.getDozeAmount(),
+                mStatusBarStateController.getInterpolatedDozeAmount());
 
         if (mKeyguardStatusBar != null) {
             mKeyguardStatusBar.onThemeChanged();
@@ -582,7 +561,7 @@
         int stackScrollerPadding;
         if (mBarState != StatusBarState.KEYGUARD) {
             stackScrollerPadding = (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight
-            +  mQsNotificationTopPadding;
+                    + mQsNotificationTopPadding;
         } else {
             int totalHeight = getHeight();
             int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
@@ -754,7 +733,7 @@
             mQsExpandImmediate = true;
             mNotificationStackScroller.setShouldShowShelfOnly(true);
         }
-        if (isFullyCollapsed()){
+        if (isFullyCollapsed()) {
             expand(true /* animate */);
         } else {
             flingSettings(0 /* velocity */, FLING_EXPAND);
@@ -921,7 +900,7 @@
     }
 
     private boolean flingExpandsQs(float vel) {
-        if (isFalseTouch()) {
+        if (mFalsingManager.isUnlockingDisabled() || isFalseTouch()) {
             return false;
         }
         if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
@@ -1046,11 +1025,11 @@
 
         final boolean stylusButtonClickDrag = action == MotionEvent.ACTION_DOWN
                 && (event.isButtonPressed(MotionEvent.BUTTON_STYLUS_PRIMARY)
-                        || event.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY));
+                || event.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY));
 
         final boolean mouseButtonClickDrag = action == MotionEvent.ACTION_DOWN
                 && (event.isButtonPressed(MotionEvent.BUTTON_SECONDARY)
-                        || event.isButtonPressed(MotionEvent.BUTTON_TERTIARY));
+                || event.isButtonPressed(MotionEvent.BUTTON_TERTIARY));
 
         return twoFingerDrag || stylusButtonClickDrag || mouseButtonClickDrag;
     }
@@ -1221,7 +1200,8 @@
         }
     }
 
-    private void setBarState(int statusBarState) {
+    @Override
+    public void onStateChanged(int statusBarState) {
         boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
         boolean keyguardFadingAway = mKeyguardMonitor.isKeyguardFadingAway();
         int oldState = mBarState;
@@ -1321,12 +1301,12 @@
 
     private final ValueAnimator.AnimatorUpdateListener mStatusBarAnimateAlphaListener =
             new ValueAnimator.AnimatorUpdateListener() {
-        @Override
-        public void onAnimationUpdate(ValueAnimator animation) {
-            mKeyguardStatusBarAnimateAlpha = (float) animation.getAnimatedValue();
-            updateHeaderKeyguardAlpha();
-        }
-    };
+                @Override
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    mKeyguardStatusBarAnimateAlpha = (float) animation.getAnimatedValue();
+                    updateHeaderKeyguardAlpha();
+                }
+            };
 
     private void animateKeyguardStatusBarIn(long duration) {
         mKeyguardStatusBar.setVisibility(View.VISIBLE);
@@ -1382,7 +1362,7 @@
             if (keyguardFadingAway) {
                 mKeyguardStatusView.animate()
                         .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
-                        .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration()/2)
+                        .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration() / 2)
                         .start();
             }
         } else if (mBarState == StatusBarState.SHADE_LOCKED
@@ -1425,8 +1405,8 @@
         updateEmptyShadeView();
         mQsNavbarScrim.setVisibility(mBarState == StatusBarState.SHADE && mQsExpanded
                 && !mStackScrollerOverscrolling && mQsScrimEnabled
-                        ? View.VISIBLE
-                        : View.INVISIBLE);
+                ? View.VISIBLE
+                : View.INVISIBLE);
         if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) {
             mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */);
         }
@@ -1459,7 +1439,8 @@
             setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
         }
 
-        if (mQsFullyExpanded && mFalsingManager.shouldEnforceBouncer()) {
+        if (!mFalsingManager.isUnlockingDisabled() && mQsFullyExpanded
+                && mFalsingManager.shouldEnforceBouncer()) {
             mStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
                     false /* dismissShade */, true /* afterKeyguardGone */, false /* deferred */);
         }
@@ -2130,8 +2111,7 @@
                     }
                 }, null, true /* dismissShade */, false /* afterKeyguardGone */,
                         true /* deferred */);
-            }
-            else {
+            } else {
                 mKeyguardBottomArea.launchLeftAffordance();
             }
         } else {
@@ -2588,7 +2568,7 @@
         x = Math.min(rightMost, Math.max(leftMost, x));
         setVerticalPanelTranslation(x -
                 (mNotificationStackScroller.getLeft() + mNotificationStackScroller.getWidth() / 2));
-     }
+    }
 
     private void resetVerticalPanelPosition() {
         setVerticalPanelTranslation(0f);
@@ -2716,8 +2696,8 @@
         String packageToLaunch = (resolveInfo == null || resolveInfo.activityInfo == null)
                 ? null : resolveInfo.activityInfo.packageName;
         return packageToLaunch != null &&
-               (keyguardIsShowing || !isForegroundApp(packageToLaunch)) &&
-               !mAffordanceHelper.isSwipingInProgress();
+                (keyguardIsShowing || !isForegroundApp(packageToLaunch))
+                && !mAffordanceHelper.isSwipingInProgress();
     }
 
     /**
@@ -2806,24 +2786,12 @@
             updateDozingVisibilities(animate);
         }
 
-        final float darkAmount = dozing ? 1 : 0;
-        if (mDarkAnimator != null && mDarkAnimator.isRunning()) {
-            if (animate && mDarkAmountTarget == darkAmount) {
-                return;
-            } else {
-                mDarkAnimator.cancel();
-            }
-            if (mSemiAwake) {
-                setDarkAmount(0, 0);
-            }
-        }
-        mDarkAmountTarget = darkAmount;
+        final float darkAmount = dozing && !mSemiAwake ? 1 : 0;
         if (!mSemiAwake) {
-            if (animate) {
-                startDarkAnimation();
-            } else {
-                setDarkAmount(darkAmount, darkAmount);
-            }
+            mStatusBarStateController.setDozeAmount(darkAmount, animate);
+        }
+        if (animate) {
+            mNotificationStackScroller.notifyDarkAnimationStart(mDozing);
         }
     }
 
@@ -2831,21 +2799,8 @@
         return mSemiAwake;
     }
 
-    private void startDarkAnimation() {
-        if (mInterpolatedDarkAmount == 0f || mInterpolatedDarkAmount == 1f) {
-            mDarkInterpolator = mDozing
-                    ? Interpolators.FAST_OUT_SLOW_IN
-                    : Interpolators.TOUCH_RESPONSE_REVERSE;
-        }
-        mNotificationStackScroller.notifyDarkAnimationStart(mDozing);
-        mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, mDozing ? 1 : 0);
-        mDarkAnimator.setInterpolator(Interpolators.LINEAR);
-        mDarkAnimator.setDuration(
-                mNotificationStackScroller.getDarkAnimationDuration(mDozing));
-        mDarkAnimator.start();
-    }
-
-    private void setDarkAmount(float linearAmount, float amount) {
+    @Override
+    public void onDozeAmountChanged(float linearAmount, float amount) {
         mInterpolatedDarkAmount = amount;
         mLinearDarkAmount = linearAmount;
         mKeyguardStatusBar.setDarkAmount(mInterpolatedDarkAmount);
@@ -2884,13 +2839,14 @@
     }
 
     public void setStatusAccessibilityImportance(int mode) {
-         mKeyguardStatusView.setImportantForAccessibility(mode);
+        mKeyguardStatusView.setImportantForAccessibility(mode);
     }
 
     /**
      * TODO: this should be removed.
      * It's not correct to pass this view forward because other classes will end up adding
      * children to it. Theme will be out of sync.
+     *
      * @return bottom area view
      */
     public KeyguardBottomAreaView getKeyguardBottomAreaView() {
@@ -2980,6 +2936,7 @@
     }
 
     public void updateNotificationViews() {
+        mNotificationStackScroller.updateSectionBoundaries();
         mNotificationStackScroller.updateSpeedBumpIndex();
         mNotificationStackScroller.updateFooter();
         updateShowEmptyShadeView();
@@ -3045,7 +3002,8 @@
             mSemiAwake = false;
             mNotificationStackScroller.setDark(false /* dark */, true /* animate */,
                     null /* touchLocation */);
-            startDarkAnimation();
+            mStatusBarStateController.setDozeAmount(0f, true /* animated */);
+            mNotificationStackScroller.notifyDarkAnimationStart(mDozing);
             mStatusBar.updateScrimController();
 
             return WAKE_UP_TO_SHADE;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
index e7ede6f..ca762cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -20,7 +20,6 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Canvas;
-import androidx.annotation.DimenRes;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewStub;
@@ -28,6 +27,8 @@
 import android.view.WindowInsets;
 import android.widget.FrameLayout;
 
+import androidx.annotation.DimenRes;
+
 import com.android.systemui.R;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index deac669e..65b0ecc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -22,7 +22,6 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.MotionEvent;
-import android.view.View;
 import android.widget.FrameLayout;
 
 public abstract class PanelBar extends FrameLayout {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index f29b7ca..021b430 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -670,6 +670,10 @@
      * @return whether a fling should expands the panel; contracts otherwise
      */
     protected boolean flingExpands(float vel, float vectorVel, float x, float y) {
+        if (mFalsingManager.isUnlockingDisabled()) {
+            return true;
+        }
+
         if (isFalseTouch(x, y)) {
             return true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 0e6efc8..c84f3db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -66,6 +66,8 @@
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.UiOffloadThread;
+import com.android.systemui.privacy.PrivacyItem;
+import com.android.systemui.privacy.PrivacyItemController;
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.qs.tiles.RotationLockTile;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -101,7 +103,8 @@
  */
 public class PhoneStatusBarPolicy implements Callback, Callbacks,
         RotationLockControllerCallback, Listener, LocationChangeCallback,
-        ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback {
+        ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback,
+        PrivacyItemController.Callback {
     private static final String TAG = "PhoneStatusBarPolicy";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -120,6 +123,8 @@
     private final String mSlotHeadset;
     private final String mSlotDataSaver;
     private final String mSlotLocation;
+    private final String mSlotMicrophone;
+    private final String mSlotCamera;
 
     private final Context mContext;
     private final Handler mHandler = new Handler();
@@ -136,6 +141,7 @@
     private final DeviceProvisionedController mProvisionedController;
     private final KeyguardMonitor mKeyguardMonitor;
     private final LocationController mLocationController;
+    private final PrivacyItemController mPrivacyItemController;
     private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
     private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
@@ -169,6 +175,7 @@
         mProvisionedController = Dependency.get(DeviceProvisionedController.class);
         mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
         mLocationController = Dependency.get(LocationController.class);
+        mPrivacyItemController = new PrivacyItemController(mContext, this);
 
         mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
         mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -183,6 +190,8 @@
         mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
         mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
         mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location);
+        mSlotMicrophone = context.getString(com.android.internal.R.string.status_bar_microphone);
+        mSlotCamera = context.getString(com.android.internal.R.string.status_bar_camera);
 
         // listen for broadcasts
         IntentFilter filter = new IntentFilter();
@@ -241,6 +250,12 @@
                 context.getString(R.string.accessibility_data_saver_on));
         mIconController.setIconVisibility(mSlotDataSaver, false);
 
+        // privacy items
+        mIconController.setIcon(mSlotMicrophone, R.drawable.stat_sys_mic_none, null);
+        mIconController.setIconVisibility(mSlotMicrophone, false);
+        mIconController.setIcon(mSlotCamera, R.drawable.stat_sys_camera, null);
+        mIconController.setIconVisibility(mSlotCamera, false);
+
         mRotationLockController.addCallback(this);
         mBluetooth.addCallback(this);
         mProvisionedController.addCallback(this);
@@ -251,6 +266,7 @@
         mDataSaver.addCallback(this);
         mKeyguardMonitor.addCallback(this);
         mLocationController.addCallback(this);
+        mPrivacyItemController.setListening(true);
 
         SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallbacks(this);
         ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener);
@@ -279,6 +295,7 @@
         mDataSaver.removeCallback(this);
         mKeyguardMonitor.removeCallback(this);
         mLocationController.removeCallback(this);
+        mPrivacyItemController.setListening(false);
         SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallbacks(this);
         mContext.unregisterReceiver(mIntentReceiver);
 
@@ -798,6 +815,34 @@
         mIconController.setIconVisibility(mSlotDataSaver, isDataSaving);
     }
 
+    @Override  // PrivacyItemController.Callback
+    public void privacyChanged(List<PrivacyItem> privacyItems) {
+        updatePrivacyItems(privacyItems);
+    }
+
+    private void updatePrivacyItems(List<PrivacyItem> items) {
+        boolean showCamera = false;
+        boolean showMicrophone = false;
+        boolean showLocation = false;
+        for (PrivacyItem item : items) {
+            switch (item.getPrivacyType()) {
+                case TYPE_CAMERA:
+                    showCamera = true;
+                    break;
+                case TYPE_LOCATION:
+                    showLocation = true;
+                    break;
+                case TYPE_MICROPHONE:
+                    showMicrophone = true;
+                    break;
+            }
+        }
+
+        mIconController.setIconVisibility(mSlotCamera, showCamera);
+        mIconController.setIconVisibility(mSlotMicrophone, showMicrophone);
+        mIconController.setIconVisibility(mSlotLocation, showLocation);
+    }
+
     private final TaskStackChangeListener mTaskListener = new TaskStackChangeListener() {
         @Override
         public void onTaskStackChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
new file mode 100644
index 0000000..74744f1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.android.systemui.Interpolators.ALPHA_IN;
+import static com.android.systemui.Interpolators.ALPHA_OUT;
+import static com.android.systemui.recents.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
+import static com.android.systemui.recents.OverviewProxyService.TAG_OPS;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.annotation.NonNull;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RadialGradient;
+import android.graphics.Rect;
+import android.graphics.Shader;
+import android.os.RemoteException;
+import android.util.FloatProperty;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.recents.utilities.Utilities;
+
+/**
+ * QuickScrub action to send to launcher to start quickscrub gesture
+ */
+public class QuickScrubAction extends NavigationGestureAction {
+    private static final String TAG = "QuickScrubAction";
+
+    private static final float TRACK_SCALE = 0.95f;
+    private static final float GRADIENT_WIDTH = .75f;
+    private static final int ANIM_IN_DURATION_MS = 150;
+    private static final int ANIM_OUT_DURATION_MS = 134;
+
+    private AnimatorSet mTrackAnimator;
+    private View mCurrentNavigationBarView;
+
+    private float mTrackScale = TRACK_SCALE;
+    private float mTrackAlpha;
+    private float mHighlightCenter;
+    private float mDarkIntensity;
+
+    private final int mTrackThickness;
+    private final int mTrackEndPadding;
+    private final Paint mTrackPaint = new Paint();
+    private final Rect mTrackRect = new Rect();
+
+    private final FloatProperty<QuickScrubAction> mTrackAlphaProperty =
+            new FloatProperty<QuickScrubAction>("TrackAlpha") {
+        @Override
+        public void setValue(QuickScrubAction action, float alpha) {
+            mTrackAlpha = alpha;
+            mNavigationBarView.invalidate();
+        }
+
+        @Override
+        public Float get(QuickScrubAction action) {
+            return mTrackAlpha;
+        }
+    };
+
+    private final FloatProperty<QuickScrubAction> mTrackScaleProperty =
+            new FloatProperty<QuickScrubAction>("TrackScale") {
+        @Override
+        public void setValue(QuickScrubAction action, float scale) {
+            mTrackScale = scale;
+            mNavigationBarView.invalidate();
+        }
+
+        @Override
+        public Float get(QuickScrubAction action) {
+            return mTrackScale;
+        }
+    };
+
+    private final FloatProperty<QuickScrubAction> mNavBarAlphaProperty =
+            new FloatProperty<QuickScrubAction>("NavBarAlpha") {
+        @Override
+        public void setValue(QuickScrubAction action, float alpha) {
+            if (mCurrentNavigationBarView != null) {
+                mCurrentNavigationBarView.setAlpha(alpha);
+            }
+        }
+
+        @Override
+        public Float get(QuickScrubAction action) {
+            if (mCurrentNavigationBarView != null) {
+                return mCurrentNavigationBarView.getAlpha();
+            }
+            return 1f;
+        }
+    };
+
+    private AnimatorListenerAdapter mQuickScrubEndListener = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            if (mCurrentNavigationBarView != null) {
+                mCurrentNavigationBarView.setAlpha(1f);
+            }
+            mCurrentNavigationBarView = null;
+            updateHighlight();
+        }
+    };
+
+    public QuickScrubAction(@NonNull NavigationBarView navigationBarView,
+            @NonNull OverviewProxyService service) {
+        super(navigationBarView, service);
+        mTrackPaint.setAntiAlias(true);
+        mTrackPaint.setDither(true);
+
+        final Resources res = navigationBarView.getResources();
+        mTrackThickness = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_thickness);
+        mTrackEndPadding = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_edge_padding);
+    }
+
+    @Override
+    public void setBarState(boolean changed, int navBarPos, boolean dragHorPositive,
+            boolean dragVerPositive) {
+        super.setBarState(changed, navBarPos, dragHorPositive, dragVerPositive);
+        if (changed && isActive()) {
+            // End quickscrub if the state changes mid-transition
+            endQuickScrub(false /* animate */);
+        }
+    }
+
+    @Override
+    public void reset() {
+        super.reset();
+
+        // End any existing quickscrub animations before starting the new transition
+        if (mTrackAnimator != null) {
+            mTrackAnimator.end();
+            mTrackAnimator = null;
+        }
+        mCurrentNavigationBarView = mNavigationBarView.getCurrentView();
+    }
+
+    @Override
+    public void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        final int paddingLeft = mNavigationBarView.getPaddingLeft();
+        final int paddingTop = mNavigationBarView.getPaddingTop();
+        final int paddingRight = mNavigationBarView.getPaddingRight();
+        final int paddingBottom = mNavigationBarView.getPaddingBottom();
+        final int width = (right - left) - paddingRight - paddingLeft;
+        final int height = (bottom - top) - paddingBottom - paddingTop;
+        final int x1, x2, y1, y2;
+        if (isNavBarVertical()) {
+            x1 = (width - mTrackThickness) / 2 + paddingLeft;
+            x2 = x1 + mTrackThickness;
+            y1 = paddingTop + mTrackEndPadding;
+            y2 = y1 + height - 2 * mTrackEndPadding;
+        } else {
+            y1 = (height - mTrackThickness) / 2 + paddingTop;
+            y2 = y1 + mTrackThickness;
+            x1 = mNavigationBarView.getPaddingStart() + mTrackEndPadding;
+            x2 = x1 + width - 2 * mTrackEndPadding;
+        }
+        mTrackRect.set(x1, y1, x2, y2);
+    }
+
+    @Override
+    public void onDarkIntensityChange(float intensity) {
+        mDarkIntensity = intensity;
+        updateHighlight();
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        if (!isEnabled()) {
+            return;
+        }
+        mTrackPaint.setAlpha(Math.round(255f * mTrackAlpha));
+
+        // Scale the track, but apply the inverse scale from the nav bar
+        final float radius = mTrackRect.height() / 2;
+        canvas.save();
+        float translate = Utilities.clamp(mHighlightCenter, mTrackRect.left, mTrackRect.right);
+        canvas.translate(translate, 0);
+        canvas.scale(mTrackScale / mNavigationBarView.getScaleX(),
+                1f / mNavigationBarView.getScaleY(),
+                mTrackRect.centerX(), mTrackRect.centerY());
+        canvas.drawRoundRect(mTrackRect.left - translate, mTrackRect.top,
+                mTrackRect.right - translate, mTrackRect.bottom, radius, radius, mTrackPaint);
+        canvas.restore();
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return mNavigationBarView.isQuickScrubEnabled();
+    }
+
+    @Override
+    protected void onGestureStart(MotionEvent event) {
+        updateHighlight();
+        ObjectAnimator trackAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
+                PropertyValuesHolder.ofFloat(mTrackAlphaProperty, 1f),
+                PropertyValuesHolder.ofFloat(mTrackScaleProperty, 1f));
+        trackAnimator.setInterpolator(ALPHA_IN);
+        trackAnimator.setDuration(ANIM_IN_DURATION_MS);
+        ObjectAnimator navBarAnimator = ObjectAnimator.ofFloat(this, mNavBarAlphaProperty, 0f);
+        navBarAnimator.setInterpolator(ALPHA_OUT);
+        navBarAnimator.setDuration(ANIM_OUT_DURATION_MS);
+        mTrackAnimator = new AnimatorSet();
+        mTrackAnimator.playTogether(trackAnimator, navBarAnimator);
+        mTrackAnimator.start();
+
+        // Disable slippery for quick scrub to not cancel outside the nav bar
+        mNavigationBarView.updateSlippery();
+
+        try {
+            mProxySender.getProxy().onQuickScrubStart();
+            if (DEBUG_OVERVIEW_PROXY) {
+                Log.d(TAG_OPS, "Quick Scrub Start");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to send start of quick scrub.", e);
+        }
+        mProxySender.notifyQuickScrubStarted();
+    }
+
+    @Override
+    public void onGestureMove(int x, int y) {
+        int trackSize, offset;
+        if (isNavBarVertical()) {
+            trackSize = mTrackRect.height();
+            offset = y - mTrackRect.top;
+        } else {
+            offset = x - mTrackRect.left;
+            trackSize = mTrackRect.width();
+        }
+        if (!mDragHorizontalPositive || !mDragVerticalPositive) {
+            offset -= isNavBarVertical() ? mTrackRect.height() : mTrackRect.width();
+        }
+        float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
+        try {
+            mProxySender.getProxy().onQuickScrubProgress(scrubFraction);
+            if (DEBUG_OVERVIEW_PROXY) {
+                Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to send progress of quick scrub.", e);
+        }
+        mHighlightCenter = x;
+        mNavigationBarView.invalidate();
+    }
+
+    @Override
+    protected void onGestureEnd() {
+        endQuickScrub(true /* animate */);
+    }
+
+    private void endQuickScrub(boolean animate) {
+        animateEnd();
+        try {
+            mProxySender.getProxy().onQuickScrubEnd();
+            if (DEBUG_OVERVIEW_PROXY) {
+                Log.d(TAG_OPS, "Quick Scrub End");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to send end of quick scrub.", e);
+        }
+        if (!animate) {
+            if (mTrackAnimator != null) {
+                mTrackAnimator.end();
+                mTrackAnimator = null;
+            }
+        }
+    }
+
+    private void updateHighlight() {
+        if (mTrackRect.isEmpty()) {
+            return;
+        }
+        int colorBase, colorGrad;
+        if (mDarkIntensity > 0.5f) {
+            colorBase = getContext().getColor(R.color.quick_step_track_background_background_dark);
+            colorGrad = getContext().getColor(R.color.quick_step_track_background_foreground_dark);
+        } else {
+            colorBase = getContext().getColor(R.color.quick_step_track_background_background_light);
+            colorGrad = getContext().getColor(R.color.quick_step_track_background_foreground_light);
+        }
+        final RadialGradient mHighlight = new RadialGradient(0, mTrackRect.height() / 2,
+                mTrackRect.width() * GRADIENT_WIDTH, colorGrad, colorBase,
+                Shader.TileMode.CLAMP);
+        mTrackPaint.setShader(mHighlight);
+    }
+
+    private void animateEnd() {
+        if (mTrackAnimator != null) {
+            mTrackAnimator.cancel();
+        }
+
+        ObjectAnimator trackAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
+                PropertyValuesHolder.ofFloat(mTrackAlphaProperty, 0f),
+                PropertyValuesHolder.ofFloat(mTrackScaleProperty, TRACK_SCALE));
+        trackAnimator.setInterpolator(ALPHA_OUT);
+        trackAnimator.setDuration(ANIM_OUT_DURATION_MS);
+        ObjectAnimator navBarAnimator = ObjectAnimator.ofFloat(this, mNavBarAlphaProperty, 1f);
+        navBarAnimator.setInterpolator(ALPHA_IN);
+        navBarAnimator.setDuration(ANIM_IN_DURATION_MS);
+        mTrackAnimator = new AnimatorSet();
+        mTrackAnimator.playTogether(trackAnimator, navBarAnimator);
+        mTrackAnimator.addListener(mQuickScrubEndListener);
+        mTrackAnimator.start();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepAction.java
new file mode 100644
index 0000000..b18b79e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepAction.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.android.systemui.recents.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
+import static com.android.systemui.recents.OverviewProxyService.TAG_OPS;
+
+import android.annotation.NonNull;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.systemui.recents.OverviewProxyService;
+
+/**
+ * QuickStep action to send to launcher to start overview
+ */
+public class QuickStepAction extends NavigationGestureAction {
+    private static final String TAG = "QuickStepAction";
+
+    public QuickStepAction(@NonNull NavigationBarView navigationBarView,
+            @NonNull OverviewProxyService service) {
+        super(navigationBarView, service);
+    }
+
+    @Override
+    public boolean canRunWhenNotificationsShowing() {
+        return false;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return mNavigationBarView.isQuickStepSwipeUpEnabled();
+    }
+
+    @Override
+    public void onGestureStart(MotionEvent event) {
+        try {
+            mProxySender.getProxy().onQuickStep(event);
+            if (DEBUG_OVERVIEW_PROXY) {
+                Log.d(TAG_OPS, "Quick Step Start");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to send quick step started.", e);
+        }
+        mProxySender.notifyQuickStepStarted();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 3980126..0eff4d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -18,187 +18,99 @@
 
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
-import static com.android.systemui.Interpolators.ALPHA_IN;
-import static com.android.systemui.Interpolators.ALPHA_OUT;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
+
 import static com.android.systemui.recents.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
 import static com.android.systemui.recents.OverviewProxyService.TAG_OPS;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.RadialGradient;
-import android.graphics.Rect;
-import android.graphics.Shader;
-import android.hardware.input.InputManager;
-import android.os.Handler;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.provider.Settings;
-import android.util.FloatProperty;
 import android.util.Log;
-import android.util.Slog;
-import android.view.HapticFeedbackConstants;
-import android.view.InputDevice;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewPropertyAnimator;
-import android.view.WindowManagerGlobal;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
-import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.utilities.Utilities;
 import com.android.systemui.shared.system.NavigationBarCompat;
+
 import java.io.PrintWriter;
 
 /**
  * Class to detect gestures on the navigation bar and implement quick scrub.
+ * Note that the variables in this class horizontal and vertical represents horizontal always
+ * aligned with along the navigation bar.
  */
 public class QuickStepController implements GestureHelper {
 
     private static final String TAG = "QuickStepController";
-    private static final int ANIM_IN_DURATION_MS = 150;
-    private static final int ANIM_OUT_DURATION_MS = 134;
-    private static final float TRACK_SCALE = 0.95f;
-    private static final float GRADIENT_WIDTH = .75f;
 
     /** Experiment to swipe home button left to execute a back key press */
-    private static final String PULL_HOME_GO_BACK_PROP = "quickstepcontroller_homegoesback";
     private static final String HIDE_BACK_BUTTON_PROP = "quickstepcontroller_hideback";
-    private static final String BACK_AFTER_END_PROP
-            = "quickstepcontroller_homegoesbackwhenend";
-    private static final String NAVBAR_EXPERIMENTS_DISABLED = "navbarexperiments_disabled";
-    private static final long BACK_BUTTON_FADE_OUT_ALPHA = 60;
     private static final long BACK_BUTTON_FADE_IN_ALPHA = 150;
-    private static final long BACK_GESTURE_POLL_TIMEOUT = 1000;
 
     /** When the home-swipe-back gesture is disallowed, make it harder to pull */
-    private static final float DISALLOW_GESTURE_DAMPING_FACTOR = 0.16f;
+    private static final float HORIZONTAL_GESTURE_DAMPING = 0.3f;
+    private static final float VERTICAL_GESTURE_DAMPING = 0.15f;
+    private static final float HORIZONTAL_DISABLED_GESTURE_DAMPING = 0.16f;
+    private static final float VERTICAL_DISABLED_GESTURE_DAMPING = 0.06f;
+
+    private static final int ACTION_SWIPE_UP_INDEX = 0;
+    private static final int ACTION_SWIPE_DOWN_INDEX = 1;
+    private static final int ACTION_SWIPE_LEFT_INDEX = 2;
+    private static final int ACTION_SWIPE_RIGHT_INDEX = 3;
+    private static final int MAX_GESTURES = 4;
 
     private NavigationBarView mNavigationBarView;
 
-    private boolean mQuickScrubActive;
     private boolean mAllowGestureDetection;
-    private boolean mBackGestureActive;
-    private boolean mCanPerformBack;
-    private boolean mQuickStepStarted;
     private boolean mNotificationsVisibleOnDown;
     private int mTouchDownX;
     private int mTouchDownY;
-    private boolean mDragPositive;
-    private boolean mIsVertical;
+    private boolean mDragHPositive;
+    private boolean mDragVPositive;
     private boolean mIsRTL;
-    private float mTrackAlpha;
-    private float mTrackScale = TRACK_SCALE;
+    private int mNavBarPosition;
     private float mDarkIntensity;
-    private RadialGradient mHighlight;
-    private float mHighlightCenter;
-    private AnimatorSet mTrackAnimator;
-    private ViewPropertyAnimator mHomeAnimator;
+    private ViewPropertyAnimator mDragBtnAnimator;
     private ButtonDispatcher mHitTarget;
-    private View mCurrentNavigationBarView;
     private boolean mIsInScreenPinning;
+    private boolean mGestureHorizontalDragsButton;
+    private boolean mGestureVerticalDragsButton;
+    private float mMaxDragLimit;
+    private float mMinDragLimit;
+    private float mDragDampeningFactor;
 
-    private final Handler mHandler = new Handler();
-    private final Rect mTrackRect = new Rect();
+    private NavigationGestureAction mCurrentAction;
+    private NavigationGestureAction[] mGestureActions = new NavigationGestureAction[MAX_GESTURES];
+
     private final OverviewProxyService mOverviewEventSender;
-    private final int mTrackThickness;
-    private final int mTrackEndPadding;
-    private final int mHomeBackGestureDragLimit;
     private final Context mContext;
     private final StatusBar mStatusBar;
     private final Matrix mTransformGlobalMatrix = new Matrix();
     private final Matrix mTransformLocalMatrix = new Matrix();
-    private final Paint mTrackPaint = new Paint();
-
-    private final FloatProperty<QuickStepController> mTrackAlphaProperty =
-            new FloatProperty<QuickStepController>("TrackAlpha") {
-        @Override
-        public void setValue(QuickStepController controller, float alpha) {
-            mTrackAlpha = alpha;
-            mNavigationBarView.invalidate();
-        }
-
-        @Override
-        public Float get(QuickStepController controller) {
-            return mTrackAlpha;
-        }
-    };
-
-    private final FloatProperty<QuickStepController> mTrackScaleProperty =
-            new FloatProperty<QuickStepController>("TrackScale") {
-        @Override
-        public void setValue(QuickStepController controller, float scale) {
-            mTrackScale = scale;
-            mNavigationBarView.invalidate();
-        }
-
-        @Override
-        public Float get(QuickStepController controller) {
-            return mTrackScale;
-        }
-    };
-
-    private final FloatProperty<QuickStepController> mNavBarAlphaProperty =
-            new FloatProperty<QuickStepController>("NavBarAlpha") {
-        @Override
-        public void setValue(QuickStepController controller, float alpha) {
-            if (mCurrentNavigationBarView != null) {
-                mCurrentNavigationBarView.setAlpha(alpha);
-            }
-        }
-
-        @Override
-        public Float get(QuickStepController controller) {
-            if (mCurrentNavigationBarView != null) {
-                return mCurrentNavigationBarView.getAlpha();
-            }
-            return 1f;
-        }
-    };
-
-    private AnimatorListenerAdapter mQuickScrubEndListener = new AnimatorListenerAdapter() {
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            resetQuickScrub();
-        }
-    };
-
-    private final Runnable mExecuteBackRunnable = new Runnable() {
-        @Override
-        public void run() {
-            if (canPerformHomeBackGesture()) {
-                performBack();
-                mHandler.postDelayed(this, BACK_GESTURE_POLL_TIMEOUT);
-            }
-        }
-    };
 
     public QuickStepController(Context context) {
         final Resources res = context.getResources();
         mContext = context;
         mStatusBar = SysUiServiceProvider.getComponent(context, StatusBar.class);
         mOverviewEventSender = Dependency.get(OverviewProxyService.class);
-        mTrackThickness = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_thickness);
-        mTrackEndPadding = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_edge_padding);
-        mHomeBackGestureDragLimit =
-                res.getDimensionPixelSize(R.dimen.nav_home_back_gesture_drag_limit);
-        mTrackPaint.setAntiAlias(true);
-        mTrackPaint.setDither(true);
     }
 
     public void setComponents(NavigationBarView navigationBarView) {
@@ -210,6 +122,31 @@
     }
 
     /**
+     * Set each gesture an action. After set the gestures triggered will run the actions attached.
+     * @param swipeUpAction action after swiping up
+     * @param swipeDownAction action after swiping down
+     * @param swipeLeftAction action after swiping left
+     * @param swipeRightAction action after swiping right
+     */
+    public void setGestureActions(@Nullable NavigationGestureAction swipeUpAction,
+            @Nullable NavigationGestureAction swipeDownAction,
+            @Nullable NavigationGestureAction swipeLeftAction,
+            @Nullable NavigationGestureAction swipeRightAction) {
+        mGestureActions[ACTION_SWIPE_UP_INDEX] = swipeUpAction;
+        mGestureActions[ACTION_SWIPE_DOWN_INDEX] = swipeDownAction;
+        mGestureActions[ACTION_SWIPE_LEFT_INDEX] = swipeLeftAction;
+        mGestureActions[ACTION_SWIPE_RIGHT_INDEX] = swipeRightAction;
+
+        // Set the current state to all actions
+        for (NavigationGestureAction action: mGestureActions) {
+            if (action != null) {
+                action.setBarState(true, mNavBarPosition, mDragHPositive, mDragVPositive);
+                action.onDarkIntensityChange(mDarkIntensity);
+            }
+        }
+    }
+
+    /**
      * @return true if we want to intercept touch events for quick scrub and prevent proxying the
      *         event to the overview service.
      */
@@ -242,8 +179,10 @@
     private boolean handleTouchEvent(MotionEvent event) {
         final boolean deadZoneConsumed =
                 mNavigationBarView.getDownHitTarget() == HIT_TARGET_DEAD_ZONE;
-        if (mOverviewEventSender.getProxy() == null || (!mNavigationBarView.isQuickScrubEnabled()
-                && !mNavigationBarView.isQuickStepSwipeUpEnabled())) {
+
+        // Requires proxy and an active gesture or able to perform any gesture to continue
+        if (mOverviewEventSender.getProxy() == null
+                || (mCurrentAction == null && !canPerformAnyAction())) {
             return deadZoneConsumed;
         }
         mNavigationBarView.requestUnbufferedDispatch(event);
@@ -255,33 +194,45 @@
                 int y = (int) event.getY();
                 mIsInScreenPinning = mNavigationBarView.inScreenPinning();
 
-                // End any existing quickscrub animations before starting the new transition
-                if (mTrackAnimator != null) {
-                    mTrackAnimator.end();
-                    mTrackAnimator = null;
+                for (NavigationGestureAction gestureAction: mGestureActions) {
+                    if (gestureAction != null) {
+                        gestureAction.reset();
+                    }
                 }
 
-                mCurrentNavigationBarView = mNavigationBarView.getCurrentView();
-                mHitTarget = mNavigationBarView.getButtonAtPosition(x, y);
+                // Valid buttons to drag over
+                switch (mNavigationBarView.getDownHitTarget()) {
+                    case HIT_TARGET_BACK:
+                        mHitTarget = mNavigationBarView.getBackButton();
+                        break;
+                    case HIT_TARGET_HOME:
+                        mHitTarget = mNavigationBarView.getHomeButton();
+                        break;
+                    case HIT_TARGET_OVERVIEW:
+                        mHitTarget = mNavigationBarView.getRecentsButton();
+                        break;
+                    default:
+                        mHitTarget = null;
+                        break;
+                }
                 if (mHitTarget != null) {
                     // Pre-emptively delay the touch feedback for the button that we just touched
                     mHitTarget.setDelayTouchFeedback(true);
                 }
                 mTouchDownX = x;
                 mTouchDownY = y;
+                mGestureHorizontalDragsButton = false;
+                mGestureVerticalDragsButton = false;
                 mTransformGlobalMatrix.set(Matrix.IDENTITY_MATRIX);
                 mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX);
                 mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix);
                 mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
-                mQuickStepStarted = false;
-                mBackGestureActive = false;
                 mAllowGestureDetection = true;
                 mNotificationsVisibleOnDown = !mNavigationBarView.isNotificationsFullyCollapsed();
-                mCanPerformBack = canPerformHomeBackGesture();
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
-                if (mQuickStepStarted || !mAllowGestureDetection){
+                if (!mAllowGestureDetection) {
                     break;
                 }
                 int x = (int) event.getX();
@@ -289,108 +240,120 @@
                 int xDiff = Math.abs(x - mTouchDownX);
                 int yDiff = Math.abs(y - mTouchDownY);
 
-                boolean exceededScrubTouchSlop, exceededSwipeUpTouchSlop;
-                int pos, touchDown, offset, trackSize;
+                boolean exceededSwipeHorizontalTouchSlop, exceededSwipeVerticalTouchSlop;
+                int posH, touchDownH, posV, touchDownV;
 
-                if (mIsVertical) {
-                    exceededScrubTouchSlop =
+                if (isNavBarVertical()) {
+                    exceededSwipeHorizontalTouchSlop =
                             yDiff > NavigationBarCompat.getQuickScrubTouchSlopPx() && yDiff > xDiff;
-                    exceededSwipeUpTouchSlop =
+                    exceededSwipeVerticalTouchSlop =
                             xDiff > NavigationBarCompat.getQuickStepTouchSlopPx() && xDiff > yDiff;
-                    pos = y;
-                    touchDown = mTouchDownY;
-                    offset = pos - mTrackRect.top;
-                    trackSize = mTrackRect.height();
+                    posH = y;
+                    touchDownH = mTouchDownY;
+                    posV = x;
+                    touchDownV = mTouchDownX;
                 } else {
-                    exceededScrubTouchSlop =
+                    exceededSwipeHorizontalTouchSlop =
                             xDiff > NavigationBarCompat.getQuickScrubTouchSlopPx() && xDiff > yDiff;
-                    exceededSwipeUpTouchSlop =
+                    exceededSwipeVerticalTouchSlop =
                             yDiff > NavigationBarCompat.getQuickStepTouchSlopPx() && yDiff > xDiff;
-                    pos = x;
-                    touchDown = mTouchDownX;
-                    offset = pos - mTrackRect.left;
-                    trackSize = mTrackRect.width();
-                }
-                // Decide to start quickstep if dragging away from the navigation bar, otherwise in
-                // the parallel direction, decide to start quickscrub. Only one may run.
-                if (!mBackGestureActive && !mQuickScrubActive && exceededSwipeUpTouchSlop) {
-                    if (mNavigationBarView.isQuickStepSwipeUpEnabled()
-                            && !mNotificationsVisibleOnDown) {
-                        startQuickStep(event);
-                    }
-                    break;
+                    posH = x;
+                    touchDownH = mTouchDownX;
+                    posV = y;
+                    touchDownV = mTouchDownY;
                 }
 
-                // Do not handle quick scrub if disabled
-                if (!mNavigationBarView.isQuickScrubEnabled()) {
-                    break;
-                }
-
-                if (!mDragPositive) {
-                    offset -= mIsVertical ? mTrackRect.height() : mTrackRect.width();
-                }
-
-                final boolean allowDrag = !mDragPositive
-                        ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
-                float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
-                if (!mQuickScrubActive && !mBackGestureActive && exceededScrubTouchSlop) {
-                    // Passing the drag slop then touch slop will start quick step
-                    if (allowDrag) {
-                        startQuickScrub();
-                    } else if (swipeHomeGoBackGestureEnabled(mContext)
-                            && mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME
-                            && mDragPositive ? pos < touchDown : pos > touchDown) {
-                        startBackGesture();
-                    }
-                }
-
-                if (mQuickScrubActive && (mDragPositive && offset >= 0
-                        || !mDragPositive && offset <= 0)) {
-                    try {
-                        mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
-                        if (DEBUG_OVERVIEW_PROXY) {
-                            Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
+                if (mCurrentAction != null) {
+                    // Gesture started, provide positions to the current action
+                    mCurrentAction.onGestureMove(x, y);
+                } else {
+                    // Detect gesture and try to execute an action, only one can run at a time
+                    if (exceededSwipeVerticalTouchSlop) {
+                        if (mDragVPositive ? (posV < touchDownV) : (posV > touchDownV)) {
+                            // Swiping up gesture
+                            tryToStartGesture(mGestureActions[ACTION_SWIPE_UP_INDEX],
+                                    false /* alignedWithNavBar */, false /* positiveDirection */,
+                                    event);
+                        } else {
+                            // Swiping down gesture
+                            tryToStartGesture(mGestureActions[ACTION_SWIPE_DOWN_INDEX],
+                                    false /* alignedWithNavBar */, true /* positiveDirection */,
+                                    event);
                         }
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Failed to send progress of quick scrub.", e);
-                    }
-                    mHighlightCenter = x;
-                    mNavigationBarView.invalidate();
-                } else if (mBackGestureActive) {
-                    int diff = pos - touchDown;
-                    // If dragging the incorrect direction after starting back gesture or unable
-                    // to execute back functionality, then move home but dampen its distance
-                    if (!mCanPerformBack || (mDragPositive ? diff > 0 : diff < 0)) {
-                        diff *= DISALLOW_GESTURE_DAMPING_FACTOR;
-                    } if (Math.abs(diff) > mHomeBackGestureDragLimit) {
-                        // Once the user drags the home button past a certain limit, the distance
-                        // will lessen as the home button dampens showing that it was pulled too far
-                        float distanceAfterDragLimit = (Math.abs(diff) - mHomeBackGestureDragLimit)
-                                * DISALLOW_GESTURE_DAMPING_FACTOR;
-                        diff = (int)(distanceAfterDragLimit + mHomeBackGestureDragLimit);
-                        if (mDragPositive) {
-                            diff *= -1;
+                    } else if (exceededSwipeHorizontalTouchSlop) {
+                        if (mDragHPositive ? (posH < touchDownH) : (posH > touchDownH)) {
+                            // Swiping left (ltr) gesture
+                            tryToStartGesture(mGestureActions[ACTION_SWIPE_LEFT_INDEX],
+                                    true /* alignedWithNavBar */, false /* positiveDirection */,
+                                    event);
+                        } else {
+                            // Swiping right (ltr) gesture
+                            tryToStartGesture(mGestureActions[ACTION_SWIPE_RIGHT_INDEX],
+                                    true /* alignedWithNavBar */, true /* positiveDirection */,
+                                    event);
                         }
                     }
-                    moveHomeButton(diff);
                 }
+
+                handleDragHitTarget(mGestureHorizontalDragsButton ? posH : posV,
+                        mGestureHorizontalDragsButton ? touchDownH : touchDownV);
                 break;
             }
             case MotionEvent.ACTION_CANCEL:
             case MotionEvent.ACTION_UP:
-                endQuickScrub(true /* animate */);
-                endBackGesture();
+                if (mCurrentAction != null) {
+                    mCurrentAction.endGesture();
+                    mCurrentAction = null;
+                }
+
+                // Return the hit target back to its original position
+                if (mHitTarget != null) {
+                    final View button = mHitTarget.getCurrentView();
+                    if (mGestureHorizontalDragsButton || mGestureVerticalDragsButton) {
+                        mDragBtnAnimator = button.animate().setDuration(BACK_BUTTON_FADE_IN_ALPHA)
+                                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+                        if (mGestureVerticalDragsButton ^ isNavBarVertical()) {
+                            mDragBtnAnimator.translationY(0);
+                        } else {
+                            mDragBtnAnimator.translationX(0);
+                        }
+                        mDragBtnAnimator.start();
+                    }
+                }
                 break;
         }
 
         if (shouldProxyEvents(action)) {
             proxyMotionEvents(event);
         }
-        return mBackGestureActive || mQuickScrubActive || mQuickStepStarted || deadZoneConsumed;
+        return mCurrentAction != null || deadZoneConsumed;
+    }
+
+    private void handleDragHitTarget(int position, int touchDown) {
+        // Drag the hit target if gesture action requires it
+        if (mHitTarget != null && (mGestureVerticalDragsButton || mGestureHorizontalDragsButton)) {
+            final View button = mHitTarget.getCurrentView();
+            if (mDragBtnAnimator != null) {
+                mDragBtnAnimator.cancel();
+                mDragBtnAnimator = null;
+            }
+
+            // Clamp drag to the bounding box of the navigation bar
+            float diff = (position - touchDown) * mDragDampeningFactor;
+            diff = Utilities.clamp(diff, mMinDragLimit, mMaxDragLimit);
+            if (mGestureVerticalDragsButton ^ isNavBarVertical()) {
+                button.setTranslationY(diff);
+            } else {
+                button.setTranslationX(diff);
+            }
+        }
     }
 
     private boolean shouldProxyEvents(int action) {
-        if (!mBackGestureActive && !mQuickScrubActive && !mIsInScreenPinning) {
+        final boolean actionValid = (mCurrentAction == null
+                || (mGestureActions[ACTION_SWIPE_UP_INDEX] != null
+                        && mGestureActions[ACTION_SWIPE_UP_INDEX].isActive()));
+        if (actionValid && !mIsInScreenPinning) {
             // Allow down, cancel and up events, move and other events are passed if notifications
             // are not showing and disabled gestures (such as long press) are not executed
             switch (action) {
@@ -407,46 +370,18 @@
 
     @Override
     public void onDraw(Canvas canvas) {
-        if (!mNavigationBarView.isQuickScrubEnabled()) {
-            return;
+        if (mCurrentAction != null) {
+            mCurrentAction.onDraw(canvas);
         }
-        mTrackPaint.setAlpha(Math.round(255f * mTrackAlpha));
-
-        // Scale the track, but apply the inverse scale from the nav bar
-        final float radius = mTrackRect.height() / 2;
-        canvas.save();
-        float translate = Utilities.clamp(mHighlightCenter, mTrackRect.left, mTrackRect.right);
-        canvas.translate(translate, 0);
-        canvas.scale(mTrackScale / mNavigationBarView.getScaleX(),
-                1f / mNavigationBarView.getScaleY(),
-                mTrackRect.centerX(), mTrackRect.centerY());
-        canvas.drawRoundRect(mTrackRect.left - translate, mTrackRect.top,
-                mTrackRect.right - translate, mTrackRect.bottom, radius, radius, mTrackPaint);
-        canvas.restore();
     }
 
     @Override
     public void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        final int paddingLeft = mNavigationBarView.getPaddingLeft();
-        final int paddingTop = mNavigationBarView.getPaddingTop();
-        final int paddingRight = mNavigationBarView.getPaddingRight();
-        final int paddingBottom = mNavigationBarView.getPaddingBottom();
-        final int width = (right - left) - paddingRight - paddingLeft;
-        final int height = (bottom - top) - paddingBottom - paddingTop;
-        final int x1, x2, y1, y2;
-        if (mIsVertical) {
-            x1 = (width - mTrackThickness) / 2 + paddingLeft;
-            x2 = x1 + mTrackThickness;
-            y1 = paddingTop + mTrackEndPadding;
-            y2 = y1 + height - 2 * mTrackEndPadding;
-        } else {
-            y1 = (height - mTrackThickness) / 2 + paddingTop;
-            y2 = y1 + mTrackThickness;
-            x1 = mNavigationBarView.getPaddingStart() + mTrackEndPadding;
-            x2 = x1 + width - 2 * mTrackEndPadding;
+        for (NavigationGestureAction action: mGestureActions) {
+            if (action != null) {
+                action.onLayout(changed, left, top, right, bottom);
+            }
         }
-        mTrackRect.set(x1, y1, x2, y2);
-        updateHighlight();
     }
 
     @Override
@@ -456,119 +391,126 @@
 
         // When in quick scrub, invalidate gradient if changing intensity from black to white and
         // vice-versa
-        if (mNavigationBarView.isQuickScrubEnabled()
+        if (mCurrentAction != null && mNavigationBarView.isQuickScrubEnabled()
                 && Math.round(intensity) != Math.round(oldIntensity)) {
-            updateHighlight();
+            mCurrentAction.onDarkIntensityChange(mDarkIntensity);
         }
         mNavigationBarView.invalidate();
     }
 
     @Override
-    public void setBarState(boolean isVertical, boolean isRTL) {
-        final boolean changed = (mIsVertical != isVertical) || (mIsRTL != isRTL);
-        if (changed) {
-            // End quickscrub if the state changes mid-transition
-            endQuickScrub(false /* animate */);
-        }
-        mIsVertical = isVertical;
+    public void setBarState(boolean isRTL, int navBarPosition) {
+        final boolean changed = (mIsRTL != isRTL) || (mNavBarPosition != navBarPosition);
         mIsRTL = isRTL;
-        try {
-            int navbarPos = WindowManagerGlobal.getWindowManagerService().getNavBarPosition();
-            mDragPositive = navbarPos == NAV_BAR_LEFT || navbarPos == NAV_BAR_BOTTOM;
-            if (isRTL) {
-                mDragPositive = !mDragPositive;
+        mNavBarPosition = navBarPosition;
+
+        // Determine the drag directions depending on location of nav bar
+        switch (navBarPosition) {
+            case NAV_BAR_LEFT:
+                mDragHPositive = !isRTL;
+                mDragVPositive = false;
+                break;
+            case NAV_BAR_RIGHT:
+                mDragHPositive = isRTL;
+                mDragVPositive = true;
+                break;
+            case NAV_BAR_BOTTOM:
+                mDragHPositive = !isRTL;
+                mDragVPositive = true;
+                break;
+        }
+
+        for (NavigationGestureAction action: mGestureActions) {
+            if (action != null) {
+                action.setBarState(changed, mNavBarPosition, mDragHPositive, mDragVPositive);
             }
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to get nav bar position.", e);
         }
     }
 
     @Override
     public void onNavigationButtonLongPress(View v) {
         mAllowGestureDetection = false;
-        mHandler.removeCallbacksAndMessages(null);
     }
 
     @Override
     public void dump(PrintWriter pw) {
         pw.println("QuickStepController {");
-        pw.print("    "); pw.println("mQuickScrubActive=" + mQuickScrubActive);
-        pw.print("    "); pw.println("mQuickStepStarted=" + mQuickStepStarted);
         pw.print("    "); pw.println("mAllowGestureDetection=" + mAllowGestureDetection);
-        pw.print("    "); pw.println("mBackGestureActive=" + mBackGestureActive);
-        pw.print("    "); pw.println("mCanPerformBack=" + mCanPerformBack);
         pw.print("    "); pw.println("mNotificationsVisibleOnDown=" + mNotificationsVisibleOnDown);
-        pw.print("    "); pw.println("mIsVertical=" + mIsVertical);
+        pw.print("    "); pw.println("mNavBarPosition=" + mNavBarPosition);
         pw.print("    "); pw.println("mIsRTL=" + mIsRTL);
         pw.print("    "); pw.println("mIsInScreenPinning=" + mIsInScreenPinning);
         pw.println("}");
     }
 
-    private void startQuickStep(MotionEvent event) {
-        if (mIsInScreenPinning) {
-            mNavigationBarView.showPinningEscapeToast();
-            mAllowGestureDetection = false;
-            return;
-        }
-
-        mQuickStepStarted = true;
-        event.transform(mTransformGlobalMatrix);
-        try {
-            mOverviewEventSender.getProxy().onQuickStep(event);
-            if (DEBUG_OVERVIEW_PROXY) {
-                Log.d(TAG_OPS, "Quick Step Start");
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to send quick step started.", e);
-        } finally {
-            event.transform(mTransformLocalMatrix);
-        }
-        mOverviewEventSender.notifyQuickStepStarted();
-        mHandler.removeCallbacksAndMessages(null);
-
-        if (mHitTarget != null) {
-            mHitTarget.abortCurrentGesture();
-        }
-
-        if (mQuickScrubActive) {
-            animateEnd();
-        }
+    public NavigationGestureAction getCurrentAction() {
+        return mCurrentAction;
     }
 
-    private void startQuickScrub() {
+    private void tryToStartGesture(NavigationGestureAction action, boolean alignedWithNavBar,
+            boolean positiveDirection, MotionEvent event) {
+        if (action == null) {
+            return;
+        }
         if (mIsInScreenPinning) {
             mNavigationBarView.showPinningEscapeToast();
             mAllowGestureDetection = false;
             return;
         }
 
-        if (!mQuickScrubActive) {
-            updateHighlight();
-            mQuickScrubActive = true;
-            ObjectAnimator trackAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
-                    PropertyValuesHolder.ofFloat(mTrackAlphaProperty, 1f),
-                    PropertyValuesHolder.ofFloat(mTrackScaleProperty, 1f));
-            trackAnimator.setInterpolator(ALPHA_IN);
-            trackAnimator.setDuration(ANIM_IN_DURATION_MS);
-            ObjectAnimator navBarAnimator = ObjectAnimator.ofFloat(this, mNavBarAlphaProperty, 0f);
-            navBarAnimator.setInterpolator(ALPHA_OUT);
-            navBarAnimator.setDuration(ANIM_OUT_DURATION_MS);
-            mTrackAnimator = new AnimatorSet();
-            mTrackAnimator.playTogether(trackAnimator, navBarAnimator);
-            mTrackAnimator.start();
+        // Start new action from gesture if is able to start and depending on notifications
+        // visibility and starting touch down target. If the action is enabled, then also check if
+        // can perform the action so that if action requires the button to be dragged, then the
+        // gesture will have a large dampening factor and prevent action from running.
+        final boolean validHitTarget = action.requiresTouchDownHitTarget() == HIT_TARGET_NONE
+                || action.requiresTouchDownHitTarget() == mNavigationBarView.getDownHitTarget();
+        if (mCurrentAction == null && validHitTarget && action.isEnabled()
+                && (!mNotificationsVisibleOnDown || action.canRunWhenNotificationsShowing())) {
+            if (action.canPerformAction()) {
+                mCurrentAction = action;
+                event.transform(mTransformGlobalMatrix);
+                action.startGesture(event);
+                event.transform(mTransformLocalMatrix);
 
-            // Disable slippery for quick scrub to not cancel outside the nav bar
-            mNavigationBarView.updateSlippery();
+                // Calculate the bounding limits of drag to avoid dragging off nav bar's window
+                if (action.requiresDragWithHitTarget() && mHitTarget != null) {
+                    final int[] buttonCenter = new int[2];
+                    View button = mHitTarget.getCurrentView();
+                    button.getLocationInWindow(buttonCenter);
+                    buttonCenter[0] += button.getWidth() / 2;
+                    buttonCenter[1] += button.getHeight() / 2;
+                    final int x = isNavBarVertical() ? buttonCenter[1] : buttonCenter[0];
+                    final int y = isNavBarVertical() ? buttonCenter[0] : buttonCenter[1];
+                    final int iconHalfSize = mContext.getResources()
+                            .getDimensionPixelSize(R.dimen.navigation_icon_size) / 2;
 
-            try {
-                mOverviewEventSender.getProxy().onQuickScrubStart();
-                if (DEBUG_OVERVIEW_PROXY) {
-                    Log.d(TAG_OPS, "Quick Scrub Start");
+                    if (alignedWithNavBar) {
+                        mMinDragLimit =  iconHalfSize - x;
+                        mMaxDragLimit = -x - iconHalfSize + (isNavBarVertical()
+                                ? mNavigationBarView.getHeight() : mNavigationBarView.getWidth());
+                    } else {
+                        mMinDragLimit = iconHalfSize - y;
+                        mMaxDragLimit =  -y - iconHalfSize + (isNavBarVertical()
+                                ? mNavigationBarView.getWidth() : mNavigationBarView.getHeight());
+                    }
                 }
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to send start of quick scrub.", e);
             }
-            mOverviewEventSender.notifyQuickScrubStarted();
+
+            // Handle direction of the hit target drag from the axis that started the gesture
+            // Also calculate the dampening factor, weaker dampening if there is an active action
+            if (action.requiresDragWithHitTarget()) {
+                if (alignedWithNavBar) {
+                    mGestureHorizontalDragsButton = true;
+                    mGestureVerticalDragsButton = false;
+                    mDragDampeningFactor = action.isActive()
+                            ? HORIZONTAL_GESTURE_DAMPING : HORIZONTAL_DISABLED_GESTURE_DAMPING;
+                } else {
+                    mGestureVerticalDragsButton = true;
+                    mGestureHorizontalDragsButton = false;
+                    mDragDampeningFactor = action.isActive()
+                            ? VERTICAL_GESTURE_DAMPING : VERTICAL_DISABLED_GESTURE_DAMPING;
+                }
+            }
 
             if (mHitTarget != null) {
                 mHitTarget.abortCurrentGesture();
@@ -576,148 +518,13 @@
         }
     }
 
-    private void endQuickScrub(boolean animate) {
-        if (mQuickScrubActive) {
-            animateEnd();
-            try {
-                mOverviewEventSender.getProxy().onQuickScrubEnd();
-                if (DEBUG_OVERVIEW_PROXY) {
-                    Log.d(TAG_OPS, "Quick Scrub End");
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to send end of quick scrub.", e);
+    private boolean canPerformAnyAction() {
+        for (NavigationGestureAction action: mGestureActions) {
+            if (action != null && action.isEnabled()) {
+                return true;
             }
         }
-        if (!animate) {
-            if (mTrackAnimator != null) {
-                mTrackAnimator.end();
-                mTrackAnimator = null;
-            }
-        }
-    }
-
-    private void startBackGesture() {
-        if (!mBackGestureActive) {
-            mBackGestureActive = true;
-            mNavigationBarView.getHomeButton().abortCurrentGesture();
-            final boolean runBackMidGesture = !shouldExecuteBackOnUp(mContext);
-            if (mCanPerformBack) {
-                if (!shouldhideBackButton(mContext)) {
-                    mNavigationBarView.getBackButton().setAlpha(0 /* alpha */, true /* animate */,
-                            BACK_BUTTON_FADE_OUT_ALPHA);
-                }
-                if (runBackMidGesture) {
-                    performBack();
-                }
-            }
-            mHandler.removeCallbacks(mExecuteBackRunnable);
-            if (runBackMidGesture) {
-                mHandler.postDelayed(mExecuteBackRunnable, BACK_GESTURE_POLL_TIMEOUT);
-            }
-        }
-    }
-
-    private void endBackGesture() {
-        if (mBackGestureActive) {
-            mHandler.removeCallbacks(mExecuteBackRunnable);
-            mHomeAnimator = mNavigationBarView.getHomeButton().getCurrentView()
-                    .animate()
-                    .setDuration(BACK_BUTTON_FADE_IN_ALPHA)
-                    .setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-            if (mIsVertical) {
-                mHomeAnimator.translationY(0);
-            } else {
-                mHomeAnimator.translationX(0);
-            }
-            mHomeAnimator.start();
-            if (!shouldhideBackButton(mContext)) {
-                mNavigationBarView.getBackButton().setAlpha(
-                        mOverviewEventSender.getBackButtonAlpha(), true /* animate */);
-            }
-            if (shouldExecuteBackOnUp(mContext)) {
-                performBack();
-            }
-        }
-    }
-
-    private void animateEnd() {
-        if (mTrackAnimator != null) {
-            mTrackAnimator.cancel();
-        }
-
-        ObjectAnimator trackAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
-                PropertyValuesHolder.ofFloat(mTrackAlphaProperty, 0f),
-                PropertyValuesHolder.ofFloat(mTrackScaleProperty, TRACK_SCALE));
-        trackAnimator.setInterpolator(ALPHA_OUT);
-        trackAnimator.setDuration(ANIM_OUT_DURATION_MS);
-        ObjectAnimator navBarAnimator = ObjectAnimator.ofFloat(this, mNavBarAlphaProperty, 1f);
-        navBarAnimator.setInterpolator(ALPHA_IN);
-        navBarAnimator.setDuration(ANIM_IN_DURATION_MS);
-        mTrackAnimator = new AnimatorSet();
-        mTrackAnimator.playTogether(trackAnimator, navBarAnimator);
-        mTrackAnimator.addListener(mQuickScrubEndListener);
-        mTrackAnimator.start();
-    }
-
-    private void resetQuickScrub() {
-        mQuickScrubActive = false;
-        mAllowGestureDetection = false;
-        if (mCurrentNavigationBarView != null) {
-            mCurrentNavigationBarView.setAlpha(1f);
-        }
-        mCurrentNavigationBarView = null;
-        updateHighlight();
-    }
-
-    private void moveHomeButton(float pos) {
-        if (mHomeAnimator != null) {
-            mHomeAnimator.cancel();
-            mHomeAnimator = null;
-        }
-        final View homeButton = mNavigationBarView.getHomeButton().getCurrentView();
-        if (mIsVertical) {
-            homeButton.setTranslationY(pos);
-        } else {
-            homeButton.setTranslationX(pos);
-        }
-    }
-
-    private void updateHighlight() {
-        if (mTrackRect.isEmpty()) {
-            return;
-        }
-        int colorBase, colorGrad;
-        if (mDarkIntensity > 0.5f) {
-            colorBase = mContext.getColor(R.color.quick_step_track_background_background_dark);
-            colorGrad = mContext.getColor(R.color.quick_step_track_background_foreground_dark);
-        } else {
-            colorBase = mContext.getColor(R.color.quick_step_track_background_background_light);
-            colorGrad = mContext.getColor(R.color.quick_step_track_background_foreground_light);
-        }
-        mHighlight = new RadialGradient(0, mTrackRect.height() / 2,
-                mTrackRect.width() * GRADIENT_WIDTH, colorGrad, colorBase,
-                Shader.TileMode.CLAMP);
-        mTrackPaint.setShader(mHighlight);
-    }
-
-    private boolean canPerformHomeBackGesture() {
-        return swipeHomeGoBackGestureEnabled(mContext)
-                && mOverviewEventSender.getBackButtonAlpha() > 0;
-    }
-
-    private void performBack() {
-        sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
-        sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
-        mNavigationBarView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
-    }
-
-    private void sendEvent(int action, int code) {
-        long when = SystemClock.uptimeMillis();
-        final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,
-                0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
-                KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
-                InputDevice.SOURCE_KEYBOARD);
-        InputManager.getInstance().injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+        return false;
     }
 
     private boolean proxyMotionEvents(MotionEvent event) {
@@ -740,22 +547,15 @@
         return false;
     }
 
-    private static boolean getBoolGlobalSetting(Context context, String key) {
+    protected boolean isNavBarVertical() {
+        return mNavBarPosition == NAV_BAR_LEFT || mNavBarPosition == NAV_BAR_RIGHT;
+    }
+
+    static boolean getBoolGlobalSetting(Context context, String key) {
         return Settings.Global.getInt(context.getContentResolver(), key, 0) != 0;
     }
 
-    public static boolean swipeHomeGoBackGestureEnabled(Context context) {
-        return !getBoolGlobalSetting(context, NAVBAR_EXPERIMENTS_DISABLED)
-            && getBoolGlobalSetting(context, PULL_HOME_GO_BACK_PROP);
-    }
-
     public static boolean shouldhideBackButton(Context context) {
-        return swipeHomeGoBackGestureEnabled(context)
-            && getBoolGlobalSetting(context, HIDE_BACK_BUTTON_PROP);
-    }
-
-    public static boolean shouldExecuteBackOnUp(Context context) {
-        return !getBoolGlobalSetting(context, NAVBAR_EXPERIMENTS_DISABLED)
-            && getBoolGlobalSetting(context, BACK_AFTER_END_PROP);
+        return getBoolGlobalSetting(context, HIDE_BACK_BUTTON_PROP);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
index c6e98e0..a7b8eff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
@@ -39,10 +39,10 @@
 import android.view.View;
 import android.view.WindowManagerGlobal;
 
-import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
index 2a5028b..f8731b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.os.SystemClock;
 import android.util.Slog;
-import android.view.WindowManager;
 import android.widget.Toast;
 
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 1bed26d..9f34cbb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -23,7 +23,6 @@
 import android.app.WallpaperManager;
 import android.content.Context;
 import android.graphics.Color;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Trace;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index ade063d..286eea0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.phone;
 
 import android.graphics.Color;
+import android.os.SystemProperties;
 import android.os.Trace;
 import android.util.MathUtils;
 
@@ -75,7 +76,12 @@
         public void prepare(ScrimState previousState) {
             mBlankScreen = mDisplayRequiresBlanking && previousState != ScrimState.AOD;
             mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
-            mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_DARK_KEYGUARD;
+            String opacity = SystemProperties.get("persist.sysui.aod2_scrim_opacity", "0.8");
+            try {
+                mCurrentBehindAlpha = Float.parseFloat(opacity);
+            } catch (RuntimeException e) {
+                mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_DARK_KEYGUARD;
+            }
             mCurrentInFrontAlpha = 0;
             mCurrentInFrontTint = Color.BLACK;
             mCurrentBehindTint = Color.BLACK;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
index e546119..f926218 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
@@ -15,6 +15,7 @@
 package com.android.systemui.statusbar.phone;
 
 import android.view.View;
+
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 2337857..1c4538e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -70,6 +70,7 @@
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
 import android.media.AudioAttributes;
 import android.metrics.LogMaker;
 import android.net.Uri;
@@ -168,6 +169,7 @@
 import com.android.systemui.statusbar.BackDropView;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.DisplayNavigationBarController;
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.KeyboardShortcuts;
@@ -340,7 +342,8 @@
     private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
     protected StatusBarWindowController mStatusBarWindowController;
     protected UnlockMethodCache mUnlockMethodCache;
-    private DozeServiceHost mDozeServiceHost = new DozeServiceHost();
+    @VisibleForTesting
+    DozeServiceHost mDozeServiceHost = new DozeServiceHost();
     private boolean mWakeUpComingFromTouch;
     private PointF mWakeUpTouchLocation;
 
@@ -477,7 +480,7 @@
     private boolean mLaunchCameraOnScreenTurningOn;
     private boolean mLaunchCameraOnFinishedGoingToSleep;
     private int mLastCameraLaunchSource;
-    private PowerManager.WakeLock mGestureWakeLock;
+    protected PowerManager.WakeLock mGestureWakeLock;
     private Vibrator mVibrator;
     private long[] mCameraLaunchGestureVibePattern;
 
@@ -558,8 +561,11 @@
                 }
             };
 
+    protected DisplayManager mDisplayManager;
+
     private NavigationBarFragment mNavigationBar;
     private View mNavigationBarView;
+
     private HeadsUpAppearanceController mHeadsUpAppearanceController;
     private boolean mVibrateOnOpening;
     private VibratorHelper mVibratorHelper;
@@ -586,7 +592,6 @@
         mNotificationLogger = Dependency.get(NotificationLogger.class);
         mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class);
         mNotificationListener =  Dependency.get(NotificationListener.class);
-        mGroupManager = Dependency.get(NotificationGroupManager.class);
         mNetworkController = Dependency.get(NetworkController.class);
         mUserSwitcherController = Dependency.get(UserSwitcherController.class);
         mScreenLifecycle = Dependency.get(ScreenLifecycle.class);
@@ -607,6 +612,7 @@
         mKeyguardViewMediator = getComponent(KeyguardViewMediator.class);
         mColorExtractor = Dependency.get(SysuiColorExtractor.class);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
+        mNavigationBarController = Dependency.get(DisplayNavigationBarController.class);
 
         mColorExtractor.addOnColorsChangedListener(this);
         mStatusBarStateController.addListener(this, StatusBarStateController.RANK_STATUS_BAR);
@@ -864,6 +870,7 @@
             }
         });
 
+        // TODO(115978725): Support light bar controller on external nav bars.
         mLightBarController = Dependency.get(LightBarController.class);
         if (mNavigationBar != null) {
             mNavigationBar.setLightBarController(mLightBarController);
@@ -1096,6 +1103,9 @@
     @Override
     public void onThemeChanged() {
         // Recreate Indication controller because internal references changed
+        if (mKeyguardIndicationController != null) {
+            mKeyguardIndicationController.destroy();
+        }
         mKeyguardIndicationController =
                 SystemUIFactory.getInstance().createKeyguardIndicationController(mContext,
                         mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
@@ -1104,7 +1114,6 @@
         mKeyguardIndicationController
                 .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
         mKeyguardIndicationController.setVisible(mState == StatusBarState.KEYGUARD);
-        mKeyguardIndicationController.setDozing(mDozing);
         if (mStatusBarKeyguardViewManager != null) {
             mStatusBarKeyguardViewManager.onThemeChanged();
         }
@@ -2065,6 +2074,7 @@
         }
     }
 
+    // TODO(115978725): Support auto hide on external nav bars.
     void touchAutoHide() {
         // update transient bar autohide
         if (mStatusBarMode == MODE_SEMI_TRANSPARENT || (mNavigationBar != null
@@ -2104,6 +2114,7 @@
                 : MODE_OPAQUE;
     }
 
+    // TODO(115978725): Support animations on external nav bars.
     void checkBarModes() {
         if (mDemoMode) return;
         if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState,
@@ -2123,6 +2134,7 @@
         transitions.transitionTo(mode, anim);
     }
 
+    // TODO(115978725): Support animations on external nav bars.
     private void finishBarAnimations() {
         if (mStatusBarView != null) {
             mStatusBarView.getBarTransitions().finishAnimations();
@@ -2856,6 +2868,7 @@
             mWindowManager.removeViewImmediate(mNavigationBarView);
             mNavigationBarView = null;
         }
+        mNavigationBarController.destroy();
         mContext.unregisterReceiver(mBroadcastReceiver);
         mContext.unregisterReceiver(mDemoReceiver);
         mAssistManager.destroy();
@@ -2924,6 +2937,7 @@
                     "transparent".equals(mode) ? MODE_TRANSPARENT :
                     "warning".equals(mode) ? MODE_WARNING :
                     -1;
+            // TODO(115978725): Support external nav bar transitions
             if (barMode != -1) {
                 boolean animate = true;
                 if (mStatusBarView != null) {
@@ -3157,6 +3171,7 @@
                 mDraggedDownRow = null;
             }
 
+            // TODO(115978725): Support animations on external nav bars.
             // Disable layout transitions in navbar for this transition because the load is just
             // too heavy for the CPU and GPU on any device.
             if (mNavigationBar != null) {
@@ -3247,12 +3262,12 @@
         boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup())
                 || (mDozing && mDozeServiceHost.shouldAnimateScreenOff() && sleepingFromKeyguard);
 
-        mDozeScrimController.setDozing(mDozing);
-        mKeyguardIndicationController.setDozing(mDozing);
         mNotificationPanel.setDozing(mDozing, animate, mWakeUpTouchLocation,
                 mDozeServiceHost.wasPassivelyInterrupted());
-        mNotificationLogger.setDozing(mDozing);
-        mGroupManager.setDozing(mDozing);
+        if (mNotificationPanel.isSemiAwake()
+                && SystemProperties.getBoolean("persist.systemui.show_swipe_up", false)) {
+            mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock);
+        }
         updateQsExpansionEnabled();
         Trace.endSection();
     }
@@ -3442,13 +3457,6 @@
         updateQsExpansionEnabled();
         mKeyguardViewMediator.setAodShowing(mDozing);
 
-        //TODO: make these folks listeners of StatusBarStateController.onDozingChanged
-        mStatusBarWindowController.setDozing(mDozing);
-        mStatusBarKeyguardViewManager.setDozing(mDozing);
-        if (mAmbientIndicationContainer instanceof DozeReceiver) {
-            ((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing);
-        }
-
         mEntryManager.updateNotifications();
         updateDozingState();
         updateScrimController();
@@ -3606,6 +3614,7 @@
         }
     }
 
+    @VisibleForTesting
     final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
         @Override
         public void onFinishedGoingToSleep() {
@@ -3647,6 +3656,7 @@
             mNotificationPanel.setTouchAndAnimationDisabled(false);
             updateVisibleToUser();
             updateIsKeyguard();
+            mDozeServiceHost.stopDozing();
         }
     };
 
@@ -3853,7 +3863,8 @@
         return mStatusBarKeyguardViewManager.isShowing();
     }
 
-    private final class DozeServiceHost implements DozeHost {
+    @VisibleForTesting
+    final class DozeServiceHost implements DozeHost {
         private final ArrayList<Callback> mCallbacks = new ArrayList<>();
         private boolean mAnimateWakeup;
         private boolean mAnimateScreenOff;
@@ -3941,7 +3952,6 @@
                 mDozingRequested = false;
                 DozeLog.traceDozing(mContext, mDozing);
                 updateDozing();
-                mWakefulnessLifecycle.dispatchStartedWakingUp();
             }
         }
 
@@ -4109,6 +4119,8 @@
     private DeviceProvisionedController mDeviceProvisionedController
             = Dependency.get(DeviceProvisionedController.class);
 
+    protected DisplayNavigationBarController mNavigationBarController;
+
     // UI-specific methods
 
     protected WindowManager mWindowManager;
@@ -4425,6 +4437,7 @@
     }
     // End Extra BaseStatusBarMethods.
 
+    // TODO(115978725): Handle dimming for external nav bars
     private final Runnable mAutoDim = () -> {
         if (mNavigationBar != null) {
             mNavigationBar.getBarTransitions().setAutoDim(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 0d6cb5c..26c9d28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -16,16 +16,15 @@
 
 import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
 import static android.app.StatusBarManager.DISABLE_NONE;
+
 import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
 import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE;
 import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI;
 
 import android.content.Context;
 import android.os.Bundle;
-import androidx.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.ArraySet;
-import android.util.Log;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
@@ -33,19 +32,22 @@
 import android.widget.LinearLayout;
 import android.widget.LinearLayout.LayoutParams;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.DemoMode;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.StatusBarMobileView;
 import com.android.systemui.statusbar.StatusBarWifiView;
+import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
 import com.android.systemui.util.Utils.DisableStateTracker;
+
 import java.util.List;
 
 public interface StatusBarIconController {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 24a5896..7c17c01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -45,8 +45,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
-
 /**
  * Receives the callbacks from CommandQueue related to icons and tracks the state of
  * all the icons. Dispatches this state to any IconManagers that are currently
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
index c4ff85f..88d0035 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.graphics.drawable.Icon;
 import android.os.UserHandle;
+
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
index b7e1cfb..2e41617 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
@@ -16,16 +16,17 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.statusbar.StatusBarIcon;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
-import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
-
 public class StatusBarIconList {
     private ArrayList<Slot> mSlots = new ArrayList<>();
 
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 df99a9c..484fe11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -59,7 +59,8 @@
  * which is in turn, reported to this class by the current
  * {@link com.android.keyguard.KeyguardViewBase}.
  */
-public class StatusBarKeyguardViewManager implements RemoteInputController.Callback {
+public class StatusBarKeyguardViewManager implements RemoteInputController.Callback,
+        StatusBarStateController.StateListener {
 
     // When hiding the Keyguard with timing supplied from WindowManager, better be early than late.
     private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3;
@@ -150,6 +151,7 @@
         mLockPatternUtils = lockPatternUtils;
         mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
         KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitorCallback);
+        Dependency.get(StatusBarStateController.class).addListener(this);
     }
 
     public void registerStatusBar(StatusBar statusBar,
@@ -334,7 +336,7 @@
         updateStates();
     }
 
-    public void setDozing(boolean dozing) {
+    private void setDozing(boolean dozing) {
         if (mDozing != dozing) {
             mDozing = dozing;
             if (dozing || mBouncer.needsFullscreenBouncer() || mOccluded) {
@@ -781,6 +783,16 @@
         }
     }
 
+    @Override
+    public void onStateChanged(int newState) {
+        // Nothing
+    }
+
+    @Override
+    public void onDozingChanged(boolean isDozing) {
+        setDozing(isDozing);
+    }
+
     private static class DismissWithActionRequest {
         final OnDismissAction dismissAction;
         final Runnable cancelAction;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index f81ffe9..8286d26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -17,29 +17,20 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Rect;
 import android.os.Handler;
-import android.os.Looper;
 import android.telephony.SubscriptionInfo;
 import android.util.ArraySet;
 import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.ImageView;
-import com.android.settingslib.graph.SignalDrawable;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl;
 import com.android.systemui.statusbar.policy.SecurityController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 0d37b55..11de941 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -76,7 +76,6 @@
     private final State mCurrentState = new State();
     private OtherwisedCollapsedListener mListener;
 
-    private final StateListener mStateListener = this::setStatusBarState;
     private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
 
     public StatusBarWindowController(Context context) {
@@ -564,6 +563,18 @@
         }
     }
 
+    private final StateListener mStateListener = new StateListener() {
+        @Override
+        public void onStateChanged(int newState) {
+            setStatusBarState(newState);
+        }
+
+        @Override
+        public void onDozingChanged(boolean isDozing) {
+            setDozing(isDozing);
+        }
+    };
+
     /**
      * Custom listener to pipe data back to plugins about whether or not the status bar would be
      * collapsed if not for the plugin.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index ad9b9b3..978a72d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -33,7 +33,6 @@
 import android.media.session.MediaSessionLegacyHelper;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.view.ActionMode;
@@ -50,8 +49,6 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.Window;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
 import android.widget.FrameLayout;
 
 import com.android.internal.annotations.VisibleForTesting;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index 56a177e..6495910 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -16,9 +16,9 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
 import static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT;
 import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
+import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
 
 import android.annotation.Nullable;
 import android.content.Context;
@@ -28,14 +28,15 @@
 import android.graphics.Paint.Style;
 import android.util.AttributeSet;
 import android.util.Log;
-
 import android.view.View;
+
 import com.android.keyguard.AlphaOptimizedLinearLayout;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.notification.stack.AnimationFilter;
 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
 import com.android.systemui.statusbar.notification.stack.ViewState;
+
 import java.util.ArrayList;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index e5925f0..bdd76c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -16,8 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.hardware.biometrics.BiometricSourceType;
 import android.content.Context;
+import android.hardware.biometrics.BiometricSourceType;
 import android.os.Trace;
 
 import com.android.internal.widget.LockPatternUtils;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
index 2ed2edb..ba55f2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
@@ -20,7 +20,6 @@
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
-import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto b/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
index 50fd52a..cfb633d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/touch_analytics.proto
@@ -134,4 +134,6 @@
     optional int32 touchAreaHeight = 10;
     optional Type type = 11;
     repeated PhoneEvent phoneEvents = 12;
+
+    optional string device_id = 13;
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
index d85e18c..67da8a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
@@ -14,14 +14,11 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.accessibilityservice.AccessibilityServiceInfo;
 import android.content.Context;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
 
-import java.util.List;
-
 /**
  * For mocking because AccessibilityManager is final for some reason...
  */
@@ -62,8 +59,8 @@
         mAccessibilityManager.sendAccessibilityEvent(event);
     }
 
-    public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(
-            int feedbackTypeFlags) {
-        return mAccessibilityManager.getEnabledAccessibilityServiceList(feedbackTypeFlags);
+    /** Returns a recommended ui timeout value in milliseconds. */
+    public int getRecommendedTimeoutMillis(int originalTimeout, int uiContentFlags) {
+        return mAccessibilityManager.getRecommendedTimeoutMillis(originalTimeout, uiContentFlags);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 6f4026d..f65f826 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -55,4 +55,11 @@
         default void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {}
         default void onPowerSaveChanged(boolean isPowerSave) {}
     }
+
+    /**
+     * If available, get the estimated battery time remaining as a string
+     */
+    default String getEstimatedTimeRemainingString() {
+        return null;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 7221efa..ddcfbf6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -29,9 +29,14 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.fuelgauge.BatterySaverUtils;
+import com.android.settingslib.utils.PowerUtil;
+import com.android.systemui.Dependency;
+import com.android.systemui.power.EnhancedEstimates;
+import com.android.systemui.power.Estimate;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.text.NumberFormat;
 import java.util.ArrayList;
 
 /**
@@ -44,7 +49,9 @@
     public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
 
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final int UPDATE_GRANULARITY_MSEC = 1000 * 60;
 
+    private final EnhancedEstimates mEstimates = Dependency.get(EnhancedEstimates.class);
     private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
     private final PowerManager mPowerManager;
     private final Handler mHandler;
@@ -58,6 +65,8 @@
     protected boolean mAodPowerSave;
     private boolean mTestmode = false;
     private boolean mHasReceivedBattery = false;
+    private Estimate mEstimate;
+    private long mLastEstimateTimestamp = -1;
 
     public BatteryControllerImpl(Context context) {
         this(context, context.getSystemService(PowerManager.class));
@@ -71,6 +80,7 @@
 
         registerReceiver();
         updatePowerSave();
+        updateEstimate();
     }
 
     private void registerReceiver() {
@@ -180,6 +190,26 @@
         return mAodPowerSave;
     }
 
+    @Override
+    public String getEstimatedTimeRemainingString() {
+        if (mEstimate == null
+                || System.currentTimeMillis() > mLastEstimateTimestamp + UPDATE_GRANULARITY_MSEC) {
+            updateEstimate();
+        }
+        // Estimates may not exist yet even if we've checked
+        if (mEstimate == null) {
+            return null;
+        }
+        final String percentage = NumberFormat.getPercentInstance().format((double) mLevel / 100.0);
+        return PowerUtil.getBatteryRemainingShortStringFormatted(
+                mContext, mEstimate.estimateMillis);
+    }
+
+    private void updateEstimate() {
+        mEstimate = mEstimates.getEstimate();
+        mLastEstimateTimestamp = System.currentTimeMillis();
+    }
+
     private void updatePowerSave() {
         setPowerSave(mPowerManager.isPowerSaveMode());
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index b76d536..e1bb19a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -19,6 +19,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.telephony.SubscriptionInfo;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index 533bd86..ccfe073 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.policy;
 
+import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
+
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -30,6 +32,8 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.annotations.GuardedBy;
 import com.android.systemui.R;
 
@@ -40,10 +44,6 @@
 import java.util.Set;
 import java.util.UUID;
 
-import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
-
-import androidx.annotation.VisibleForTesting;
-
 
 /** Platform implementation of the cast controller. **/
 public class CastControllerImpl implements CastController {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
index 2ede327..911715f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
@@ -21,8 +21,6 @@
 import android.os.Looper;
 import android.os.RemoteException;
 
-import com.android.systemui.statusbar.policy.DataSaverController.Listener;
-
 import java.util.ArrayList;
 
 public class DataSaverControllerImpl implements DataSaverController {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index dcce77c..74a30fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -27,7 +27,6 @@
 import android.util.AttributeSet;
 import android.widget.TextView;
 
-import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
index cae76b4..7b4c35a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
@@ -14,8 +14,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.content.Context;
-
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 
 public interface DeviceProvisionedController extends CallbackController<DeviceProvisionedListener> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
index c726189..0d6178b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
@@ -23,13 +23,9 @@
 import android.content.IntentFilter;
 import android.net.ConnectivityManager;
 import android.provider.Settings;
-import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.text.TextUtils;
 import android.util.AttributeSet;
-import android.util.Log;
-import android.view.ViewGroup;
-import android.view.ViewParent;
 import android.widget.TextView;
 
 import com.android.internal.telephony.IccCardConstants;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
index 11fc408..e23ce2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
@@ -30,8 +30,6 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.systemui.statusbar.policy.FlashlightController.FlashlightListener;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index b4d24d16..6b83b70b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -16,22 +16,23 @@
 
 package com.android.systemui.statusbar.policy;
 
-import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
+import static com.android.systemui.statusbar.notification.row.NotificationInflater
+        .FLAG_CONTENT_VIEW_HEADS_UP;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.ContentObserver;
-import android.util.ArrayMap;
 import android.provider.Settings;
+import android.util.ArrayMap;
 import android.util.Log;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.AlertingNotificationManager;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
index 5fd79a4..aee021c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
@@ -23,9 +23,10 @@
 import android.metrics.LogMaker;
 import android.os.Handler;
 import android.os.Looper;
-import androidx.annotation.VisibleForTesting;
 import android.util.ArraySet;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.logging.MetricsLogger;
 
 import java.util.Arrays;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
index 2340786..03c89c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
@@ -37,6 +37,7 @@
 import android.graphics.drawable.Drawable;
 import android.util.FloatProperty;
 import android.view.ContextThemeWrapper;
+
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index 59bd85e..8b86996 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -25,9 +25,9 @@
 import android.graphics.ColorFilter;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.RecordingCanvas;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
-import android.graphics.RecordingCanvas;
 import android.view.RenderNodeAnimator;
 import android.view.View;
 import android.view.ViewConfiguration;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 6fa73ef..2c756ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -45,12 +45,13 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ImageView;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
-import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.system.NavigationBarCompat;
 
 public class KeyButtonView extends ImageView implements ButtonInterface {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index fcd7e09..840e77e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -29,12 +29,14 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+
 import androidx.annotation.VisibleForTesting;
+
 import com.android.systemui.util.Utils;
+
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 8ca1415..e943261 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -35,8 +35,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.EriInfo;
-import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.Utils;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
index dfdeae1..dac878c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
@@ -23,8 +23,6 @@
 import android.content.IntentFilter;
 import android.os.UserHandle;
 
-import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
index 5028fd1..d434768 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
@@ -16,8 +16,8 @@
 
 package com.android.systemui.statusbar.policy;
 
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
  * A listener to heads up changes
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 7dd0d0f..a485fa8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -55,8 +55,8 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index 91c208d..9ec30d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -15,16 +15,17 @@
  */
 package com.android.systemui.statusbar.policy;
 
+import static com.android.systemui.statusbar.policy.NetworkControllerImpl.TAG;
+
 import android.content.Context;
 import android.text.format.DateFormat;
 import android.util.Log;
+
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import java.io.PrintWriter;
 import java.util.BitSet;
 
-import static com.android.systemui.statusbar.policy.NetworkControllerImpl.TAG;
-
 
 /**
  * Common base class for handling signal for both wifi and mobile data.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
index 7b0b8004..71d6e54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.policy;
 
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.ContentObserver;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index aa4782f..42f1378 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -28,11 +28,11 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ContrastColorUtil;
-import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
index f5ae88b..fed8032 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
@@ -37,7 +37,6 @@
 import com.android.internal.util.UserIcons;
 import com.android.settingslib.drawable.UserIconDrawable;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
 
 import java.util.ArrayList;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index b5d92a5..cd379c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -25,7 +25,6 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.SystemUI;
-import com.android.systemui.pip.tv.PipManager;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
index 499be42..905b9a3 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
@@ -14,19 +14,21 @@
 
 package com.android.systemui.tuner;
 
+import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
+
 import android.content.Context;
 import android.provider.Settings;
-import androidx.preference.DropDownPreference;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.AttributeSet;
+
+import androidx.preference.DropDownPreference;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 
-import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
-
 public class BatteryPreference extends DropDownPreference implements TunerService.Tunable {
 
     private static final String PERCENT = "percent";
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java
index 702abea..265823a 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java
@@ -15,9 +15,10 @@
 package com.android.systemui.tuner;
 
 import android.content.Context;
-import androidx.preference.ListPreference;
 import android.util.AttributeSet;
 
+import androidx.preference.ListPreference;
+
 public class BetterListPreference extends ListPreference {
 
     private CharSequence mSummary;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
index 16ab65c..a526603 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
@@ -14,11 +14,12 @@
 package com.android.systemui.tuner;
 
 import android.content.Context;
-import androidx.preference.DropDownPreference;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.AttributeSet;
 
+import androidx.preference.DropDownPreference;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.Clock;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
index 8da0043..ade1f82 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
@@ -14,7 +14,6 @@
 
 package com.android.systemui.tuner;
 
-import android.annotation.Nullable;
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
@@ -22,12 +21,10 @@
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnClickListener;
 import android.os.Bundle;
-import androidx.preference.ListPreferenceDialogFragment;
-import androidx.preference.ListPreference;
 import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
+
+import androidx.preference.ListPreference;
+import androidx.preference.ListPreferenceDialogFragment;
 
 public class CustomListPreference extends ListPreference {
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
index a0f278b..a60ca62 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -23,12 +23,13 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.Settings;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.SwitchPreference;
+import android.view.MenuItem;
+
 import androidx.preference.Preference;
 import androidx.preference.Preference.OnPreferenceChangeListener;
+import androidx.preference.PreferenceFragment;
 import androidx.preference.PreferenceScreen;
-import android.view.MenuItem;
+import androidx.preference.SwitchPreference;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
index d63235c..4dbceac 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
@@ -21,32 +21,25 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.LauncherActivityInfo;
-import android.content.pm.LauncherApps;
-import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ShortcutInfo;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.ScaleDrawable;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.Process;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.SwitchPreference;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.ViewHolder;
 import android.text.TextUtils;
-import android.util.Log;
 import android.util.TypedValue;
-import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.SwitchPreference;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
@@ -57,7 +50,6 @@
 import com.android.systemui.tuner.TunerService.Tunable;
 
 import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 import java.util.function.Consumer;
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
index e3a452a..fa531b5 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
@@ -34,9 +34,6 @@
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.Handler;
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceChangeListener;
 import android.text.SpannableStringBuilder;
 import android.text.style.ImageSpan;
 import android.util.Log;
@@ -44,6 +41,10 @@
 import android.view.KeyEvent;
 import android.widget.EditText;
 
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.Preference.OnPreferenceChangeListener;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.tuner.TunerService.Tunable;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java b/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java
index d766145..7239c8a 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java
@@ -15,7 +15,9 @@
 package com.android.systemui.tuner;
 
 import android.os.Bundle;
+
 import androidx.preference.PreferenceFragment;
+
 import com.android.systemui.R;
 
 public class OtherPrefs extends PreferenceFragment {
@@ -23,4 +25,4 @@
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         addPreferencesFromResource(R.xml.other_settings);
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
index ecb830c..dae1472 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
@@ -29,6 +29,11 @@
 import android.util.ArraySet;
 import android.view.View;
 
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SwitchPreference;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
@@ -41,11 +46,6 @@
 import java.util.List;
 import java.util.Set;
 
-import androidx.preference.PreferenceFragment;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.PreferenceViewHolder;
-import androidx.preference.SwitchPreference;
-
 public class PluginFragment extends PreferenceFragment {
 
     public static final String ACTION_PLUGIN_SETTINGS
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
index 8740a3c..80f9de6 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
@@ -15,10 +15,6 @@
  */
 package com.android.systemui.tuner;
 
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-
 import android.annotation.Nullable;
 import android.app.Fragment;
 import android.os.Bundle;
@@ -29,6 +25,10 @@
 import android.widget.Switch;
 import android.widget.TextView;
 
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+
 public class PowerNotificationControlsFragment extends Fragment {
 
     private static final String KEY_SHOW_PNC = "show_importance_slider";
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
index d80c649..79811c5 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
@@ -17,21 +17,19 @@
 import android.app.AlertDialog.Builder;
 import android.app.Dialog;
 import android.app.DialogFragment;
-import android.app.Fragment;
 import android.content.Context;
 import android.content.DialogInterface.OnClickListener;
 import android.os.Bundle;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
 import android.widget.Toolbar;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
 import com.android.settingslib.Utils;
-import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.R;
+import com.android.systemui.fragments.FragmentHostManager;
 
 import java.util.Objects;
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java b/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
index dded464..0be793e 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
@@ -16,9 +16,10 @@
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
-import androidx.preference.CheckBoxPreference;
 import android.util.TypedValue;
 
+import androidx.preference.CheckBoxPreference;
+
 import com.android.systemui.statusbar.ScalingDrawableWrapper;
 
 public class SelectablePreference extends CheckBoxPreference {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java b/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
index 3c9d25d..11e1f27 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
@@ -20,12 +20,12 @@
 import android.content.pm.LauncherActivityInfo;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.drawable.ColorDrawable;
 import android.os.Bundle;
 import android.os.Process;
-import androidx.preference.PreferenceFragment;
+
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragment;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.PreferenceViewHolder;
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
index 670fcc2..6f23e20 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -19,10 +19,11 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.provider.Settings;
-import androidx.preference.SwitchPreference;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 
+import androidx.preference.SwitchPreference;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 5aa3035..ecf1784 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -22,12 +22,13 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.provider.Settings;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.Preference;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragment;
+
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
index a22277e..9cc8943 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
@@ -15,9 +15,9 @@
 package com.android.systemui.tuner;
 
 import android.app.DialogFragment;
-import android.os.Bundle;
-import androidx.preference.PreferenceFragment;
+
 import androidx.preference.Preference;
+import androidx.preference.PreferenceFragment;
 
 public abstract class TunerPreferenceFragment extends PreferenceFragment {
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 3a9d1c7..3bccdab 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -26,8 +26,6 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 
-import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
-import com.android.systemui.DemoMode;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
index f53d516..2df9000 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
@@ -3,9 +3,10 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.provider.Settings;
-import androidx.preference.SwitchPreference;
 import android.util.AttributeSet;
 
+import androidx.preference.SwitchPreference;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 2f8dfdc..329d029 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.app.Notification;
 import android.app.Notification.Action;
-import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
index ec5030b..fa3ff64 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.usb;
 
+import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
+
 import android.content.ActivityNotFoundException;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
@@ -38,8 +40,6 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 
-import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
-
 /* Activity for choosing an application for a USB device or accessory */
 public class UsbResolverActivity extends ResolverActivity {
     public static final String TAG = "UsbResolverActivity";
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index c468fef..f35af90 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -16,7 +16,6 @@
 
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
-
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.media.AudioAttributes;
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
index 9b15b00..efd6e03 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
@@ -20,9 +20,10 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Build;
-import androidx.core.content.FileProvider;
 import android.util.Log;
 
+import androidx.core.content.FileProvider;
+
 import com.android.systemui.Dependency;
 
 import java.io.BufferedInputStream;
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index 3c88d29..b2cc269 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -37,7 +37,6 @@
 import android.os.Process;
 import android.os.SystemProperties;
 import android.provider.Settings;
-import androidx.annotation.VisibleForTesting;
 import android.service.quicksettings.Tile;
 import android.text.format.DateUtils;
 import android.util.Log;
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java
index 574fdb98..c50e8f8 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java
@@ -24,7 +24,6 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.io.Writer;
 import java.util.Collection;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
index 8ea5fd4..a47e99d 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
@@ -27,9 +27,10 @@
 import android.os.Debug;
 import android.os.SystemProperties;
 import android.os.UserHandle;
-import androidx.core.content.FileProvider;
 import android.util.Log;
 
+import androidx.core.content.FileProvider;
+
 import com.google.android.collect.Lists;
 
 import java.io.File;
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
index f2ed55f3..13729df 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
@@ -16,9 +16,6 @@
 
 package com.android.systemui.util.wakelock;
 
-import android.os.Handler;
-import android.os.PowerManager;
-
 import com.android.internal.util.Preconditions;
 
 public class SettableWakeLock {
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
index 16ce35c..b0f1b54 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.os.PowerManager;
+
 import androidx.annotation.VisibleForTesting;
 
 /** WakeLock wrapper for testability */
@@ -71,4 +72,4 @@
             }
         };
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 3744105..9b616e0 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -34,8 +34,8 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.PixelFormat;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
@@ -65,17 +65,17 @@
 import androidx.car.widget.PagedListView;
 import androidx.car.widget.SeekbarListItem;
 
-import java.util.Iterator;
+import com.android.systemui.R;
+import com.android.systemui.plugins.VolumeDialog;
+
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
-import com.android.systemui.R;
-import com.android.systemui.plugins.VolumeDialog;
-
 /**
  * Car version of the volume dialog.
  *
@@ -539,9 +539,9 @@
       if (value != volumeItem.progress) {
         volumeItem.listItem.setProgress(value);
         volumeItem.progress = value;
-        if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
-          show(Events.SHOW_REASON_VOLUME_CHANGED);
-        }
+      }
+      if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
+        show(Events.SHOW_REASON_VOLUME_CHANGED);
       }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
index c97095e..361604c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
@@ -27,7 +27,6 @@
 import android.view.KeyEvent;
 import android.view.WindowManager;
 
-
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 
 abstract public class SafetyWarningDialog extends SystemUIDialog
@@ -116,4 +115,4 @@
             }
         }
     };
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
index 36c673c..4239337 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
@@ -19,7 +19,6 @@
 import android.content.res.Configuration;
 
 import com.android.systemui.DemoMode;
-import com.android.systemui.statusbar.policy.ZenModeController;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 798f8bc..b588305 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.volume;
 
-import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
-import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_GENERIC;
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
 import static android.media.AudioManager.RINGER_MODE_NORMAL;
 import static android.media.AudioManager.RINGER_MODE_SILENT;
@@ -32,7 +30,6 @@
 
 import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED;
 
-import android.accessibilityservice.AccessibilityServiceInfo;
 import android.animation.ObjectAnimator;
 import android.annotation.SuppressLint;
 import android.app.ActivityManager;
@@ -68,13 +65,12 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.AccessibilityDelegate;
-import android.view.View.OnAttachStateChangeListener;
 import android.view.ViewGroup;
 import android.view.ViewPropertyAnimator;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
+import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.FrameLayout;
@@ -113,6 +109,10 @@
     private static final long USER_ATTEMPT_GRACE_PERIOD = 1000;
     private static final int UPDATE_ANIMATION_DURATION = 80;
 
+    static final int DIALOG_TIMEOUT_MILLIS = 3000;
+    static final int DIALOG_SAFETYWARNING_TIMEOUT_MILLIS = 5000;
+    static final int DIALOG_HOVERING_TIMEOUT_MILLIS = 16000;
+
     private final Context mContext;
     private final H mHandler = new H();
     private final VolumeDialogController mController;
@@ -170,7 +170,6 @@
 
     @Override
     public void destroy() {
-        mAccessibility.destroy();
         mController.removeCallback(mControllerCallbackH);
         mHandler.removeCallbacksAndMessages(null);
     }
@@ -356,8 +355,6 @@
         writer.print("  mDynamic: "); writer.println(mDynamic);
         writer.print("  mAutomute: "); writer.println(mAutomute);
         writer.print("  mSilentMode: "); writer.println(mSilentMode);
-        writer.print("  mAccessibility.mFeedbackEnabled: ");
-        writer.println(mAccessibility.mFeedbackEnabled);
     }
 
     private static int getImpliedLevel(SeekBar seekBar, int progress) {
@@ -571,10 +568,18 @@
     }
 
     private int computeTimeoutH() {
-        if (mAccessibility.mFeedbackEnabled) return 20000;
-        if (mHovering) return 16000;
-        if (mSafetyWarning != null) return 5000;
-        return 3000;
+        if (mHovering) {
+            return mAccessibilityMgr.getRecommendedTimeoutMillis(DIALOG_HOVERING_TIMEOUT_MILLIS,
+                    AccessibilityManager.FLAG_CONTENT_CONTROLS);
+        }
+        if (mSafetyWarning != null) {
+            return mAccessibilityMgr.getRecommendedTimeoutMillis(
+                    DIALOG_SAFETYWARNING_TIMEOUT_MILLIS,
+                    AccessibilityManager.FLAG_CONTENT_TEXT
+                            | AccessibilityManager.FLAG_CONTENT_CONTROLS);
+        }
+        return mAccessibilityMgr.getRecommendedTimeoutMillis(DIALOG_TIMEOUT_MILLIS,
+                AccessibilityManager.FLAG_CONTENT_CONTROLS);
     }
 
     protected void dismissH(int reason) {
@@ -1261,28 +1266,8 @@
     }
 
     private final class Accessibility extends AccessibilityDelegate {
-        private boolean mFeedbackEnabled;
-
         public void init() {
-            mDialogView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
-                @Override
-                public void onViewDetachedFromWindow(View v) {
-                    if (D.BUG) Log.d(TAG, "onViewDetachedFromWindow");
-                }
-
-                @Override
-                public void onViewAttachedToWindow(View v) {
-                    if (D.BUG) Log.d(TAG, "onViewAttachedToWindow");
-                    updateFeedbackEnabled();
-                }
-            });
             mDialogView.setAccessibilityDelegate(this);
-            mAccessibilityMgr.addCallback(mListener);
-            updateFeedbackEnabled();
-        }
-
-        public void destroy() {
-            mAccessibilityMgr.removeCallback(mListener);
         }
 
         @Override
@@ -1298,25 +1283,6 @@
             rescheduleTimeoutH();
             return super.onRequestSendAccessibilityEvent(host, child, event);
         }
-
-        private void updateFeedbackEnabled() {
-            mFeedbackEnabled = computeFeedbackEnabled();
-        }
-
-        private boolean computeFeedbackEnabled() {
-            // are there any enabled non-generic a11y services?
-            final List<AccessibilityServiceInfo> services =
-                    mAccessibilityMgr.getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK);
-            for (AccessibilityServiceInfo asi : services) {
-                if (asi.feedbackType != 0 && asi.feedbackType != FEEDBACK_GENERIC) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private final AccessibilityServicesStateChangeListener mListener =
-                enabled -> updateFeedbackEnabled();
     }
 
     private static class VolumeRow {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 6f65b08..e4f37de 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -23,8 +23,6 @@
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.qs.tiles.DndTile;
-import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index aac37a2..b32bf99 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -39,7 +39,7 @@
     telephony-common \
     android.test.base \
     android.car \
-    android.car.user
+    android.car.userlib
 
 LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui:com.android.keyguard
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/chooser/ChooserHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/chooser/ChooserHelperTest.java
new file mode 100644
index 0000000..19ad7ca
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/chooser/ChooserHelperTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.chooser;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.app.ActivityTaskManager;
+import android.content.Intent;
+import android.os.Binder;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ChooserHelperTest extends SysuiTestCase {
+
+    @Test
+    public void testOnChoose_CallsStartActivityAsCallerWithToken() {
+        final Intent intent = new Intent();
+        final Binder token = new Binder();
+        intent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, token);
+
+        final Activity mockActivity = mock(Activity.class);
+        when(mockActivity.getIntent()).thenReturn(intent);
+
+        ChooserHelper.onChoose(mockActivity);
+        verify(mockActivity, times(1)).startActivityAsCaller(
+                any(), any(), eq(token), anyBoolean(), anyInt());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
index 7204d31..b23f667 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
@@ -27,55 +27,28 @@
 @SmallTest
 class PrivacyDialogBuilderTest : SysuiTestCase() {
 
-    companion object {
-        val MILLIS_IN_MINUTE: Long = 1000 * 60
-        val NOW = 4 * MILLIS_IN_MINUTE
-    }
-
     @Test
-    fun testGenerateText_multipleApps() {
+    fun testGenerateAppsList() {
         val bar2 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
-                "Bar", context), 2 * MILLIS_IN_MINUTE)
+                "Bar", context))
         val bar3 = PrivacyItem(Privacy.TYPE_LOCATION, PrivacyApplication(
-                "Bar", context), 3 * MILLIS_IN_MINUTE)
+                "Bar", context))
         val foo0 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
-                "Foo", context), 0)
+                "Foo", context))
         val baz1 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
-                "Baz", context), 1 * MILLIS_IN_MINUTE)
+                "Baz", context))
 
         val items = listOf(bar2, foo0, baz1, bar3)
 
         val textBuilder = PrivacyDialogBuilder(context, items)
 
-        val textList = textBuilder.generateText(NOW)
-        assertEquals(2, textList.size)
-        assertEquals("Bar, Foo, Baz are using your camera", textList[0])
-        assertEquals("Bar is using your location for the last 1 min", textList[1])
-    }
-
-    @Test
-    fun testGenerateText_singleApp() {
-        val bar2 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
-                "Bar", context), 0)
-        val bar1 = PrivacyItem(Privacy.TYPE_LOCATION, PrivacyApplication(
-                "Bar", context), 0)
-
-        val items = listOf(bar2, bar1)
-
-        val textBuilder = PrivacyDialogBuilder(context, items)
-        val textList = textBuilder.generateText(NOW)
-        assertEquals(1, textList.size)
-        assertEquals("Bar is using your camera, location", textList[0])
-    }
-
-    @Test
-    fun testGenerateText_singleApp_singleType() {
-        val bar2 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
-                "Bar", context), 2 * MILLIS_IN_MINUTE)
-        val items = listOf(bar2)
-        val textBuilder = PrivacyDialogBuilder(context, items)
-        val textList = textBuilder.generateText(NOW)
-        assertEquals(1, textList.size)
-        assertEquals("Bar is using your camera for the last 2 min", textList[0])
+        val list = textBuilder.appsAndTypes
+        assertEquals(3, list.size)
+        val appsList = list.map { it.first }
+        val typesList = list.map { it.second }
+        assertEquals(listOf("Bar", "Baz", "Foo"), appsList.map { it.packageName })
+        assertEquals(listOf(Privacy.TYPE_CAMERA, Privacy.TYPE_LOCATION), typesList[0])
+        assertEquals(listOf(Privacy.TYPE_CAMERA), typesList[1])
+        assertEquals(listOf(Privacy.TYPE_CAMERA), typesList[2])
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
new file mode 100644
index 0000000..48491d7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 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.privacy
+
+import android.app.AppOpsManager
+import android.os.Handler
+import android.support.test.filters.SmallTest
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.testing.TestableLooper.RunWithLooper
+import com.android.systemui.Dependency
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.appops.AppOpItem
+import com.android.systemui.appops.AppOpsController
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyList
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.verify
+
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+@RunWithLooper
+class PrivacyItemControllerTest : SysuiTestCase() {
+
+    @Mock
+    private lateinit var appOpsController: AppOpsController
+    @Mock
+    private lateinit var callback: PrivacyItemController.Callback
+
+    private lateinit var testableLooper: TestableLooper
+    private lateinit var privacyItemController: PrivacyItemController
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        testableLooper = TestableLooper.get(this)
+
+        appOpsController = mDependency.injectMockDependency(AppOpsController:: class.java)
+        mDependency.injectTestDependency(Dependency.BG_LOOPER, testableLooper.looper)
+        mDependency.injectTestDependency(Dependency.MAIN_HANDLER, Handler(testableLooper.looper))
+
+        doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, 0, "", 0)))
+                .`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+
+        privacyItemController = PrivacyItemController(mContext, callback)
+    }
+    @Test
+    fun testSetListeningTrue() {
+        privacyItemController.setListening(true)
+        verify(appOpsController).addCallback(eq(PrivacyItemController.OPS),
+                any(AppOpsController.Callback::class.java))
+        testableLooper.processAllMessages()
+        verify(callback).privacyChanged(anyList())
+    }
+
+    @Test
+    fun testSetListeningFalse() {
+        privacyItemController.setListening(true)
+        privacyItemController.setListening(false)
+        verify(appOpsController).removeCallback(eq(PrivacyItemController.OPS),
+                any(AppOpsController.Callback:: class.java))
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
index 459dc5d..f59bfae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
@@ -72,6 +72,8 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -390,10 +392,16 @@
     @Test
     public void testCreateNotificationDataEntry_RankingUpdate() {
         Ranking ranking = mock(Ranking.class);
+        initStatusBarNotification(false);
 
-        ArrayList<Notification.Action> smartActions = new ArrayList<>();
-        smartActions.add(createAction());
-        when(ranking.getSmartActions()).thenReturn(smartActions);
+        List<Notification.Action> appGeneratedSmartActions =
+                Collections.singletonList(createContextualAction("appGeneratedAction"));
+        mMockStatusBarNotification.getNotification().actions =
+                appGeneratedSmartActions.toArray(new Notification.Action[0]);
+
+        List<Notification.Action> systemGeneratedSmartActions =
+                Collections.singletonList(createAction("systemGeneratedAction"));
+        when(ranking.getSmartActions()).thenReturn(systemGeneratedSmartActions);
 
         when(ranking.getChannel()).thenReturn(NOTIFICATION_CHANNEL);
 
@@ -407,7 +415,7 @@
         NotificationData.Entry entry =
                 new NotificationData.Entry(mMockStatusBarNotification, ranking);
 
-        assertEquals(smartActions, entry.smartActions);
+        assertEquals(systemGeneratedSmartActions, entry.systemGeneratedSmartActions);
         assertEquals(NOTIFICATION_CHANNEL, entry.channel);
         assertEquals(Ranking.USER_SENTIMENT_NEGATIVE, entry.userSentiment);
         assertEquals(snoozeCriterions, entry.snoozeCriteria);
@@ -437,31 +445,42 @@
                         outRanking.getImportance(), outRanking.getImportanceExplanation(),
                         outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
                         outRanking.canShowBadge(), outRanking.getUserSentiment(), true,
-                        null, null);
+                        false, false, null, null);
             } else if (key.equals(TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY)) {
                 outRanking.populate(key, outRanking.getRank(),
                         outRanking.matchesInterruptionFilter(),
                         outRanking.getVisibilityOverride(), 255,
                         outRanking.getImportance(), outRanking.getImportanceExplanation(),
                         outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
-                        outRanking.canShowBadge(), outRanking.getUserSentiment(), true, null, null);
+                        outRanking.canShowBadge(), outRanking.getUserSentiment(), true, false,
+                        false, null, null);
             } else {
                 outRanking.populate(key, outRanking.getRank(),
                         outRanking.matchesInterruptionFilter(),
                         outRanking.getVisibilityOverride(), outRanking.getSuppressedVisualEffects(),
                         outRanking.getImportance(), outRanking.getImportanceExplanation(),
                         outRanking.getOverrideGroupKey(), NOTIFICATION_CHANNEL, null, null,
-                        outRanking.canShowBadge(), outRanking.getUserSentiment(), false, null,
-                        null);
+                        outRanking.canShowBadge(), outRanking.getUserSentiment(), false, false,
+                        false, null, null);
             }
             return true;
         }
     }
 
-    private Notification.Action createAction() {
+    private Notification.Action createContextualAction(String title) {
         return new Notification.Action.Builder(
                 Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
-                "action",
+                title,
+                PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0))
+                        .setSemanticAction(
+                                Notification.Action.SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION)
+                        .build();
+    }
+
+    private Notification.Action createAction(String title) {
+        return new Notification.Action.Builder(
+                Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
+                title,
                 PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build();
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index fb4ecd1..d1fe5af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -19,7 +19,6 @@
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.assertFalse;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
@@ -168,7 +167,7 @@
                     0,
                     NotificationManager.IMPORTANCE_DEFAULT,
                     null, null,
-                    null, null, null, true, sentiment, false, null, null);
+                    null, null, null, true, sentiment, false, false, false, null, null);
             return true;
         }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
     }
@@ -186,8 +185,8 @@
                     NotificationManager.IMPORTANCE_DEFAULT,
                     null, null,
                     null, null, null, true,
-                    NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL, false,
-                    smartActions, null);
+                    NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL, false, false,
+                    false, smartActions, null);
             return true;
         }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
     }
@@ -439,8 +438,8 @@
 
         mEntryManager.updateNotificationRanking(mRankingMap);
         verify(mRow).setEntry(eq(mEntry));
-        assertEquals(1, mEntry.smartActions.size());
-        assertEquals("action", mEntry.smartActions.get(0).title);
+        assertEquals(1, mEntry.systemGeneratedSmartActions.size());
+        assertEquals("action", mEntry.systemGeneratedSmartActions.get(0).title);
     }
 
     @Test
@@ -454,7 +453,7 @@
 
         mEntryManager.updateNotificationRanking(mRankingMap);
         verify(mRow, never()).setEntry(eq(mEntry));
-        assertEquals(0, mEntry.smartActions.size());
+        assertEquals(0, mEntry.systemGeneratedSmartActions.size());
     }
 
     @Test
@@ -468,8 +467,8 @@
 
         mEntryManager.updateNotificationRanking(mRankingMap);
         verify(mRow, never()).setEntry(eq(mEntry));
-        assertEquals(1, mEntry.smartActions.size());
-        assertEquals("action", mEntry.smartActions.get(0).title);
+        assertEquals(1, mEntry.systemGeneratedSmartActions.size());
+        assertEquals("action", mEntry.systemGeneratedSmartActions.get(0).title);
     }
 
     @Test
@@ -483,8 +482,8 @@
 
         mEntryManager.updateNotificationRanking(mRankingMap);
         verify(mRow, never()).setEntry(eq(mEntry));
-        assertEquals(1, mEntry.smartActions.size());
-        assertEquals("action", mEntry.smartActions.get(0).title);
+        assertEquals(1, mEntry.systemGeneratedSmartActions.size());
+        assertEquals("action", mEntry.systemGeneratedSmartActions.get(0).title);
     }
 
     private Notification.Action createAction() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index ee35449..3d2ea70 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -19,8 +19,10 @@
 import static android.app.AppOpsManager.OP_CAMERA;
 import static android.app.AppOpsManager.OP_RECORD_AUDIO;
 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.service.notification.NotificationListenerService.Ranking
+        .USER_SENTIMENT_NEGATIVE;
 
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
@@ -34,15 +36,14 @@
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.app.INotificationManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
-import android.app.NotificationManager;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.Binder;
@@ -57,11 +58,12 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager
+        .OnSettingsClickListener;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 
@@ -71,8 +73,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
-import org.mockito.junit.MockitoRule;
 import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 /**
  * Tests for {@link NotificationGutsManager}.
@@ -84,7 +86,7 @@
     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
 
     private NotificationChannel mTestNotificationChannel = new NotificationChannel(
-            TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
+            TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
     private TestableLooper mTestableLooper;
     private Handler mHandler;
     private NotificationTestHelper mHelper;
@@ -282,7 +284,8 @@
         when(row.getIsNonblockable()).thenReturn(false);
         StatusBarNotification statusBarNotification = row.getStatusBarNotification();
 
-        mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+        mGutsManager.initializeNotificationInfo(row, notificationInfoView,
+                NotificationInfo.ACTION_NONE);
 
         verify(notificationInfoView).bindNotification(
                 any(PackageManager.class),
@@ -297,7 +300,10 @@
                 eq(false),
                 eq(false),
                 eq(true) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */);
+                eq(true) /* isUserSentimentNegative */,
+                eq(false) /*isNoisy */,
+                eq(0),
+                eq(NotificationInfo.ACTION_NONE));
     }
 
     @Test
@@ -309,7 +315,8 @@
         when(row.getIsNonblockable()).thenReturn(false);
         StatusBarNotification statusBarNotification = row.getStatusBarNotification();
 
-        mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+        mGutsManager.initializeNotificationInfo(row, notificationInfoView,
+                NotificationInfo.ACTION_NONE);
 
         verify(notificationInfoView).bindNotification(
                 any(PackageManager.class),
@@ -324,7 +331,74 @@
                 eq(false),
                 eq(false),
                 eq(false) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */);
+                eq(true) /* isUserSentimentNegative */,
+                eq(false) /*isNoisy */,
+                eq(0),
+                eq(NotificationInfo.ACTION_NONE));
+    }
+
+    @Test
+    public void testInitializeNotificationInfoView_noisy() throws Exception {
+        NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+        ExpandableNotificationRow row = spy(mHelper.createRow());
+        row.setBlockingHelperShowing(true);
+        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+        row.getEntry().noisy = true;
+        when(row.getIsNonblockable()).thenReturn(false);
+        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+        mGutsManager.initializeNotificationInfo(row, notificationInfoView,
+                NotificationInfo.ACTION_NONE);
+
+        verify(notificationInfoView).bindNotification(
+                any(PackageManager.class),
+                any(INotificationManager.class),
+                eq(statusBarNotification.getPackageName()),
+                any(NotificationChannel.class),
+                anyInt(),
+                eq(statusBarNotification),
+                any(NotificationInfo.CheckSaveListener.class),
+                any(NotificationInfo.OnSettingsClickListener.class),
+                any(NotificationInfo.OnAppSettingsClickListener.class),
+                eq(false),
+                eq(false),
+                eq(true) /* isForBlockingHelper */,
+                eq(true) /* isUserSentimentNegative */,
+                eq(true) /*isNoisy */,
+                eq(0),
+                eq(NotificationInfo.ACTION_NONE));
+    }
+
+    @Test
+    public void testInitializeNotificationInfoView_importance() throws Exception {
+        NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+        ExpandableNotificationRow row = spy(mHelper.createRow());
+        row.setBlockingHelperShowing(true);
+        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+        row.getEntry().importance = IMPORTANCE_DEFAULT;
+        when(row.getIsNonblockable()).thenReturn(false);
+        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+        mGutsManager.initializeNotificationInfo(row, notificationInfoView,
+                NotificationInfo.ACTION_NONE);
+
+        verify(notificationInfoView).bindNotification(
+                any(PackageManager.class),
+                any(INotificationManager.class),
+                eq(statusBarNotification.getPackageName()),
+                any(NotificationChannel.class),
+                anyInt(),
+                eq(statusBarNotification),
+                any(NotificationInfo.CheckSaveListener.class),
+                any(NotificationInfo.OnSettingsClickListener.class),
+                any(NotificationInfo.OnAppSettingsClickListener.class),
+                eq(false),
+                eq(false),
+                eq(true) /* isForBlockingHelper */,
+                eq(true) /* isUserSentimentNegative */,
+                eq(false) /*isNoisy */,
+                eq(IMPORTANCE_DEFAULT),
+                eq(NotificationInfo.ACTION_NONE));
     }
 
     @Test
@@ -337,7 +411,8 @@
         StatusBarNotification statusBarNotification = row.getStatusBarNotification();
         when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
 
-        mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+        mGutsManager.initializeNotificationInfo(row, notificationInfoView,
+                NotificationInfo.ACTION_NONE);
 
         verify(notificationInfoView).bindNotification(
                 any(PackageManager.class),
@@ -352,7 +427,41 @@
                 eq(true),
                 eq(false),
                 eq(false) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */);
+                eq(true) /* isUserSentimentNegative */,
+                eq(false) /*isNoisy */,
+                eq(0),
+                eq(NotificationInfo.ACTION_NONE));
+    }
+
+    @Test
+    public void testInitializeNotificationInfoView_withInitialAction() throws Exception {
+        NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+        ExpandableNotificationRow row = spy(mHelper.createRow());
+        row.setBlockingHelperShowing(true);
+        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+        when(row.getIsNonblockable()).thenReturn(false);
+        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+        mGutsManager.initializeNotificationInfo(row, notificationInfoView,
+                NotificationInfo.ACTION_BLOCK);
+
+        verify(notificationInfoView).bindNotification(
+                any(PackageManager.class),
+                any(INotificationManager.class),
+                eq(statusBarNotification.getPackageName()),
+                any(NotificationChannel.class),
+                anyInt(),
+                eq(statusBarNotification),
+                any(NotificationInfo.CheckSaveListener.class),
+                any(NotificationInfo.OnSettingsClickListener.class),
+                any(NotificationInfo.OnAppSettingsClickListener.class),
+                eq(false),
+                eq(false),
+                eq(true) /* isForBlockingHelper */,
+                eq(true) /* isUserSentimentNegative */,
+                eq(false) /*isNoisy */,
+                eq(0),
+                eq(NotificationInfo.ACTION_BLOCK));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index ca968a8..1cc1c63 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -17,11 +17,14 @@
 package com.android.systemui.statusbar.notification.row;
 
 import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
+import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 
@@ -56,6 +59,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.IBinder;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -72,6 +76,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -150,6 +155,15 @@
                 IMPORTANCE_LOW);
         mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
                 new Notification(), UserHandle.CURRENT, null, 0);
+
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
+    }
+
+    @After
+    public void tearDown() {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
     }
 
     // TODO: if tests are taking too long replace this with something that makes the animation
@@ -172,7 +186,8 @@
     public void testBindNotification_SetsTextApplicationName() throws Exception {
         when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
         assertTrue(textView.getText().toString().contains("App Name"));
         assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
@@ -184,7 +199,8 @@
         when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
                 .thenReturn(iconDrawable);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
         assertEquals(iconDrawable, iconView.getDrawable());
     }
@@ -192,7 +208,8 @@
     @Test
     public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
         assertEquals(GONE, groupNameView.getVisibility());
         final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
@@ -208,7 +225,8 @@
                 eq("test_group_id"), eq(TEST_PACKAGE_NAME), eq(TEST_UID)))
                 .thenReturn(notificationChannelGroup);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
         assertEquals(View.VISIBLE, groupNameView.getVisibility());
         assertEquals("Test Group Name", groupNameView.getText());
@@ -219,7 +237,8 @@
     @Test
     public void testBindNotification_SetsTextChannelName() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(TEST_CHANNEL_NAME, textView.getText());
     }
@@ -228,7 +247,7 @@
     public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
-                false);
+                false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(GONE, textView.getVisibility());
     }
@@ -241,7 +260,7 @@
                 eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
-                false);
+                false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(VISIBLE, textView.getVisibility());
     }
@@ -249,7 +268,8 @@
     @Test
     public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(VISIBLE, textView.getVisibility());
     }
@@ -257,18 +277,71 @@
     @Test
     public void testBindNotification_BlockButton() throws Exception {
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+               TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+               false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final View block = mNotificationInfo.findViewById(R.id.block);
+        final View toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
         final View minimize = mNotificationInfo.findViewById(R.id.minimize);
         assertEquals(VISIBLE, block.getVisibility());
+        assertEquals(GONE, toggleSilent.getVisibility());
         assertEquals(GONE, minimize.getVisibility());
     }
 
     @Test
+    public void testBindNotification_SilenceButton() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+        final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+        assertEquals(VISIBLE, toggleSilent.getVisibility());
+        assertEquals(
+                mContext.getString(R.string.inline_silent_button_silent), toggleSilent.getText());
+    }
+
+    @Test
+    public void testBindNotification_UnSilenceButton() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_LOW, NotificationInfo.ACTION_NONE);
+        final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+        assertEquals(VISIBLE, toggleSilent.getVisibility());
+        assertEquals(
+                mContext.getString(R.string.inline_silent_button_alert), toggleSilent.getText());
+    }
+
+    @Test
+    public void testBindNotification_SilenceButton_ChannelImportanceUnspecified() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+        final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+        assertEquals(VISIBLE, toggleSilent.getVisibility());
+        assertEquals(
+                mContext.getString(R.string.inline_silent_button_silent), toggleSilent.getText());
+    }
+
+    @Test
+    public void testBindNotification_UnSilenceButton_ChannelImportanceUnspecified()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_LOW, NotificationInfo.ACTION_NONE);
+        final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+        assertEquals(VISIBLE, toggleSilent.getVisibility());
+        assertEquals(
+                mContext.getString(R.string.inline_silent_button_alert), toggleSilent.getText());
+    }
+
+    @Test
     public void testBindNotification_MinButton() throws Exception {
         mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final View block = mNotificationInfo.findViewById(R.id.block);
         final View minimize = mNotificationInfo.findViewById(R.id.minimize);
         assertEquals(GONE, block.getVisibility());
@@ -283,7 +356,7 @@
                 (View v, NotificationChannel c, int appUid) -> {
                     assertEquals(mNotificationChannel, c);
                     latch.countDown();
-                }, null, true, false);
+                }, null, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         settingsButton.performClick();
@@ -294,7 +367,8 @@
     @Test
     public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         assertTrue(settingsButton.getVisibility() != View.VISIBLE);
     }
@@ -306,7 +380,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
                 (View v, NotificationChannel c, int appUid) -> {
                     assertEquals(mNotificationChannel, c);
-                }, null, false, false);
+                }, null, false, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         assertTrue(settingsButton.getVisibility() != View.VISIBLE);
     }
@@ -314,11 +388,12 @@
     @Test
     public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
                 (View v, NotificationChannel c, int appUid) -> {
-                }, null, true, false);
+                }, null, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         assertEquals(View.VISIBLE, settingsButton.getVisibility());
     }
@@ -326,7 +401,8 @@
     @Test
     public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
         verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
     }
@@ -335,7 +411,7 @@
     public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
-                true, true);
+                true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
         verify(mMetricsLogger, times(1)).count(anyString(), anyInt());
     }
@@ -348,7 +424,7 @@
                 (View v, NotificationChannel c, int appUid) -> {
                     assertEquals(null, c);
                     latch.countDown();
-                }, null, true, true);
+                }, null, true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.info).performClick();
         // Verify that listener was triggered.
@@ -361,7 +437,7 @@
             throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
-                null, true, true);
+                null, true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView channelNameView =
                 mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(GONE, channelNameView.getVisibility());
@@ -372,7 +448,7 @@
     public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
-                null, true, true);
+                null, true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView blockView = mNotificationInfo.findViewById(R.id.block);
         assertEquals(GONE, blockView.getVisibility());
     }
@@ -381,7 +457,7 @@
     public void testbindNotification_BlockingHelper() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, false,
-                true, true);
+                true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
         assertEquals(View.VISIBLE, view.getVisibility());
         assertEquals(mContext.getString(R.string.inline_blocking_helper), view.getText());
@@ -390,7 +466,8 @@
     @Test
     public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
         assertEquals(View.VISIBLE, view.getVisibility());
         assertEquals(mContext.getString(R.string.notification_unblockable_desc),
@@ -400,7 +477,8 @@
     @Test
     public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         mTestableLooper.processAllMessages();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), eq(TEST_UID), any());
@@ -410,7 +488,8 @@
     public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         mTestableLooper.processAllMessages();
@@ -423,7 +502,8 @@
             throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         mTestableLooper.processAllMessages();
@@ -432,11 +512,40 @@
     }
 
     @Test
+    public void testDoesNotUpdateNotificationChannelAfterImportanceChangedSilenced()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), any());
+    }
+
+    @Test
+    public void testDoesNotUpdateNotificationChannelAfterImportanceChangedUnSilenced()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), any());
+    }
+
+    @Test
     public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
             throws Exception {
         int originalImportance = mNotificationChannel.getImportance();
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.handleCloseControls(true, false);
         mTestableLooper.processAllMessages();
@@ -450,7 +559,8 @@
             throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.handleCloseControls(true, false);
 
@@ -468,7 +578,8 @@
                 TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
                 10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
                 null /* onSettingsClick */, null /* onAppSettingsClick */ ,
-                true, false /* isNonblockable */);
+                true, false /* isNonblockable */, false /* isNoisy */, IMPORTANCE_DEFAULT,
+                NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -488,8 +599,9 @@
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
                 10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
-                true, false /* isNonblockable */);
+                null /* onSettingsClick */, null /* onAppSettingsClick */,
+                true, false /* isNonblockable */, false /* isNoisy */, IMPORTANCE_DEFAULT,
+                NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -510,7 +622,8 @@
                 null /* onSettingsClick */, null /* onAppSettingsClick */ ,
                 true /* provisioned */,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
+                true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT,
+                NotificationInfo.ACTION_NONE);
 
         NotificationGuts guts = spy(new NotificationGuts(mContext, null));
         when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -538,7 +651,8 @@
                 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
                 null /* onSettingsClick */, null /* onAppSettingsClick */ , true /* provisioned */,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
+                true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT,
+                NotificationInfo.ACTION_NONE);
 
         NotificationGuts guts = spy(new NotificationGuts(mContext, null));
         when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -566,7 +680,8 @@
                 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
                 null /* onSettingsClick */, null /* onAppSettingsClick */ ,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
-                true, true /* isUserSentimentNegative */);
+                true, true /* isUserSentimentNegative */, false /* isNoisy */,
+                IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
 
@@ -585,7 +700,8 @@
                 null /* onSettingsClick */, null /* onAppSettingsClick */,
                 true /* provisioned */,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
+                true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT,
+                NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         mTestableLooper.processAllMessages();
@@ -607,7 +723,8 @@
                 false /* isNonblockable */,
                 true /* isForBlockingHelper */,
                 true,
-                false /* isUserSentimentNegative */);
+                false /* isUserSentimentNegative */,
+                false /* isNoisy */, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         NotificationGuts guts = mock(NotificationGuts.class);
         doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
         mNotificationInfo.setGutsParent(guts);
@@ -621,7 +738,8 @@
     public void testNonBlockableAppDoesNotBecomeBlocked() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
 
@@ -634,7 +752,8 @@
     public void testBlockChangedCallsUpdateNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -666,7 +785,8 @@
                 true /*provisioned */,
                 false /* isNonblockable */,
                 true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
+                true /* isUserSentimentNegative */,
+                false/* isNoisy */, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -687,7 +807,8 @@
     public void testNonBlockableAppDoesNotBecomeMin() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         waitForUndoButton();
 
@@ -701,7 +822,8 @@
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         waitForUndoButton();
@@ -721,7 +843,8 @@
     public void testKeepUpdatesNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.handleCloseControls(true, false);
 
@@ -738,7 +861,8 @@
     public void testBlockUndoDoesNotBlockNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -759,7 +883,8 @@
     public void testMinUndoDoesNotMinNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         waitForUndoButton();
@@ -777,10 +902,97 @@
     }
 
     @Test
+    public void testSilenceCallsUpdateNotificationChannel() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance());
+    }
+
+    @Test
+    public void testUnSilenceCallsUpdateNotificationChannel() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_HIGH, updated.getValue().getImportance());
+    }
+
+    @Test
+    public void testSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance());
+    }
+
+    @Test
+    public void testUnSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_LOW, NotificationInfo.ACTION_NONE);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_HIGH, updated.getValue().getImportance());
+    }
+
+    @Test
     public void testCloseControlsDoesNotUpdateiMinIfSaveIsFalse() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         waitForUndoButton();
@@ -795,7 +1007,8 @@
     public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -812,7 +1025,7 @@
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
                 (Runnable saveImportance, StatusBarNotification sbn) -> {
-                }, null, null, true, true);
+                }, null, null, true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         mTestableLooper.processAllMessages();
@@ -830,7 +1043,8 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
                 (Runnable saveImportance, StatusBarNotification sbn) -> {
                     saveImportance.run();
-                }, null, null, true, false);
+                }, null, null, true, false, false, IMPORTANCE_DEFAULT,
+                NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         mTestableLooper.processAllMessages();
@@ -866,7 +1080,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null,
                 (View v, Intent intent) -> {
                     latch.countDown();
-                }, true, false);
+                }, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
         assertEquals(View.VISIBLE, settingsLink.getVisibility());
         settingsLink.performClick();
@@ -894,7 +1108,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
                 (View v, Intent intent) -> {
                     latch.countDown();
-                }, true, false);
+                }, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
         assertEquals(View.VISIBLE, settingsLink.getVisibility());
         settingsLink.performClick();
@@ -913,7 +1127,7 @@
 
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
-                null, true, false);
+                null, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
         assertEquals(GONE, settingsLink.getVisibility());
     }
@@ -933,7 +1147,8 @@
                 0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
 
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
         assertEquals(GONE, settingsLink.getVisibility());
     }
@@ -956,7 +1171,7 @@
 
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false, true,
-                true, true);
+                true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
         final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
         assertEquals(GONE, settingsLink.getVisibility());
     }
@@ -972,7 +1187,8 @@
         mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         waitForUndoButton();
@@ -984,7 +1200,8 @@
     public void testUndoText_block() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -993,10 +1210,39 @@
     }
 
     @Test
+    public void testUndoText_silence() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        waitForUndoButton();
+        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
+        assertEquals(mContext.getString(R.string.notification_channel_silenced),
+                confirmationText.getText());
+    }
+
+    @Test
+    public void testUndoText_unsilence() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        waitForUndoButton();
+        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
+        assertEquals(mContext.getString(R.string.notification_channel_unsilenced),
+                confirmationText.getText());
+    }
+
+    @Test
     public void testNoHeaderOnConfirmation() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -1007,7 +1253,8 @@
     public void testHeaderOnUndo() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -1015,4 +1262,60 @@
         waitForStopButton();
         assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
     }
+
+    @Test
+    public void testBindNotificationWithInitialBlockAction() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_BLOCK);
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
+    }
+
+    @Test
+    public void testBindNotificationWithInitialSilenceAction() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_TOGGLE_SILENT);
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance());
+    }
+
+    @Test
+    public void testBindNotificationWithInitialUnSilenceAction() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_LOW, NotificationInfo.ACTION_TOGGLE_SILENT);
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_HIGH, updated.getValue().getImportance());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
index f2431b4..a4a111a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
@@ -18,7 +18,10 @@
 
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -26,8 +29,8 @@
 import android.view.View;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -58,39 +61,105 @@
                 -> mRoundnessManager.onHeadsupAnimatingAwayChanged(mSecond, animatingAway));
         mRoundnessManager.setOnRoundingChangedCallback(mRoundnessCallback);
         mRoundnessManager.setAnimatedChildren(mAnimatedChildren);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mFirst, mFirst);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mFirst, mFirst),
+                createSection(null, null)
+        });
         mRoundnessManager.setExpanded(1.0f, 1.0f);
+        reset(mRoundnessCallback);
     }
 
     @Test
     public void testCallbackCalledWhenSecondChanged() {
-        mRoundnessManager.setFirstAndLastBackgroundChild(mFirst, mSecond);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mFirst, mSecond),
+                createSection(null, null)
+        });
         verify(mRoundnessCallback, atLeast(1)).run();
     }
 
     @Test
     public void testCallbackCalledWhenFirstChanged() {
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mFirst);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mSecond, mFirst),
+                createSection(null, null)
+        });
         verify(mRoundnessCallback, atLeast(1)).run();
     }
 
     @Test
+    public void testCallbackCalledWhenSecondSectionFirstChanged() {
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mFirst, mFirst),
+                createSection(mSecond, null)
+        });
+        verify(mRoundnessCallback, atLeast(1)).run();
+    }
+
+    @Test
+    public void testCallbackCalledWhenSecondSectionLastChanged() {
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mFirst, mFirst),
+                createSection(null, mSecond)
+        });
+        verify(mRoundnessCallback, atLeast(1)).run();
+    }
+
+    @Test
+    public void testCallbackNotCalledWhenFirstChangesSections() {
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(null, mFirst),
+                createSection(mFirst, null)
+        });
+        verify(mRoundnessCallback, never()).run();
+    }
+
+    @Test
     public void testRoundnessSetOnLast() {
-        mRoundnessManager.setFirstAndLastBackgroundChild(mFirst, mSecond);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mFirst, mSecond),
+                createSection(null, null)
+        });
         Assert.assertEquals(1.0f, mSecond.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(0.0f, mSecond.getCurrentTopRoundness(), 0.0f);
     }
 
     @Test
+    public void testRoundnessSetOnSecondSectionLast() {
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mFirst, mFirst),
+                createSection(null, mSecond)
+        });
+        Assert.assertEquals(1.0f, mSecond.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(0.0f, mSecond.getCurrentTopRoundness(), 0.0f);
+    }
+
+    @Test
+    public void testRoundnessSetOnSecondSectionFirst() {
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mFirst, mFirst),
+                createSection(mSecond, null)
+        });
+        Assert.assertEquals(0.0f, mSecond.getCurrentBottomRoundness(), 0.0f);
+        Assert.assertEquals(1.0f, mSecond.getCurrentTopRoundness(), 0.0f);
+    }
+
+    @Test
     public void testRoundnessSetOnNew() {
-        mRoundnessManager.setFirstAndLastBackgroundChild(mFirst, null);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mFirst, null),
+                createSection(null, null)
+        });
         Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
     }
 
     @Test
     public void testCompleteReplacement() {
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mSecond, mSecond),
+                createSection(null, null)
+        });
         Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
     }
@@ -98,7 +167,10 @@
     @Test
     public void testNotCalledWhenRemoved() {
         mFirst.setRemoved();
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mSecond, mSecond),
+                createSection(null, null)
+        });
         Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
     }
@@ -107,7 +179,10 @@
     public void testRoundedWhenPinnedAndCollapsed() {
         mFirst.setPinned(true);
         mRoundnessManager.setExpanded(0.0f /* expandedHeight */, 0.0f /* appearFraction */);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mSecond, mSecond),
+                createSection(null, null)
+        });
         Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
     }
@@ -116,7 +191,10 @@
     public void testRoundedWhenGoingAwayAndCollapsed() {
         mFirst.setHeadsUpAnimatingAway(true);
         mRoundnessManager.setExpanded(0.0f /* expandedHeight */, 0.0f /* appearFraction */);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mSecond, mSecond),
+                createSection(null, null)
+        });
         Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
     }
@@ -125,7 +203,10 @@
     public void testRoundedNormalRoundingWhenExpanded() {
         mFirst.setHeadsUpAnimatingAway(true);
         mRoundnessManager.setExpanded(1.0f /* expandedHeight */, 0.0f /* appearFraction */);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mSecond, mSecond),
+                createSection(null, null)
+        });
         Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
     }
@@ -134,7 +215,10 @@
     public void testTrackingHeadsUpRoundedIfPushingUp() {
         mRoundnessManager.setExpanded(1.0f /* expandedHeight */, -0.5f /* appearFraction */);
         mRoundnessManager.setTrackingHeadsUp(mFirst);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mSecond, mSecond),
+                createSection(null, null)
+        });
         Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
     }
@@ -143,7 +227,10 @@
     public void testTrackingHeadsUpNotRoundedIfPushingDown() {
         mRoundnessManager.setExpanded(1.0f /* expandedHeight */, 0.5f /* appearFraction */);
         mRoundnessManager.setTrackingHeadsUp(mFirst);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mSecond, mSecond),
+                createSection(null, null)
+        });
         Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
     }
@@ -151,7 +238,10 @@
     @Test
     public void testRoundingUpdatedWhenAnimatingAwayTrue() {
         mRoundnessManager.setExpanded(0.0f, 0.0f);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mSecond, mSecond),
+                createSection(null, null)
+        });
         mFirst.setHeadsUpAnimatingAway(true);
         Assert.assertEquals(1.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(1.0f, mFirst.getCurrentTopRoundness(), 0.0f);
@@ -161,10 +251,49 @@
     @Test
     public void testRoundingUpdatedWhenAnimatingAwayFalse() {
         mRoundnessManager.setExpanded(0.0f, 0.0f);
-        mRoundnessManager.setFirstAndLastBackgroundChild(mSecond, mSecond);
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mSecond, mSecond),
+                createSection(null, null)
+        });
         mFirst.setHeadsUpAnimatingAway(true);
         mFirst.setHeadsUpAnimatingAway(false);
         Assert.assertEquals(0.0f, mFirst.getCurrentBottomRoundness(), 0.0f);
         Assert.assertEquals(0.0f, mFirst.getCurrentTopRoundness(), 0.0f);
     }
+
+    @Test
+    public void testNoViewsFirstOrLastInSectionWhenSecondSectionEmpty() {
+        Assert.assertFalse(mFirst.isFirstInSection());
+        Assert.assertFalse(mFirst.isLastInSection());
+    }
+
+    @Test
+    public void testNoViewsFirstOrLastInSectionWhenFirstSectionEmpty() {
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(null, null),
+                createSection(mSecond, mSecond)
+        });
+        Assert.assertFalse(mSecond.isFirstInSection());
+        Assert.assertFalse(mSecond.isLastInSection());
+    }
+
+    @Test
+    public void testFirstAndLastViewsInSectionSetWhenBothSectionsNonEmpty() {
+        mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
+                createSection(mFirst, mFirst),
+                createSection(mSecond, mSecond)
+        });
+        Assert.assertFalse(mFirst.isFirstInSection());
+        Assert.assertTrue(mFirst.isLastInSection());
+        Assert.assertTrue(mSecond.isFirstInSection());
+        Assert.assertFalse(mSecond.isLastInSection());
+    }
+
+    private NotificationSection createSection(ExpandableNotificationRow first,
+            ExpandableNotificationRow last) {
+        NotificationSection section = mock(NotificationSection.class);
+        when(section.getFirstVisibleChild()).thenReturn(first);
+        when(section.getLastVisibleChild()).thenReturn(last);
+        return section;
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index fdd89de..74ce5f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -13,6 +13,8 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
+import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
@@ -23,6 +25,7 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doNothing;
@@ -36,6 +39,7 @@
 import android.os.IPowerManager;
 import android.os.Looper;
 import android.os.PowerManager;
+import android.provider.Settings;
 import android.service.dreams.IDreamManager;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
@@ -67,6 +71,7 @@
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarTest.TestableNotificationEntryManager;
 
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
@@ -102,6 +107,7 @@
     @Mock private IDreamManager mDreamManager;
     private PowerManager mPowerManager;
     private TestableNotificationEntryManager mEntryManager;
+    private int mOriginalInterruptionModelSetting;
 
     @Before
     @UiThreadTest
@@ -147,6 +153,17 @@
         doNothing().when(mGroupManager).collapseAllGroups();
         doNothing().when(mExpandHelper).cancelImmediately();
         doNothing().when(notificationShelf).setAnimationsEnabled(anyBoolean());
+
+        mOriginalInterruptionModelSetting = Settings.Secure.getInt(mContext.getContentResolver(),
+                NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
+    }
+
+    @After
+    public void tearDown() {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                NOTIFICATION_NEW_INTERRUPTION_MODEL, mOriginalInterruptionModelSetting);
     }
 
     @Test
@@ -318,6 +335,64 @@
     }
 
     @Test
+    public void testUpdateGapIndex_allHighPriority() {
+        when(mStackScroller.getChildCount()).thenReturn(3);
+        for (int i = 0; i < 3; i++) {
+            ExpandableNotificationRow row = mock(ExpandableNotificationRow.class,
+                    RETURNS_DEEP_STUBS);
+            String key = Integer.toString(i);
+            when(row.getStatusBarNotification().getKey()).thenReturn(key);
+            when(mNotificationData.isHighPriority(row.getStatusBarNotification())).thenReturn(true);
+            when(mStackScroller.getChildAt(i)).thenReturn(row);
+        }
+
+        mStackScroller.updateSectionBoundaries();
+        assertEquals(-1, mStackScroller.getSectionBoundaryIndex(0));
+    }
+
+    @Test
+    public void testUpdateGapIndex_allLowPriority() {
+        when(mStackScroller.getChildCount()).thenReturn(3);
+        for (int i = 0; i < 3; i++) {
+            ExpandableNotificationRow row = mock(ExpandableNotificationRow.class,
+                    RETURNS_DEEP_STUBS);
+            String key = Integer.toString(i);
+            when(row.getStatusBarNotification().getKey()).thenReturn(key);
+            when(mNotificationData.isHighPriority(row.getStatusBarNotification()))
+                    .thenReturn(false);
+            when(mStackScroller.getChildAt(i)).thenReturn(row);
+        }
+
+        mStackScroller.updateSectionBoundaries();
+        assertEquals(-1, mStackScroller.getSectionBoundaryIndex(0));
+    }
+
+    @Test
+    public void testUpdateGapIndex_gapExists() {
+        when(mStackScroller.getChildCount()).thenReturn(6);
+        for (int i = 0; i < 6; i++) {
+            ExpandableNotificationRow row = mock(ExpandableNotificationRow.class,
+                    RETURNS_DEEP_STUBS);
+            String key = Integer.toString(i);
+            when(row.getStatusBarNotification().getKey()).thenReturn(key);
+            when(mNotificationData.isHighPriority(row.getStatusBarNotification()))
+                    .thenReturn(i < 3);
+            when(mStackScroller.getChildAt(i)).thenReturn(row);
+        }
+
+        mStackScroller.updateSectionBoundaries();
+        assertEquals(3, mStackScroller.getSectionBoundaryIndex(0));
+    }
+
+    @Test
+    public void testUpdateGapIndex_empty() {
+        when(mStackScroller.getChildCount()).thenReturn(0);
+
+        mStackScroller.updateSectionBoundaries();
+        assertEquals(-1, mStackScroller.getSectionBoundaryIndex(0));
+    }
+
+    @Test
     public void testOnDensityOrFontScaleChanged_reInflatesFooterViews() {
         clearInvocations(mStackScroller);
         mStackScroller.onDensityOrFontScaleChanged();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index b5f67c0..dcd5946 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -15,22 +15,13 @@
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.mockitoSession;
-import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -38,49 +29,36 @@
 
 import android.animation.Animator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.content.Context;
-import android.graphics.Rect;
 import android.os.Handler;
-import android.os.IPowerManager;
-import android.os.Looper;
-import android.os.PowerManager;
 import android.service.notification.StatusBarNotification;
-import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
-import android.testing.TestableLooper.RunWithLooper;
+import android.testing.UiThreadTest;
 import android.view.MotionEvent;
-import android.view.VelocityTracker;
 import android.view.View;
-import android.view.MotionEvent;
 
 import com.android.systemui.SwipeHelper;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.NotificationMenuRow;
 
-import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoSession;
-import org.mockito.invocation.InvocationOnMock;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 import org.mockito.stubbing.Answer;
 
-import java.util.ArrayList;
-
 /**
  * Tests for {@link NotificationSwipeHelper}.
  */
 @SmallTest
+@Ignore
 @RunWith(AndroidJUnit4.class)
+@UiThreadTest
 public class NotificationSwipeHelperTest extends SysuiTestCase {
 
     private NotificationSwipeHelper mSwipeHelper;
@@ -96,7 +74,6 @@
     @Rule public MockitoRule mockito = MockitoJUnit.rule();
 
     @Before
-    @UiThreadTest
     public void setUp() throws Exception {
         mCallback = mock(NotificationSwipeHelper.NotificationCallback.class);
         mListener = mock(NotificationMenuRowPlugin.OnMenuEventListener.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index 23365a4..1481aef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -19,22 +19,22 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
+import android.hardware.display.ColorDisplayManager;
 import android.os.Handler;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
+
 import com.android.internal.app.ColorDisplayController;
-import com.android.systemui.Dependency;
-import com.android.systemui.Prefs;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.qs.AutoAddTracker;
 import com.android.systemui.qs.QSTileHost;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 @RunWith(AndroidTestingRunner.class)
@@ -56,7 +56,7 @@
 
     @Test
     public void nightTileAdded_whenActivated() {
-        if (!ColorDisplayController.isAvailable(mContext)) {
+        if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             return;
         }
         mAutoTileManager.mColorDisplayCallback.onActivated(true);
@@ -65,7 +65,7 @@
 
     @Test
     public void nightTileNotAdded_whenDeactivated() {
-        if (!ColorDisplayController.isAvailable(mContext)) {
+        if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             return;
         }
         mAutoTileManager.mColorDisplayCallback.onActivated(false);
@@ -74,7 +74,7 @@
 
     @Test
     public void nightTileAdded_whenNightModeTwilight() {
-        if (!ColorDisplayController.isAvailable(mContext)) {
+        if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             return;
         }
         mAutoTileManager.mColorDisplayCallback.onAutoModeChanged(
@@ -84,7 +84,7 @@
 
     @Test
     public void nightTileAdded_whenNightModeCustom() {
-        if (!ColorDisplayController.isAvailable(mContext)) {
+        if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             return;
         }
         mAutoTileManager.mColorDisplayCallback.onAutoModeChanged(
@@ -94,7 +94,7 @@
 
     @Test
     public void nightTileNotAdded_whenNightModeDisabled() {
-        if (!ColorDisplayController.isAvailable(mContext)) {
+        if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
             return;
         }
         mAutoTileManager.mColorDisplayCallback.onAutoModeChanged(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
index 231cdf5..93d8aad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
@@ -18,24 +18,25 @@
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.when;
 
 import android.app.StatusBarManager;
 import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 import android.view.ViewPropertyAnimator;
 
 import com.android.systemui.R;
-import android.testing.AndroidTestingRunner;
-
 import com.android.systemui.SysuiBaseFragmentTest;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.tuner.TunerService;
-import android.testing.TestableLooper.RunWithLooper;
 
 import org.junit.Before;
-import org.junit.runner.RunWith;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mockito;
 
 @RunWith(AndroidTestingRunner.class)
@@ -45,6 +46,7 @@
 
     private NotificationIconAreaController mMockNotificiationAreaController;
     private View mNotificationAreaInner;
+    private StatusBarStateController mStatusBarStateController;
 
     public CollapsedStatusBarFragmentTest() {
         super(CollapsedStatusBarFragment.class);
@@ -55,6 +57,8 @@
         mSysuiContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
         mSysuiContext.putComponent(StatusBar.class, mock(StatusBar.class));
         mSysuiContext.putComponent(TunerService.class, mock(TunerService.class));
+        mStatusBarStateController = mDependency
+                .injectMockDependency(StatusBarStateController.class);
         injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
         mMockNotificiationAreaController = mock(NotificationIconAreaController.class);
         mNotificationAreaInner = mock(View.class);
@@ -127,4 +131,23 @@
 
         assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.clock).getVisibility());
     }
+
+    @Test
+    public void testOnDozingChanged() throws Exception {
+        mFragments.dispatchResume();
+        processAllMessages();
+
+        CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+        fragment.initNotificationIconArea(mMockNotificiationAreaController);
+        fragment.disable(StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
+
+        Mockito.verify(mNotificationAreaInner).setVisibility(eq(View.INVISIBLE));
+
+        reset(mStatusBarStateController);
+        when(mStatusBarStateController.isDozing()).thenReturn(true);
+        fragment.onDozingChanged(true);
+
+        Mockito.verify(mStatusBarStateController).isDozing();
+        Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.VISIBLE));
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
new file mode 100644
index 0000000..f8ad298
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
+
+    private static final int SCREEN_HEIGHT = 2000;
+    private static final int EMPTY_MARGIN = 0;
+    private static final int EMPTY_HEIGHT = 0;
+    private static final boolean SECURE_LOCKED = false;
+    private static final boolean PULSING_NO = false;
+    private static final float ZERO_DRAG = 0.f;
+    private static final float OPAQUE = 1.f;
+    private static final float TRANSPARENT = 0.f;
+
+    private KeyguardClockPositionAlgorithm mClockPositionAlgorithm;
+    private KeyguardClockPositionAlgorithm.Result mClockPosition;
+    private int mNotificationStackHeight;
+    private float mPanelExpansion;
+    private int mKeyguardStatusHeight;
+    private float mDark;
+
+    @Before
+    public void setUp() {
+        mClockPositionAlgorithm = new KeyguardClockPositionAlgorithm();
+        mClockPosition = new KeyguardClockPositionAlgorithm.Result();
+    }
+
+    @Test
+    public void clockPositionMiddleOfScreenOnAOD() {
+        // GIVEN on AOD and both stack scroll and clock have 0 height
+        givenAOD();
+        mNotificationStackHeight = EMPTY_HEIGHT;
+        mKeyguardStatusHeight = EMPTY_HEIGHT;
+        // WHEN the clock position algorithm is run
+        positionClock();
+        // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2).
+        assertThat(mClockPosition.clockY).isEqualTo(1000);
+        // AND the clock is opaque and positioned on the left.
+        assertThat(mClockPosition.clockX).isEqualTo(0);
+        assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
+    }
+
+    @Test
+    public void clockPositionAdjustsForKeyguardStatusOnAOD() {
+        // GIVEN on AOD with a clock of height 100
+        givenAOD();
+        mNotificationStackHeight = EMPTY_HEIGHT;
+        mKeyguardStatusHeight = 100;
+        // WHEN the clock position algorithm is run
+        positionClock();
+        // THEN the clock Y position adjusts for the clock height (SCREEN_HEIGHT / 2 - 100).
+        assertThat(mClockPosition.clockY).isEqualTo(900);
+        // AND the clock is opaque and positioned on the left.
+        assertThat(mClockPosition.clockX).isEqualTo(0);
+        assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
+    }
+
+    @Test
+    public void clockPositionLargeClockOnAOD() {
+        // GIVEN on AOD with a full screen clock
+        givenAOD();
+        mNotificationStackHeight = EMPTY_HEIGHT;
+        mKeyguardStatusHeight = SCREEN_HEIGHT;
+        // WHEN the clock position algorithm is run
+        positionClock();
+        // THEN the clock Y position doesn't overflow the screen.
+        assertThat(mClockPosition.clockY).isEqualTo(0);
+        // AND the clock is opaque and positioned on the left.
+        assertThat(mClockPosition.clockX).isEqualTo(0);
+        assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
+    }
+
+    @Test
+    public void clockPositionMiddleOfScreenOnLockScreen() {
+        // GIVEN on lock screen with stack scroll and clock of 0 height
+        givenLockScreen();
+        mNotificationStackHeight = EMPTY_HEIGHT;
+        mKeyguardStatusHeight = EMPTY_HEIGHT;
+        // WHEN the clock position algorithm is run
+        positionClock();
+        // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2).
+        assertThat(mClockPosition.clockY).isEqualTo(1000);
+        // AND the clock is opaque and positioned on the left.
+        assertThat(mClockPosition.clockX).isEqualTo(0);
+        assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
+    }
+
+    @Test
+    public void clockPositionWithStackScrollExpandOnLockScreen() {
+        // GIVEN on lock screen with stack scroll of height 500
+        givenLockScreen();
+        mNotificationStackHeight = 500;
+        mKeyguardStatusHeight = EMPTY_HEIGHT;
+        // WHEN the clock position algorithm is run
+        positionClock();
+        // THEN the clock Y position adjusts for stack scroll height ( (SCREEN_HEIGHT - 500 ) / 2).
+        assertThat(mClockPosition.clockY).isEqualTo(750);
+        // AND the clock is opaque and positioned on the left.
+        assertThat(mClockPosition.clockX).isEqualTo(0);
+        assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE);
+    }
+
+    @Test
+    public void clockPositionWithPartialDragOnLockScreen() {
+        // GIVEN dragging up on lock screen
+        givenLockScreen();
+        mNotificationStackHeight = EMPTY_HEIGHT;
+        mKeyguardStatusHeight = EMPTY_HEIGHT;
+        mPanelExpansion = 0.5f;
+        // WHEN the clock position algorithm is run
+        positionClock();
+        // THEN the clock Y position adjusts with drag gesture.
+        assertThat(mClockPosition.clockY).isLessThan(1000);
+        // AND the clock is positioned on the left and not fully opaque.
+        assertThat(mClockPosition.clockX).isEqualTo(0);
+        assertThat(mClockPosition.clockAlpha).isLessThan(OPAQUE);
+    }
+
+    @Test
+    public void clockPositionWithFullDragOnLockScreen() {
+        // GIVEN the lock screen is dragged up
+        givenLockScreen();
+        mNotificationStackHeight = EMPTY_HEIGHT;
+        mKeyguardStatusHeight = EMPTY_HEIGHT;
+        mPanelExpansion = 0.f;
+        // WHEN the clock position algorithm is run
+        positionClock();
+        // THEN the clock is transparent.
+        assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT);
+    }
+
+    @Test
+    public void largeClockOnLockScreenIsTransparent() {
+        // GIVEN on lock screen with a full screen clock
+        givenLockScreen();
+        mNotificationStackHeight = EMPTY_HEIGHT;
+        mKeyguardStatusHeight = SCREEN_HEIGHT;
+        // WHEN the clock position algorithm is run
+        positionClock();
+        // THEN the clock is transparent
+        assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT);
+    }
+
+    private void givenAOD() {
+        mPanelExpansion = 1.f;
+        mDark = 1.f;
+    }
+
+    private void givenLockScreen() {
+        mPanelExpansion = 1.f;
+        mDark = 0.f;
+    }
+
+    private void positionClock() {
+        mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
+                mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mDark, SECURE_LOCKED,
+                PULSING_NO, ZERO_DRAG);
+        mClockPositionAlgorithm.run(mClockPosition);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
new file mode 100644
index 0000000..0031c32
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static org.mockito.ArgumentMatchers.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.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.LightBarTransitionsController.DarkIntensityApplier;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class LightBarTransitionsControllerTest extends SysuiTestCase {
+
+    @Mock
+    private DarkIntensityApplier mApplier;
+    private LightBarTransitionsController mLightBarTransitionsController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
+        mLightBarTransitionsController = new LightBarTransitionsController(mContext, mApplier);
+    }
+
+    @Test
+    public void setIconsDark_lightAndDark() {
+        mLightBarTransitionsController.setIconsDark(true /* dark */, false /* animate */);
+        verify(mApplier).applyDarkIntensity(eq(1f));
+
+        mLightBarTransitionsController.setIconsDark(false /* dark */, false /* animate */);
+        verify(mApplier).applyDarkIntensity(eq(0f));
+    }
+
+    @Test
+    public void onDozeAmountChanged_lightWhenDozing() {
+        mLightBarTransitionsController.onDozeAmountChanged(1f /* linear */, 1f /* eased */);
+        mLightBarTransitionsController.setIconsDark(true /* dark */, false /* animate */);
+        verify(mApplier, times(2)).applyDarkIntensity(eq(0f));
+
+        reset(mApplier);
+        mLightBarTransitionsController.setIconsDark(false /* dark */, false /* animate */);
+        verify(mApplier).applyDarkIntensity(eq(0f));
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java
new file mode 100644
index 0000000..4177cd1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/QuickStepControllerTest.java
@@ -0,0 +1,641 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
+
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.anyFloat;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import com.android.systemui.R;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.recents.IOverviewProxy;
+import com.android.systemui.SysuiTestCase;
+
+import android.content.res.Resources;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.MotionEvent;
+import android.view.View;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.MockitoAnnotations;
+
+/** atest QuickStepControllerTest */
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+@SmallTest
+public class QuickStepControllerTest extends SysuiTestCase {
+    private QuickStepController mController;
+    private NavigationBarView mNavigationBarView;
+    private StatusBar mStatusBar;
+    private OverviewProxyService mProxyService;
+    private IOverviewProxy mProxy;
+    private Resources mResources;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        final ButtonDispatcher backButton = mock(ButtonDispatcher.class);
+        mResources = mock(Resources.class);
+
+        mProxyService = mock(OverviewProxyService.class);
+        mProxy = mock(IOverviewProxy.Stub.class);
+        doReturn(mProxy).when(mProxyService).getProxy();
+        mDependency.injectTestDependency(OverviewProxyService.class, mProxyService);
+
+        mStatusBar = mock(StatusBar.class);
+        doReturn(false).when(mStatusBar).isKeyguardShowing();
+        mContext.putComponent(StatusBar.class, mStatusBar);
+
+        mNavigationBarView = mock(NavigationBarView.class);
+        doReturn(false).when(mNavigationBarView).inScreenPinning();
+        doReturn(true).when(mNavigationBarView).isNotificationsFullyCollapsed();
+        doReturn(true).when(mNavigationBarView).isQuickScrubEnabled();
+        doReturn(HIT_TARGET_NONE).when(mNavigationBarView).getDownHitTarget();
+        doReturn(backButton).when(mNavigationBarView).getBackButton();
+        doReturn(mResources).when(mNavigationBarView).getResources();
+
+        mController = new QuickStepController(mContext);
+        mController.setComponents(mNavigationBarView);
+        mController.setBarState(false /* isRTL */, NAV_BAR_BOTTOM);
+    }
+
+    @Test
+    public void testNoActionsNoGestures() throws Exception {
+        MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1);
+        assertFalse(mController.onInterceptTouchEvent(ev));
+        verify(mNavigationBarView, never()).requestUnbufferedDispatch(ev);
+        assertNull(mController.getCurrentAction());
+    }
+
+    @Test
+    public void testHasActionDetectGesturesTouchdown() throws Exception {
+        MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1);
+
+        // Add enabled gesture action
+        NavigationGestureAction action = mockAction(true);
+        mController.setGestureActions(action, null /* swipeDownAction */,
+                null /* swipeLeftAction */, null /* swipeRightAction */);
+
+        assertFalse(mController.onInterceptTouchEvent(ev));
+        verify(mNavigationBarView, times(1)).requestUnbufferedDispatch(ev);
+        verify(action, times(1)).reset();
+        verify(mProxy, times(1)).onPreMotionEvent(mNavigationBarView.getDownHitTarget());
+        verify(mProxy, times(1)).onMotionEvent(ev);
+        assertNull(mController.getCurrentAction());
+    }
+
+    @Test
+    public void testProxyDisconnectedNoGestures() throws Exception {
+        MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1);
+
+        // Add enabled gesture action
+        mController.setGestureActions(mockAction(true), null /* swipeDownAction */,
+                null /* swipeLeftAction */, null /* swipeRightAction */);
+
+        // Set the gesture on deadzone
+        doReturn(null).when(mProxyService).getProxy();
+
+        assertFalse(mController.onInterceptTouchEvent(ev));
+        verify(mNavigationBarView, never()).requestUnbufferedDispatch(ev);
+        assertNull(mController.getCurrentAction());
+    }
+
+    @Test
+    public void testNoActionsNoGesturesOverDeadzone() throws Exception {
+        MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1);
+
+        // Touched over deadzone
+        doReturn(HIT_TARGET_DEAD_ZONE).when(mNavigationBarView).getDownHitTarget();
+
+        assertTrue(mController.onInterceptTouchEvent(ev));
+        verify(mNavigationBarView, never()).requestUnbufferedDispatch(ev);
+        assertNull(mController.getCurrentAction());
+    }
+
+    @Test
+    public void testOnTouchIgnoredDownEventAfterOnIntercept() {
+        mController.setGestureActions(mockAction(true), null /* swipeDownAction */,
+                null /* swipeLeftAction */, null /* swipeRightAction */);
+
+        MotionEvent ev = event(MotionEvent.ACTION_DOWN, 1, 1);
+        assertFalse(touch(ev));
+        verify(mNavigationBarView, times(1)).requestUnbufferedDispatch(ev);
+
+        // OnTouch event for down is ignored, so requestUnbufferedDispatch ran once from before
+        assertFalse(mNavigationBarView.onTouchEvent(ev));
+        verify(mNavigationBarView, times(1)).requestUnbufferedDispatch(ev);
+    }
+
+    @Test
+    public void testGesturesCallCorrectAction() throws Exception {
+        NavigationGestureAction swipeUp = mockAction(true);
+        NavigationGestureAction swipeDown = mockAction(true);
+        NavigationGestureAction swipeLeft = mockAction(true);
+        NavigationGestureAction swipeRight = mockAction(true);
+        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+
+        // Swipe Up
+        assertGestureTriggersAction(swipeUp, 1, 100, 5, 1);
+        // Swipe Down
+        assertGestureTriggersAction(swipeDown, 1, 1, 5, 100);
+        // Swipe Left
+        assertGestureTriggersAction(swipeLeft, 100, 1, 5, 1);
+        // Swipe Right
+        assertGestureTriggersAction(swipeRight, 1, 1, 100, 5);
+    }
+
+    @Test
+    public void testGesturesCallCorrectActionLandscape() throws Exception {
+        NavigationGestureAction swipeUp = mockAction(true);
+        NavigationGestureAction swipeDown = mockAction(true);
+        NavigationGestureAction swipeLeft = mockAction(true);
+        NavigationGestureAction swipeRight = mockAction(true);
+        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+
+        // In landscape
+        mController.setBarState(false /* isRTL */, NAV_BAR_RIGHT);
+
+        // Swipe Up
+        assertGestureTriggersAction(swipeRight, 1, 100, 5, 1);
+        // Swipe Down
+        assertGestureTriggersAction(swipeLeft, 1, 1, 5, 100);
+        // Swipe Left
+        assertGestureTriggersAction(swipeUp, 100, 1, 5, 1);
+        // Swipe Right
+        assertGestureTriggersAction(swipeDown, 1, 1, 100, 5);
+    }
+
+    @Test
+    public void testGesturesCallCorrectActionSeascape() throws Exception {
+        mController.setBarState(false /* isRTL */, NAV_BAR_LEFT);
+        NavigationGestureAction swipeUp = mockAction(true);
+        NavigationGestureAction swipeDown = mockAction(true);
+        NavigationGestureAction swipeLeft = mockAction(true);
+        NavigationGestureAction swipeRight = mockAction(true);
+        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+
+        // Swipe Up
+        assertGestureTriggersAction(swipeLeft, 1, 100, 5, 1);
+        // Swipe Down
+        assertGestureTriggersAction(swipeRight, 1, 1, 5, 100);
+        // Swipe Left
+        assertGestureTriggersAction(swipeDown, 100, 1, 5, 1);
+        // Swipe Right
+        assertGestureTriggersAction(swipeUp, 1, 1, 100, 5);
+    }
+
+    @Test
+    public void testGesturesCallCorrectActionRTL() throws Exception {
+        mController.setBarState(true /* isRTL */, NAV_BAR_BOTTOM);
+
+        // The swipe gestures below are for LTR, so RTL in portrait will be swapped
+        NavigationGestureAction swipeUp = mockAction(true);
+        NavigationGestureAction swipeDown = mockAction(true);
+        NavigationGestureAction swipeLeft = mockAction(true);
+        NavigationGestureAction swipeRight = mockAction(true);
+        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+
+        // Swipe Up in RTL
+        assertGestureTriggersAction(swipeUp, 1, 100, 5, 1);
+        // Swipe Down in RTL
+        assertGestureTriggersAction(swipeDown, 1, 1, 5, 100);
+        // Swipe Left in RTL
+        assertGestureTriggersAction(swipeRight, 100, 1, 5, 1);
+        // Swipe Right in RTL
+        assertGestureTriggersAction(swipeLeft, 1, 1, 100, 5);
+    }
+
+    @Test
+    public void testGesturesCallCorrectActionLandscapeRTL() throws Exception {
+        mController.setBarState(true /* isRTL */, NAV_BAR_RIGHT);
+
+        // The swipe gestures below are for LTR, so RTL in landscape will be swapped
+        NavigationGestureAction swipeUp = mockAction(true);
+        NavigationGestureAction swipeDown = mockAction(true);
+        NavigationGestureAction swipeLeft = mockAction(true);
+        NavigationGestureAction swipeRight = mockAction(true);
+        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+
+        // Swipe Up
+        assertGestureTriggersAction(swipeLeft, 1, 100, 5, 1);
+        // Swipe Down
+        assertGestureTriggersAction(swipeRight, 1, 1, 5, 100);
+        // Swipe Left
+        assertGestureTriggersAction(swipeUp, 100, 1, 5, 1);
+        // Swipe Right
+        assertGestureTriggersAction(swipeDown, 1, 1, 100, 5);
+    }
+
+    @Test
+    public void testGesturesCallCorrectActionSeascapeRTL() throws Exception {
+        mController.setBarState(true /* isRTL */, NAV_BAR_LEFT);
+
+        // The swipe gestures below are for LTR, so RTL in seascape will be swapped
+        NavigationGestureAction swipeUp = mockAction(true);
+        NavigationGestureAction swipeDown = mockAction(true);
+        NavigationGestureAction swipeLeft = mockAction(true);
+        NavigationGestureAction swipeRight = mockAction(true);
+        mController.setGestureActions(swipeUp, swipeDown, swipeLeft, swipeRight);
+
+        // Swipe Up
+        assertGestureTriggersAction(swipeRight, 1, 100, 5, 1);
+        // Swipe Down
+        assertGestureTriggersAction(swipeLeft, 1, 1, 5, 100);
+        // Swipe Left
+        assertGestureTriggersAction(swipeDown, 100, 1, 5, 1);
+        // Swipe Right
+        assertGestureTriggersAction(swipeUp, 1, 1, 100, 5);
+    }
+
+    @Test
+    public void testActionPreventByPinnedState() throws Exception {
+        // Screen is pinned
+        doReturn(true).when(mNavigationBarView).inScreenPinning();
+
+        // Add enabled gesture action
+        NavigationGestureAction action = mockAction(true);
+        mController.setGestureActions(action, null /* swipeDownAction */,
+                null /* swipeLeftAction */, null /* swipeRightAction */);
+
+        // Touch down to begin swipe
+        MotionEvent downEvent = event(MotionEvent.ACTION_DOWN, 1, 100);
+        assertFalse(touch(downEvent));
+        verify(mProxy, never()).onPreMotionEvent(mNavigationBarView.getDownHitTarget());
+        verify(mProxy, never()).onMotionEvent(downEvent);
+
+        // Move to start gesture, but pinned so it should not trigger action
+        MotionEvent moveEvent = event(MotionEvent.ACTION_MOVE, 1, 1);
+        assertFalse(touch(moveEvent));
+        assertNull(mController.getCurrentAction());
+        verify(mNavigationBarView, times(1)).showPinningEscapeToast();
+        verify(action, never()).onGestureStart(moveEvent);
+    }
+
+    @Test
+    public void testActionPreventedNotificationsShown() throws Exception {
+        NavigationGestureAction action = mockAction(true);
+        doReturn(false).when(action).canRunWhenNotificationsShowing();
+        mController.setGestureActions(action, null /* swipeDownAction */,
+                null /* swipeLeftAction */, null /* swipeRightAction */);
+
+        // Show the notifications
+        doReturn(false).when(mNavigationBarView).isNotificationsFullyCollapsed();
+
+        // Swipe up
+        assertFalse(touch(MotionEvent.ACTION_DOWN, 1, 100));
+        assertFalse(touch(MotionEvent.ACTION_MOVE, 1, 1));
+        assertNull(mController.getCurrentAction());
+        assertFalse(touch(MotionEvent.ACTION_UP, 1, 1));
+
+        // Hide the notifications
+        doReturn(true).when(mNavigationBarView).isNotificationsFullyCollapsed();
+
+        // Swipe up
+        assertFalse(touch(MotionEvent.ACTION_DOWN, 1, 100));
+        assertTrue(touch(MotionEvent.ACTION_MOVE, 1, 1));
+        assertEquals(action, mController.getCurrentAction());
+        assertFalse(touch(MotionEvent.ACTION_UP, 1, 1));
+    }
+
+    @Test
+    public void testActionCannotPerform() throws Exception {
+        NavigationGestureAction action = mockAction(true);
+        mController.setGestureActions(action, null /* swipeDownAction */,
+                null /* swipeLeftAction */, null /* swipeRightAction */);
+
+        // Cannot perform action
+        doReturn(false).when(action).canPerformAction();
+
+        // Swipe up
+        assertFalse(touch(MotionEvent.ACTION_DOWN, 1, 100));
+        assertFalse(touch(MotionEvent.ACTION_MOVE, 1, 1));
+        assertNull(mController.getCurrentAction());
+        assertFalse(touch(MotionEvent.ACTION_UP, 1, 1));
+
+        // Cannot perform action
+        doReturn(true).when(action).canPerformAction();
+
+        // Swipe up
+        assertFalse(touch(MotionEvent.ACTION_DOWN, 1, 100));
+        assertTrue(touch(MotionEvent.ACTION_MOVE, 1, 1));
+        assertEquals(action, mController.getCurrentAction());
+        assertFalse(touch(MotionEvent.ACTION_UP, 1, 1));
+    }
+
+    @Test
+    public void testQuickScrub() throws Exception {
+        QuickScrubAction action = spy(new QuickScrubAction(mNavigationBarView, mProxyService));
+        mController.setGestureActions(null /* swipeUpAction */, null /* swipeDownAction */,
+                null /* swipeLeftAction */, action);
+        int y = 20;
+
+        // Set the layout and other padding to make sure the scrub fraction is calculated correctly
+        action.onLayout(true, 0, 0, 400, 100);
+        doReturn(0).when(mNavigationBarView).getPaddingLeft();
+        doReturn(0).when(mNavigationBarView).getPaddingRight();
+        doReturn(0).when(mNavigationBarView).getPaddingStart();
+        doReturn(0).when(mResources)
+                .getDimensionPixelSize(R.dimen.nav_quick_scrub_track_edge_padding);
+
+        // Quickscrub disabled, so the action should be disabled
+        doReturn(false).when(mNavigationBarView).isQuickScrubEnabled();
+        assertFalse(action.isEnabled());
+        doReturn(true).when(mNavigationBarView).isQuickScrubEnabled();
+
+        // Touch down
+        MotionEvent downEvent = event(MotionEvent.ACTION_DOWN, 0, y);
+        assertFalse(touch(downEvent));
+        assertNull(mController.getCurrentAction());
+        verify(mProxy, times(1)).onPreMotionEvent(mNavigationBarView.getDownHitTarget());
+        verify(mProxy, times(1)).onMotionEvent(downEvent);
+
+        // Move to start trigger action from gesture
+        MotionEvent moveEvent1 = event(MotionEvent.ACTION_MOVE, 100, y);
+        assertTrue(touch(moveEvent1));
+        assertEquals(action, mController.getCurrentAction());
+        verify(action, times(1)).onGestureStart(moveEvent1);
+        verify(mProxy, times(1)).onQuickScrubStart();
+        verify(mProxyService, times(1)).notifyQuickScrubStarted();
+        verify(mNavigationBarView, times(1)).updateSlippery();
+
+        // Move again for scrub
+        MotionEvent moveEvent2 = event(MotionEvent.ACTION_MOVE, 200, y);
+        assertTrue(touch(moveEvent2));
+        assertEquals(action, mController.getCurrentAction());
+        verify(action, times(1)).onGestureMove(200, y);
+        verify(mProxy, times(1)).onQuickScrubProgress(1f / 2);
+
+        // Action up
+        MotionEvent upEvent = event(MotionEvent.ACTION_UP, 1, y);
+        assertFalse(touch(upEvent));
+        assertNull(mController.getCurrentAction());
+        verify(action, times(1)).onGestureEnd();
+        verify(mProxy, times(1)).onQuickScrubEnd();
+    }
+
+    @Test
+    public void testQuickStep() throws Exception {
+        QuickStepAction action = new QuickStepAction(mNavigationBarView, mProxyService);
+        mController.setGestureActions(action, null /* swipeDownAction */,
+                null /* swipeLeftAction */, null /* swipeRightAction */);
+
+        // Notifications are up, should prevent quickstep
+        doReturn(false).when(mNavigationBarView).isNotificationsFullyCollapsed();
+
+        // Swipe up
+        assertFalse(touch(MotionEvent.ACTION_DOWN, 1, 100));
+        assertNull(mController.getCurrentAction());
+        assertFalse(touch(MotionEvent.ACTION_MOVE, 1, 1));
+        assertNull(mController.getCurrentAction());
+        assertFalse(touch(MotionEvent.ACTION_UP, 1, 1));
+        doReturn(true).when(mNavigationBarView).isNotificationsFullyCollapsed();
+
+        // Quickstep disabled, so the action should be disabled
+        doReturn(false).when(mNavigationBarView).isQuickStepSwipeUpEnabled();
+        assertFalse(action.isEnabled());
+        doReturn(true).when(mNavigationBarView).isQuickStepSwipeUpEnabled();
+
+        // Swipe up should call proxy events
+        MotionEvent downEvent = event(MotionEvent.ACTION_DOWN, 1, 100);
+        assertFalse(touch(downEvent));
+        assertNull(mController.getCurrentAction());
+        verify(mProxy, times(1)).onPreMotionEvent(mNavigationBarView.getDownHitTarget());
+        verify(mProxy, times(1)).onMotionEvent(downEvent);
+
+        MotionEvent moveEvent = event(MotionEvent.ACTION_MOVE, 1, 1);
+        assertTrue(touch(moveEvent));
+        assertEquals(action, mController.getCurrentAction());
+        verify(mProxy, times(1)).onQuickStep(moveEvent);
+        verify(mProxyService, times(1)).notifyQuickStepStarted();
+    }
+
+    @Test
+    public void testLongPressPreventDetection() throws Exception {
+        NavigationGestureAction action = mockAction(true);
+        mController.setGestureActions(action, null /* swipeDownAction */,
+                null /* swipeLeftAction */, null /* swipeRightAction */);
+
+        // Start the drag up
+        assertFalse(touch(MotionEvent.ACTION_DOWN, 100, 1));
+        assertNull(mController.getCurrentAction());
+
+        // Long press something on the navigation bar such as Home button
+        mNavigationBarView.onNavigationButtonLongPress(mock(View.class));
+
+        // Swipe right will not start any gestures
+        MotionEvent motionMoveEvent = event(MotionEvent.ACTION_MOVE, 1, 1);
+        assertFalse(touch(motionMoveEvent));
+        assertNull(mController.getCurrentAction());
+        verify(action, never()).startGesture(motionMoveEvent);
+
+        // Touch up
+        assertFalse(touch(MotionEvent.ACTION_UP, 1, 1));
+        verify(action, never()).endGesture();
+    }
+
+    @Test
+    public void testHitTargetDragged() throws Exception {
+        final int navbarWidth = 1000;
+        final int navbarHeight = 1000;
+        ButtonDispatcher button = mock(ButtonDispatcher.class);
+        FakeLocationView buttonView = spy(new FakeLocationView(mContext, navbarWidth / 2,
+                navbarHeight / 2));
+        doReturn(buttonView).when(button).getCurrentView();
+
+        NavigationGestureAction action = mockAction(true);
+        mController.setGestureActions(action, action, action, action);
+
+        // Setup getting the hit target
+        doReturn(HIT_TARGET_HOME).when(action).requiresTouchDownHitTarget();
+        doReturn(true).when(action).requiresDragWithHitTarget();
+        doReturn(HIT_TARGET_HOME).when(mNavigationBarView).getDownHitTarget();
+        doReturn(button).when(mNavigationBarView).getHomeButton();
+        doReturn(navbarWidth).when(mNavigationBarView).getWidth();
+        doReturn(navbarHeight).when(mNavigationBarView).getHeight();
+
+        // Portrait
+        assertGestureDragsHitTargetAllDirections(buttonView, false /* isRTL */, NAV_BAR_BOTTOM);
+
+        // Portrait RTL
+        assertGestureDragsHitTargetAllDirections(buttonView, true /* isRTL */, NAV_BAR_BOTTOM);
+
+        // Landscape
+        assertGestureDragsHitTargetAllDirections(buttonView, false /* isRTL */, NAV_BAR_RIGHT);
+
+        // Landscape RTL
+        assertGestureDragsHitTargetAllDirections(buttonView, true /* isRTL */, NAV_BAR_RIGHT);
+
+        // Seascape
+        assertGestureDragsHitTargetAllDirections(buttonView, false /* isRTL */, NAV_BAR_LEFT);
+
+        // Seascape RTL
+        assertGestureDragsHitTargetAllDirections(buttonView, true /* isRTL */, NAV_BAR_LEFT);
+    }
+
+    private void assertGestureDragsHitTargetAllDirections(View buttonView, boolean isRTL,
+            int navPos) {
+        mController.setBarState(isRTL, navPos);
+
+        // Swipe up
+        assertGestureDragsHitTarget(buttonView, 10 /* x1 */, 200 /* y1 */, 0 /* x2 */, 0 /* y2 */,
+                0 /* dx */, -1 /* dy */);
+        // Swipe left
+        assertGestureDragsHitTarget(buttonView, 200 /* x1 */, 10 /* y1 */, 0 /* x2 */, 0 /* y2 */,
+                -1 /* dx */, 0 /* dy */);
+        // Swipe right
+        assertGestureDragsHitTarget(buttonView, 0 /* x1 */, 0 /* y1 */, 200 /* x2 */, 10 /* y2 */,
+                1 /* dx */, 0 /* dy */);
+        // Swipe down
+        assertGestureDragsHitTarget(buttonView, 0 /* x1 */, 0 /* y1 */, 10 /* x2 */, 200 /* y2 */,
+                0 /* dx */, 1 /* dy */);
+    }
+
+    /**
+     * Asserts the gesture actually moves the hit target
+     * @param buttonView button to check if moved, use Mockito.spy on a real object
+     * @param x1 start x
+     * @param x2 start y
+     * @param y1 end x
+     * @param y2 end y
+     * @param dx diff in x, if not 0, its sign determines direction, value does not matter
+     * @param dy diff in y, if not 0, its sign determines direction, value does not matter
+     */
+    private void assertGestureDragsHitTarget(View buttonView, int x1, int y1, int x2, int y2,
+            int dx, int dy) {
+        ArgumentCaptor<Float> captor = ArgumentCaptor.forClass(Float.class);
+        assertFalse(touch(MotionEvent.ACTION_DOWN, x1, y1));
+        assertTrue(touch(MotionEvent.ACTION_MOVE, x2, y2));
+
+        // Verify positions of the button drag
+        if (dx == 0) {
+            verify(buttonView, never()).setTranslationX(anyFloat());
+        } else {
+            verify(buttonView).setTranslationX(captor.capture());
+            if (dx < 0) {
+                assertTrue("Button should have moved left", (float) captor.getValue() < 0);
+            } else {
+                assertTrue("Button should have moved right", (float) captor.getValue() > 0);
+            }
+        }
+        if (dy == 0) {
+            verify(buttonView, never()).setTranslationY(anyFloat());
+        } else {
+            verify(buttonView).setTranslationY(captor.capture());
+            if (dy < 0) {
+                assertTrue("Button should have moved up", (float) captor.getValue() < 0);
+            } else {
+                assertTrue("Button should have moved down", (float) captor.getValue() > 0);
+            }
+        }
+
+        // Touch up
+        assertFalse(touch(MotionEvent.ACTION_UP, x2, y2));
+        verify(buttonView, times(1)).animate();
+
+        // Reset button state
+        reset(buttonView);
+    }
+
+
+    private MotionEvent event(int action, float x, float y) {
+        final MotionEvent event = mock(MotionEvent.class);
+        doReturn(x).when(event).getX();
+        doReturn(y).when(event).getY();
+        doReturn(action & MotionEvent.ACTION_MASK).when(event).getActionMasked();
+        doReturn(action).when(event).getAction();
+        return event;
+    }
+
+    private boolean touch(int action, float x, float y) {
+        return touch(event(action, x, y));
+    }
+
+    private boolean touch(MotionEvent event) {
+        return mController.onInterceptTouchEvent(event);
+    }
+
+    private NavigationGestureAction mockAction(boolean enabled) {
+        final NavigationGestureAction action = mock(NavigationGestureAction.class);
+        doReturn(enabled).when(action).isEnabled();
+        doReturn(HIT_TARGET_NONE).when(action).requiresTouchDownHitTarget();
+        doReturn(true).when(action).canPerformAction();
+        return action;
+    }
+
+    private void assertGestureTriggersAction(NavigationGestureAction action, int x1, int y1,
+            int x2, int y2) {
+        // Start the drag
+        assertFalse(touch(MotionEvent.ACTION_DOWN, x1, y1));
+        assertNull(mController.getCurrentAction());
+
+        // Swipe
+        MotionEvent motionMoveEvent = event(MotionEvent.ACTION_MOVE, x2, y2);
+        assertTrue(touch(motionMoveEvent));
+        assertEquals(action, mController.getCurrentAction());
+        verify(action, times(1)).startGesture(motionMoveEvent);
+
+        // Move again
+        assertTrue(touch(MotionEvent.ACTION_MOVE, x2, y2));
+        verify(action, times(1)).onGestureMove(x2, y2);
+
+        // Touch up
+        assertFalse(touch(MotionEvent.ACTION_UP, x2, y2));
+        assertNull(mController.getCurrentAction());
+        verify(action, times(1)).endGesture();
+    }
+
+    static class FakeLocationView extends View {
+        private final int mX;
+        private final int mY;
+
+        public FakeLocationView(Context context, int x, int y) {
+            super(context);
+            mX = x;
+            mY = y;
+        }
+
+        @Override
+        public void getLocationInWindow(int[] outLocation) {
+            outLocation[0] = mX;
+            outLocation[1] = mY;
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 882f261..d442de2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -593,6 +593,30 @@
         verify(mStatusBarStateController).setState(eq(StatusBarState.FULLSCREEN_USER_SWITCHER));
     }
 
+    @Test
+    public void testStartStopDozing() {
+        mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
+        when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
+
+        mStatusBar.mDozeServiceHost.startDozing();
+        verify(mStatusBarStateController).setIsDozing(eq(true));
+
+        mStatusBar.mDozeServiceHost.stopDozing();
+        verify(mStatusBarStateController).setIsDozing(eq(false));
+    }
+
+    @Test
+    public void testOnStartedWakingUp_isNotDozing() {
+        mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
+        when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
+
+        mStatusBar.mDozeServiceHost.startDozing();
+        verify(mStatusBarStateController).setIsDozing(eq(true));
+
+        mStatusBar.mWakefulnessObserver.onStartedWakingUp();
+        verify(mStatusBarStateController).setIsDozing(eq(false));
+    }
+
     static class TestableStatusBar extends StatusBar {
         public TestableStatusBar(StatusBarKeyguardViewManager man,
                 UnlockMethodCache unlock, KeyguardIndicationController key,
@@ -642,6 +666,7 @@
             mLockscreenUserManager = notificationLockscreenUserManager;
             mCommandQueue = commandQueue;
             mPresenter = notificationPresenter;
+            mGestureWakeLock = mock(PowerManager.WakeLock.class);
         }
 
         private WakefulnessLifecycle createAwakeWakefulnessLifecycle() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index c536dca..5f02fad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -27,18 +27,23 @@
 
 import static junit.framework.Assert.assertTrue;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.KeyguardManager;
 import android.media.AudioManager;
+import android.os.SystemClock;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.text.TextUtils;
+import android.view.InputDevice;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.ImageView;
 
 import com.android.systemui.R;
@@ -48,10 +53,11 @@
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.util.function.Predicate;
@@ -59,7 +65,6 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
-@Ignore
 public class VolumeDialogImplTest extends SysuiTestCase {
 
     VolumeDialogImpl mDialog;
@@ -113,6 +118,45 @@
                     + " failed test", condition.test(view));
         }
     }
+
+    @Test
+    public void testComputeTimeout() {
+        Mockito.reset(mAccessibilityMgr);
+        mDialog.rescheduleTimeoutH();
+        verify(mAccessibilityMgr).getRecommendedTimeoutMillis(
+                VolumeDialogImpl.DIALOG_TIMEOUT_MILLIS,
+                AccessibilityManager.FLAG_CONTENT_CONTROLS);
+    }
+
+    @Test
+    public void testComputeTimeout_withHovering() {
+        Mockito.reset(mAccessibilityMgr);
+        View dialog = mDialog.getDialogView();
+        long uptimeMillis = SystemClock.uptimeMillis();
+        MotionEvent event = MotionEvent.obtain(uptimeMillis, uptimeMillis,
+                MotionEvent.ACTION_HOVER_ENTER, 0, 0, 0);
+        event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+        dialog.dispatchGenericMotionEvent(event);
+        event.recycle();
+        verify(mAccessibilityMgr).getRecommendedTimeoutMillis(
+                VolumeDialogImpl.DIALOG_HOVERING_TIMEOUT_MILLIS,
+                AccessibilityManager.FLAG_CONTENT_CONTROLS);
+    }
+
+    @Test
+    public void testComputeTimeout_withSafetyWarningOn() {
+        Mockito.reset(mAccessibilityMgr);
+        ArgumentCaptor<VolumeDialogController.Callbacks> controllerCallbackCapture =
+                ArgumentCaptor.forClass(VolumeDialogController.Callbacks.class);
+        verify(mController).addCallback(controllerCallbackCapture.capture(), any());
+        VolumeDialogController.Callbacks callbacks = controllerCallbackCapture.getValue();
+        callbacks.onShowSafetyWarning(AudioManager.FLAG_SHOW_UI);
+        verify(mAccessibilityMgr).getRecommendedTimeoutMillis(
+                VolumeDialogImpl.DIALOG_SAFETYWARNING_TIMEOUT_MILLIS,
+                AccessibilityManager.FLAG_CONTENT_TEXT
+                        | AccessibilityManager.FLAG_CONTENT_CONTROLS);
+    }
+
 /*
     @Test
     public void testContentDescriptions() {
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-as/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-as/strings.xml
new file mode 100644
index 0000000..2e4d729
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-as/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="7290469683147348228">"ওপঙি থকা নেভিগে’শ্বন বাৰ সম্পৰীক্ষা"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-bn/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-bn/strings.xml
new file mode 100644
index 0000000..dc4994f
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-bn/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="7290469683147348228">"ফ্লোটিং নেভিগেশন বার সম্পর্কিত পরীক্ষা"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-gu/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-gu/strings.xml
new file mode 100644
index 0000000..10ca61d
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-gu/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="7290469683147348228">"ફ્લોટિંગ નૅવિગેશન બારનો પ્રયોગ"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-kn/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-kn/strings.xml
new file mode 100644
index 0000000..b3949d2
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-kn/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="7290469683147348228">"ಫ್ಲೋಟಿಂಗ್ ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್ ಪ್ರಯೋಗ"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ky/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ky/strings.xml
index bfd96da..51613ee 100644
--- a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ky/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ky/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="7290469683147348228">"Калкыма чабыттоо тилкесин колдонуу"</string>
+    <string name="experiment_navigationbar_overlay" msgid="7290469683147348228">"Калкыма чабыттоо тилкесин сыноо"</string>
 </resources>
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ml/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ml/strings.xml
new file mode 100644
index 0000000..f3bfaa2
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ml/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="7290469683147348228">"ഫ്ലോട്ടിംഗ് നാവിഗേഷൻ ബാർ പരീക്ഷണം"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ne/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ne/strings.xml
new file mode 100644
index 0000000..e9a5654
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ne/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="7290469683147348228">"उत्रिएको नेभिगेसन पट्टीको परीक्षण"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-or/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-or/strings.xml
new file mode 100644
index 0000000..1de802b
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-or/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="7290469683147348228">"ଭାସମାନ ନାଭିଗେସନ୍‍ ବାର୍‍‍‍‍‍ର ପ୍ରୟୋଗ"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-pa/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-pa/strings.xml
new file mode 100644
index 0000000..6d0970a
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-pa/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="7290469683147348228">"ਫਲੋਟਿੰਗ ਦਿਸ਼ਾ-ਨਿਰਦੇਸ਼ ਪੱਟੀ ਪ੍ਰਯੋਗ"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-si/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-si/strings.xml
new file mode 100644
index 0000000..48eedd1
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-si/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="7290469683147348228">"පාවෙන සංචාලන තීරු අත්දැකීම"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ta/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ta/strings.xml
new file mode 100644
index 0000000..5c870cd
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-ta/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="7290469683147348228">"மிதக்கும் வழிசெலுத்துதல் பட்டி சோதனை"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-te/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-te/strings.xml
new file mode 100644
index 0000000..3478e10
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values-te/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="7290469683147348228">"కదిలే నావిగేషన్ పట్టీ ప్రయోగం"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-as/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-as/strings.xml
new file mode 100644
index 0000000..8cce570
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-as/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="6953777362606036161">"লাহী নেভিগে’শ্বন বাৰ সম্পৰীক্ষা"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-bn/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-bn/strings.xml
new file mode 100644
index 0000000..c0ab3b1
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-bn/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="6953777362606036161">"স্লিম নেভিগেশন বার সম্পর্কিত পরীক্ষা"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-gu/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-gu/strings.xml
new file mode 100644
index 0000000..96418ae
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-gu/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="6953777362606036161">"સ્લિમ નૅવિગેશન બારનો પ્રયોગ"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-kn/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-kn/strings.xml
new file mode 100644
index 0000000..ccdddea
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-kn/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="6953777362606036161">"ಸ್ಲಿಮ್ ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್ ಪ್ರಯೋಗ"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ky/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ky/strings.xml
index 6b15d51..449de4f 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ky/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ky/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Жука чабыттоо тилкесин колдонуу"</string>
+    <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"Чакан чабыттоо тилкесин сыноо"</string>
 </resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ml/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ml/strings.xml
new file mode 100644
index 0000000..b65afe3
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ml/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="6953777362606036161">"സ്ലിം നാവിഗേഷൻ ബാർ പരീക്ഷണം"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ne/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ne/strings.xml
new file mode 100644
index 0000000..6022b7f
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ne/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="6953777362606036161">"पातलो नेभिगेसन पट्टीको परीक्षण"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-or/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-or/strings.xml
new file mode 100644
index 0000000..1db9783
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-or/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="6953777362606036161">"ସ୍ଲିମ୍‍ ନାଭିଗେସନ୍‍ ବାର୍‍‍‍‍‍ର ପ୍ରୟୋଗ"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pa/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pa/strings.xml
new file mode 100644
index 0000000..a782f46
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pa/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="6953777362606036161">"ਸਲਿਮ ਦਿਸ਼ਾ-ਨਿਰਦੇਸ਼ ਪੱਟੀ ਪ੍ਰਯੋਗ"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-si/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-si/strings.xml
new file mode 100644
index 0000000..a1abb64
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-si/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="6953777362606036161">"සිහින් සංචාලන තීරු අත්දැකීම"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ta/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ta/strings.xml
new file mode 100644
index 0000000..9e95c38
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ta/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="6953777362606036161">"மெலிதான வழிசெலுத்துதல் பட்டி சோதனை"</string>
+</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-te/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-te/strings.xml
new file mode 100644
index 0000000..d273ab7
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-te/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+/**
+ * Copyright (c) 2018, 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="experiment_navigationbar_overlay" msgid="6953777362606036161">"సన్నని నావిగేషన్ పట్టీ ప్రయోగం"</string>
+</resources>
diff --git a/packages/services/PacProcessor/Android.mk b/packages/services/PacProcessor/Android.mk
index 75d0363..295b3d8b 100644
--- a/packages/services/PacProcessor/Android.mk
+++ b/packages/services/PacProcessor/Android.mk
@@ -29,5 +29,3 @@
 LOCAL_JNI_SHARED_LIBRARIES := libjni_pacprocessor libpac
 
 include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/services/PacProcessor/jni/Android.bp b/packages/services/PacProcessor/jni/Android.bp
new file mode 100644
index 0000000..2a94237
--- /dev/null
+++ b/packages/services/PacProcessor/jni/Android.bp
@@ -0,0 +1,40 @@
+//
+// 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.
+//
+
+cc_library_shared {
+    name: "libjni_pacprocessor",
+
+    srcs: [
+        "jni_init.cpp",
+        "com_android_pacprocessor_PacNative.cpp",
+    ],
+
+    shared_libs: [
+        "libandroidfw",
+        "libandroid_runtime",
+        "liblog",
+        "libutils",
+        "libnativehelper",
+        "libpac",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+}
diff --git a/packages/services/PacProcessor/jni/Android.mk b/packages/services/PacProcessor/jni/Android.mk
deleted file mode 100644
index 254cbc2..0000000
--- a/packages/services/PacProcessor/jni/Android.mk
+++ /dev/null
@@ -1,41 +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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    jni_init.cpp \
-    com_android_pacprocessor_PacNative.cpp
-
-LOCAL_C_INCLUDES += \
-    external/chromium-libpac/src
-
-LOCAL_SHARED_LIBRARIES := \
-    libandroidfw \
-    libandroid_runtime \
-    liblog \
-    libutils \
-    libnativehelper \
-    libpac
-
-LOCAL_MODULE := libjni_pacprocessor
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index ddd0c2c..3e07d12 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -844,6 +844,8 @@
     //   PACKAGE: App that posted the notification
     // DETAIL: Notification is expanded by user.
     //   PACKAGE: App that posted the notification
+    // COLLAPSE: Notification is collapsed by user.
+    //   PACKAGE: App that posted the notification
     // DISMISS: Notification is dismissed.
     //   PACKAGE: App that posted the notification
     //   SUBTYPE: Dismiss reason from NotificationManagerService.java
@@ -2832,7 +2834,7 @@
     // ACTION: Logs the end to end time taken by all provisioning tasks.
     PROVISIONING_TOTAL_TASK_TIME_MS = 627;
 
-    // OPEN: Settings > Privacy
+    // OPEN: Settings > Security
     // CATEGORY: SETTINGS
     // OS: O
     ENTERPRISE_PRIVACY_SETTINGS = 628;
@@ -6579,6 +6581,29 @@
     // OS: Q
     BIOMETRIC_ENROLL_ACTIVITY = 1586;
 
+    // OPEN: Settings > Privacy
+    // CATEGORY: SETTINGS
+    // OS: Q
+    TOP_LEVEL_PRIVACY = 1587;
+
+    // OPEN: Settings > Sound & notification > Do Not Disturb > See all exceptions >
+    // Allow apps to override
+    // CATEGORY: SETTINGS
+    // OS: Q
+    NOTIFICATION_ZEN_MODE_OVERRIDING_APPS = 1588;
+
+    // OPEN: Settings > Sound & notification > Do Not Disturb > See all exceptions >
+    // Allow apps to override > Choose app
+    // CATEGORY: SETTINGS
+    // OS: Q
+    NOTIFICATION_ZEN_MODE_OVERRIDING_APP = 1589;
+
+    // ACTION: User sent a direct reply
+    //    PACKAGE: App that posted the notification
+    // CATEGORY: NOTIFICATION
+    // OS: Q
+    NOTIFICATION_DIRECT_REPLY_ACTION = 1590;
+
     // ---- End Q Constants, all Q constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/proto/src/task_snapshot.proto b/proto/src/task_snapshot.proto
index 65d6256..a1bbe52 100644
--- a/proto/src/task_snapshot.proto
+++ b/proto/src/task_snapshot.proto
@@ -31,4 +31,5 @@
      int32 windowing_mode = 7;
      int32 system_ui_visibility = 8;
      bool is_translucent = 9;
+     string top_activity_component = 10;
  }
\ No newline at end of file
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 033e996..11963d2 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -1674,4 +1674,20 @@
 
   // Total time the wifi radio is scanning in ms over the logging duration.
   optional int64 radio_scan_time_ms = 5;
+
+  // Total time the wifi radio spent doing nan scans in ms over the logging duration.
+  optional int64 radio_nan_scan_time_ms = 6;
+
+  // Total time the wifi radio spent doing background scans in ms over the logging duration.
+  optional int64 radio_background_scan_time_ms = 7;
+
+  // Total time the wifi radio spent doing roam scans in ms over the logging duration.
+  optional int64 radio_roam_scan_time_ms = 8;
+
+  // Total time the wifi radio spent doing pno scans in ms over the logging duration.
+  optional int64 radio_pno_scan_time_ms = 9;
+
+  // Total time the wifi radio spent doing hotspot 2.0 scans and GAS exchange
+  // in ms over the logging duration.
+  optional int64 radio_hs20_scan_time_ms = 10;
 }
\ No newline at end of file
diff --git a/services/Android.bp b/services/Android.bp
index bea51be..3390438 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -23,6 +23,7 @@
         "services.companion",
         "services.coverage",
         "services.devicepolicy",
+        "services.intelligence",
         "services.midi",
         "services.net",
         "services.print",
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index e89b951..5c189ce 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1672,22 +1672,23 @@
                 client -> client.setState(clientState)));
     }
 
-    private void scheduleNotifyClientsOfServicesStateChange(UserState userState) {
+    private void scheduleNotifyClientsOfServicesStateChangeLocked(UserState userState) {
+        updateRecommendedUiTimeoutLocked(userState);
         mMainHandler.sendMessage(obtainMessage(
                 AccessibilityManagerService::sendServicesStateChanged,
-                this, userState.mUserClients));
+                this, userState.mUserClients, getRecommendedTimeoutMillisLocked(userState)));
     }
 
     private void sendServicesStateChanged(
-            RemoteCallbackList<IAccessibilityManagerClient> userClients) {
-        notifyClientsOfServicesStateChange(mGlobalClients);
-        notifyClientsOfServicesStateChange(userClients);
+            RemoteCallbackList<IAccessibilityManagerClient> userClients, long uiTimeout) {
+        notifyClientsOfServicesStateChange(mGlobalClients, uiTimeout);
+        notifyClientsOfServicesStateChange(userClients, uiTimeout);
     }
 
     private void notifyClientsOfServicesStateChange(
-            RemoteCallbackList<IAccessibilityManagerClient> clients) {
+            RemoteCallbackList<IAccessibilityManagerClient> clients, long uiTimeout) {
         clients.broadcast(ignoreRemoteException(
-                client -> client.notifyServicesStateChanged()));
+                client -> client.notifyServicesStateChanged(uiTimeout)));
     }
 
     private void scheduleUpdateInputFilter(UserState userState) {
@@ -1701,24 +1702,6 @@
                 this, userState));
     }
 
-    private void scheduleSetAllClientsMinimumUiTimeout(UserState userState) {
-        mMainHandler.sendMessage(obtainMessage(
-                AccessibilityManagerService::sendMinimumUiTimeoutChanged,
-                this, userState.mUserClients, userState.mMinimumUiTimeout));
-    }
-
-    private void sendMinimumUiTimeoutChanged(
-            RemoteCallbackList<IAccessibilityManagerClient> userClients, int uiTimeout) {
-        notifyClientsOfServicesMinimumUiTimeoutChange(mGlobalClients, uiTimeout);
-        notifyClientsOfServicesMinimumUiTimeoutChange(userClients, uiTimeout);
-    }
-
-    private void notifyClientsOfServicesMinimumUiTimeoutChange(
-            RemoteCallbackList<IAccessibilityManagerClient> clients, int uiTimeout) {
-        clients.broadcast(ignoreRemoteException(
-                client -> client.setMinimumUiTimeout(uiTimeout)));
-    }
-
     private void updateInputFilter(UserState userState) {
         if (mUiAutomationManager.suppressingAccessibilityServicesLocked()) return;
 
@@ -1852,7 +1835,6 @@
         scheduleUpdateClientsIfNeededLocked(userState);
         updateRelevantEventsLocked(userState);
         updateAccessibilityButtonTargetsLocked(userState);
-        updateMinimumUiTimeoutLocked(userState);
     }
 
     private void updateAccessibilityFocusBehaviorLocked(UserState userState) {
@@ -1971,7 +1953,7 @@
         somethingChanged |= readAutoclickEnabledSettingLocked(userState);
         somethingChanged |= readAccessibilityShortcutSettingLocked(userState);
         somethingChanged |= readAccessibilityButtonSettingsLocked(userState);
-        somethingChanged |= readUserMinimumUiTimeoutSettingsLocked(userState);
+        somethingChanged |= readUserRecommendedUiTimeoutSettingsLocked(userState);
         return somethingChanged;
     }
 
@@ -2083,7 +2065,7 @@
         }
 
         userState.mServiceToEnableWithShortcut = componentNameToEnable;
-        scheduleNotifyClientsOfServicesStateChange(userState);
+        scheduleNotifyClientsOfServicesStateChangeLocked(userState);
         return true;
     }
 
@@ -2118,17 +2100,20 @@
         return true;
     }
 
-    private boolean readUserMinimumUiTimeoutSettingsLocked(UserState userState) {
-        final boolean enabled = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED, 0,
-                userState.mUserId) == 1;
-        final int timeout = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS, 0,
+    private boolean readUserRecommendedUiTimeoutSettingsLocked(UserState userState) {
+        final int nonInteractiveUiTimeout = Settings.Secure.getIntForUser(
+                mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, 0,
                 userState.mUserId);
-        if (enabled != userState.mUserMinimumUiTimeoutEnabled
-                || timeout != userState.mUserMinimumUiTimeout) {
-            userState.mUserMinimumUiTimeoutEnabled = enabled;
-            userState.mUserMinimumUiTimeout = timeout;
+        final int interactiveUiTimeout = Settings.Secure.getIntForUser(
+                mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, 0,
+                userState.mUserId);
+        if (nonInteractiveUiTimeout != userState.mUserNonInteractiveUiTimeout
+                || interactiveUiTimeout != userState.mUserInteractiveUiTimeout) {
+            userState.mUserNonInteractiveUiTimeout = nonInteractiveUiTimeout;
+            userState.mUserInteractiveUiTimeout = interactiveUiTimeout;
+            scheduleNotifyClientsOfServicesStateChangeLocked(userState);
             return true;
         }
         return false;
@@ -2300,25 +2285,33 @@
         }
     }
 
-    private void updateMinimumUiTimeoutLocked(UserState userState) {
-        int newUiTimeout = 0;
-        if (userState.mUserMinimumUiTimeoutEnabled) {
-            newUiTimeout = userState.mUserMinimumUiTimeout;
-        } else {
+    private void updateRecommendedUiTimeoutLocked(UserState userState) {
+        int newNonInteractiveUiTimeout = userState.mUserNonInteractiveUiTimeout;
+        int newInteractiveUiTimeout = userState.mUserInteractiveUiTimeout;
+        // read from a11y services if user does not specify value
+        if (newNonInteractiveUiTimeout == 0 || newInteractiveUiTimeout == 0) {
+            int serviceNonInteractiveUiTimeout = 0;
+            int serviceInteractiveUiTimeout = 0;
             final List<AccessibilityServiceConnection> services = userState.mBoundServices;
-            final int numServices = services.size();
-            for (int i = 0; i < numServices; i++) {
-                final int serviceUiTimeout = services.get(i).getServiceInfo()
-                        .getMinimumUiTimeoutMillis();
-                if (newUiTimeout < serviceUiTimeout) {
-                    newUiTimeout = serviceUiTimeout;
+            for (int i = 0; i < services.size(); i++) {
+                int timeout = services.get(i).getServiceInfo().getInteractiveUiTimeoutMillis();
+                if (serviceInteractiveUiTimeout < timeout) {
+                    serviceInteractiveUiTimeout = timeout;
+                }
+                timeout = services.get(i).getServiceInfo().getNonInteractiveUiTimeoutMillis();
+                if (serviceNonInteractiveUiTimeout < timeout) {
+                    serviceNonInteractiveUiTimeout = timeout;
                 }
             }
+            if (newNonInteractiveUiTimeout == 0) {
+                newNonInteractiveUiTimeout = serviceNonInteractiveUiTimeout;
+            }
+            if (newInteractiveUiTimeout == 0) {
+                newInteractiveUiTimeout = serviceInteractiveUiTimeout;
+            }
         }
-        if (newUiTimeout != userState.mMinimumUiTimeout) {
-            userState.mMinimumUiTimeout = newUiTimeout;
-            scheduleSetAllClientsMinimumUiTimeout(userState);
-        }
+        userState.mNonInteractiveUiTimeout = newNonInteractiveUiTimeout;
+        userState.mInteractiveUiTimeout = newInteractiveUiTimeout;
     }
 
     @GuardedBy("mLock")
@@ -2473,19 +2466,24 @@
     }
 
     /**
-     * Get the minimum timeout for changes to the UI needed by this user. Controls should remain
-     * on the screen for at least this long to give users time to react.
+     * Get the recommended timeout of interactive controls and non-interactive controls.
      *
-     * @return The minimum timeout for the current user in milliseconds.
+     * @return A long for pair of {@code int}s. First integer for interactive one, and second
+     * integer for non-interactive one.
      */
     @Override
-    public int getMinimumUiTimeout() {
+    public long getRecommendedTimeoutMillis() {
         synchronized(mLock) {
             final UserState userState = getCurrentUserStateLocked();
-            return userState.mMinimumUiTimeout;
+            return getRecommendedTimeoutMillisLocked(userState);
         }
     }
 
+    private long getRecommendedTimeoutMillisLocked(UserState userState) {
+        return IntPair.of(userState.mInteractiveUiTimeout,
+                userState.mNonInteractiveUiTimeout);
+    }
+
     @Override
     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
@@ -2503,7 +2501,8 @@
                 pw.append(", navBarMagnificationEnabled="
                         + userState.mIsNavBarMagnificationEnabled);
                 pw.append(", autoclickEnabled=" + userState.mIsAutoclickEnabled);
-                pw.append(", minimumUiTimeout=" + userState.mMinimumUiTimeout);
+                pw.append(", nonInteractiveUiTimeout=" + userState.mNonInteractiveUiTimeout);
+                pw.append(", interactiveUiTimeout=" + userState.mInteractiveUiTimeout);
                 if (mUiAutomationManager.isUiAutomationRunningLocked()) {
                     pw.append(", ");
                     mUiAutomationManager.dumpUiAutomationService(fd, pw, args);
@@ -2819,7 +2818,7 @@
         AccessibilityManagerService.UserState userState = getUserStateLocked(mCurrentUserId);
         onUserStateChangedLocked(userState);
         if (serviceInfoChanged) {
-            scheduleNotifyClientsOfServicesStateChange(userState);
+            scheduleNotifyClientsOfServicesStateChangeLocked(userState);
         }
     }
 
@@ -3794,7 +3793,8 @@
         public ComponentName mServiceToEnableWithShortcut;
 
         public int mLastSentClientState = -1;
-        public int mMinimumUiTimeout = 0;
+        public int mNonInteractiveUiTimeout = 0;
+        public int mInteractiveUiTimeout = 0;
 
         private int mSoftKeyboardShowMode = 0;
 
@@ -3809,8 +3809,8 @@
         public boolean mIsPerformGesturesEnabled;
         public boolean mIsFilterKeyEventsEnabled;
         public boolean mAccessibilityFocusOnlyInActiveWindow;
-        public boolean mUserMinimumUiTimeoutEnabled;
-        public int mUserMinimumUiTimeout;
+        public int mUserNonInteractiveUiTimeout;
+        public int mUserInteractiveUiTimeout;
 
         private boolean mBindInstantServiceAllowed;
 
@@ -3850,8 +3850,9 @@
             // Clear event management state.
             mLastSentClientState = -1;
 
-            // clear minimum ui timeout
-            mMinimumUiTimeout = 0;
+            // clear UI timeout
+            mNonInteractiveUiTimeout = 0;
+            mInteractiveUiTimeout = 0;
 
             // Clear state persisted in settings.
             mEnabledServices.clear();
@@ -3862,8 +3863,8 @@
             mServiceAssignedToAccessibilityButton = null;
             mIsNavBarMagnificationAssignedToAccessibilityButton = false;
             mIsAutoclickEnabled = false;
-            mUserMinimumUiTimeoutEnabled = false;
-            mUserMinimumUiTimeout = 0;
+            mUserNonInteractiveUiTimeout = 0;
+            mUserInteractiveUiTimeout = 0;
         }
 
         public void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
@@ -3871,7 +3872,7 @@
                 serviceConnection.onAdded();
                 mBoundServices.add(serviceConnection);
                 mComponentNameToServiceMap.put(serviceConnection.mComponentName, serviceConnection);
-                scheduleNotifyClientsOfServicesStateChange(this);
+                scheduleNotifyClientsOfServicesStateChangeLocked(this);
             }
         }
 
@@ -3897,7 +3898,7 @@
                 AccessibilityServiceConnection boundClient = mBoundServices.get(i);
                 mComponentNameToServiceMap.put(boundClient.mComponentName, boundClient);
             }
-            scheduleNotifyClientsOfServicesStateChange(this);
+            scheduleNotifyClientsOfServicesStateChangeLocked(this);
         }
 
         /**
@@ -4108,11 +4109,11 @@
         private final Uri mAccessibilityButtonComponentIdUri = Settings.Secure.getUriFor(
                 Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
 
-        private final Uri mUserMinimumUiTimeoutEnabledUri = Settings.Secure.getUriFor(
-                Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_ENABLED);
+        private final Uri mUserNonInteractiveUiTimeoutUri = Settings.Secure.getUriFor(
+                Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS);
 
-        private final Uri mUserMinimumUiTimeoutUri = Settings.Secure.getUriFor(
-                Settings.Secure.ACCESSIBILITY_MINIMUM_UI_TIMEOUT_MS);
+        private final Uri mUserInteractiveUiTimeoutUri = Settings.Secure.getUriFor(
+                Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS);
 
         public AccessibilityContentObserver(Handler handler) {
             super(handler);
@@ -4149,9 +4150,9 @@
             contentResolver.registerContentObserver(
                     mAccessibilityButtonComponentIdUri, false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(
-                    mUserMinimumUiTimeoutEnabledUri, false, this, UserHandle.USER_ALL);
+                    mUserNonInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(
-                    mUserMinimumUiTimeoutUri, false, this, UserHandle.USER_ALL);
+                    mUserInteractiveUiTimeoutUri, false, this, UserHandle.USER_ALL);
         }
 
         @Override
@@ -4202,11 +4203,9 @@
                     if (readAccessibilityButtonSettingsLocked(userState)) {
                         onUserStateChangedLocked(userState);
                     }
-                } else if (mUserMinimumUiTimeoutEnabledUri.equals(uri)
-                        || mUserMinimumUiTimeoutUri.equals(uri)) {
-                    if (readUserMinimumUiTimeoutSettingsLocked(userState)) {
-                        updateMinimumUiTimeoutLocked(userState);
-                    }
+                } else if (mUserNonInteractiveUiTimeoutUri.equals(uri)
+                        || mUserInteractiveUiTimeoutUri.equals(uri)) {
+                    readUserRecommendedUiTimeoutSettingsLocked(userState);
                 }
             }
         }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 4205ac7..31238df 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -166,12 +166,12 @@
         context.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler());
     }
 
-    @Override // from MasterSystemService
+    @Override // from AbstractMasterSystemService
     protected String getServiceSettingsProperty() {
         return Settings.Secure.AUTOFILL_SERVICE;
     }
 
-    @Override // from MasterSystemService
+    @Override // from AbstractMasterSystemService
     protected void registerForExtraSettingsChanges(@NonNull ContentResolver resolver,
             @NonNull ContentObserver observer) {
         resolver.registerContentObserver(Settings.Global.getUriFor(
@@ -188,7 +188,7 @@
                 UserHandle.USER_ALL);
     }
 
-    @Override // from MasterSystemService
+    @Override // from AbstractMasterSystemService
     protected void onSettingsChanged(int userId, @NonNull String property) {
         switch (property) {
             case Settings.Global.AUTOFILL_LOGGING_LEVEL:
@@ -210,25 +210,24 @@
         }
     }
 
-    @Override // from MasterSystemService
-    protected AutofillManagerServiceImpl newServiceLocked(int resolvedUserId, boolean disabled) {
+    @Override // from AbstractMasterSystemService
+    protected AutofillManagerServiceImpl newServiceLocked(@UserIdInt int resolvedUserId,
+            boolean disabled) {
         return new AutofillManagerServiceImpl(this, mLock, mRequestsHistory,
                 mUiLatencyHistory, mWtfHistory, resolvedUserId, mUi, mAutofillCompatState,
                 disabled);
     }
 
-    @Override // MasterSystemService
-    protected AutofillManagerServiceImpl removeCachedServiceLocked(int userId) {
-        final AutofillManagerServiceImpl service = super.removeCachedServiceLocked(userId);
-        if (service != null) {
-            service.destroyLocked();
-            mAutofillCompatState.removeCompatibilityModeRequests(userId);
-        }
-        return service;
+    @Override // AbstractMasterSystemService
+    protected void onServiceRemoved(@NonNull AutofillManagerServiceImpl service,
+            @UserIdInt int userId) {
+        service.destroyLocked();
+        mAutofillCompatState.removeCompatibilityModeRequests(userId);
     }
 
-    @Override // from MasterSystemService
-    protected void onServiceEnabledLocked(@NonNull AutofillManagerServiceImpl service, int userId) {
+    @Override // from AbstractMasterSystemService
+    protected void onServiceEnabledLocked(@NonNull AutofillManagerServiceImpl service,
+            @UserIdInt int userId) {
         addCompatibilityModeRequestsLocked(service, userId);
     }
 
@@ -245,7 +244,7 @@
     }
 
     // Called by Shell command.
-    void destroySessions(int userId, IResultReceiver receiver) {
+    void destroySessions(@UserIdInt int userId, IResultReceiver receiver) {
         Slog.i(TAG, "destroySessions() for userId " + userId);
         getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
 
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 09f915e..1ff1acd 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -281,18 +281,6 @@
                     return;
                 }
 
-                // Sanitize structure before it's sent to service.
-                final ComponentName componentNameFromApp = structure.getActivityComponent();
-                if (componentNameFromApp == null || !mComponentName.getPackageName()
-                        .equals(componentNameFromApp.getPackageName())) {
-                    Slog.w(TAG, "Activity " + mComponentName + " forged different component on "
-                            + "AssistStructure: " + componentNameFromApp);
-                    structure.setActivityComponent(mComponentName);
-                    mMetricsLogger.write(newLogMaker(MetricsEvent.AUTOFILL_FORGED_COMPONENT_ATTEMPT)
-                            .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FORGED_COMPONENT_NAME,
-                                    componentNameFromApp == null ? "null"
-                                            : componentNameFromApp.flattenToShortString()));
-                }
                 // Flags used to start the session.
                 int flags = structure.getFlags();
 
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index d1fe970c..7a65a53 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -218,8 +218,8 @@
             ViewGroup container = decor.findViewById(R.id.autofill_dataset_picker);
             final View content;
             try {
-                response.getPresentation().setApplyTheme(mThemeId);
-                content = response.getPresentation().apply(mContext, decor, interceptionHandler);
+                content = response.getPresentation().applyWithTheme(
+                        mContext, decor, interceptionHandler, mThemeId);
                 container.addView(content);
             } catch (RuntimeException e) {
                 callback.onCanceled();
@@ -259,8 +259,7 @@
             RemoteViews.OnClickHandler clickBlocker = null;
             if (headerPresentation != null) {
                 clickBlocker = newClickBlocker();
-                headerPresentation.setApplyTheme(mThemeId);
-                mHeader = headerPresentation.apply(mContext, null, clickBlocker);
+                mHeader = headerPresentation.applyWithTheme(mContext, null, clickBlocker, mThemeId);
                 final LinearLayout headerContainer =
                         decor.findViewById(R.id.autofill_dataset_header);
                 if (sVerbose) Slog.v(TAG, "adding header");
@@ -277,8 +276,8 @@
                     if (clickBlocker == null) { // already set for header
                         clickBlocker = newClickBlocker();
                     }
-                    footerPresentation.setApplyTheme(mThemeId);
-                    mFooter = footerPresentation.apply(mContext, null, clickBlocker);
+                    mFooter = footerPresentation.applyWithTheme(
+                            mContext, null, clickBlocker, mThemeId);
                     // Footer not supported on some platform e.g. TV
                     if (sVerbose) Slog.v(TAG, "adding footer");
                     footerContainer.addView(mFooter);
@@ -304,8 +303,8 @@
                     final View view;
                     try {
                         if (sVerbose) Slog.v(TAG, "setting remote view for " + focusedViewId);
-                        presentation.setApplyTheme(mThemeId);
-                        view = presentation.apply(mContext, null, interceptionHandler);
+                        view = presentation.applyWithTheme(
+                                mContext, null, interceptionHandler, mThemeId);
                     } catch (RuntimeException e) {
                         Slog.e(TAG, "Error inflating remote views", e);
                         continue;
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 1e30c8a..843aa74 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -339,8 +339,8 @@
 
         try {
             // Create the remote view peer.
-            template.setApplyTheme(mThemeId);
-            final View customSubtitleView = template.apply(context, null, handler);
+            final View customSubtitleView = template.applyWithTheme(
+                    context, null, handler, mThemeId);
 
             // Apply batch updates (if any).
             final ArrayList<Pair<InternalValidator, BatchUpdates>> updates =
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 1ad83ec..c12a5e7 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -104,7 +104,6 @@
 import com.android.server.backup.fullbackup.FullBackupEntry;
 import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
 import com.android.server.backup.internal.BackupHandler;
-import com.android.server.backup.keyvalue.BackupRequest;
 import com.android.server.backup.internal.ClearDataObserver;
 import com.android.server.backup.internal.OnTaskFinishedListener;
 import com.android.server.backup.internal.Operation;
@@ -112,6 +111,7 @@
 import com.android.server.backup.internal.ProvisionedObserver;
 import com.android.server.backup.internal.RunBackupReceiver;
 import com.android.server.backup.internal.RunInitializeReceiver;
+import com.android.server.backup.keyvalue.BackupRequest;
 import com.android.server.backup.params.AdbBackupParams;
 import com.android.server.backup.params.AdbParams;
 import com.android.server.backup.params.AdbRestoreParams;
@@ -160,7 +160,6 @@
 import java.util.concurrent.atomic.AtomicInteger;
 
 public class BackupManagerService {
-
     public static final String TAG = "BackupManagerService";
     public static final boolean DEBUG = true;
     public static final boolean MORE_DEBUG = false;
@@ -170,6 +169,9 @@
     // nonzero == enabled.  File missing or contains a zero byte == disabled.
     private static final String BACKUP_ENABLE_FILE = "backup_enabled";
 
+    // Persistently track the need to do a full init.
+    private static final String INIT_SENTINEL_FILE_NAME = "_need_init_";
+
     // System-private key used for backing up an app's widget state.  Must
     // begin with U+FFxx by convention (we reserve all keys starting
     // with U+FF00 or higher for system use).
@@ -196,11 +198,16 @@
     public static final int BACKUP_METADATA_VERSION = 1;
     public static final int BACKUP_WIDGET_METADATA_TOKEN = 0x01FFED01;
 
-    private static final boolean COMPRESS_FULL_BACKUPS = true; // should be true in production
+    private static final int CURRENT_ANCESTRAL_RECORD_VERSION = 1;
+
+    // Round-robin queue for scheduling full backup passes.
+    private static final int SCHEDULE_FILE_VERSION = 1;
 
     public static final String SETTINGS_PACKAGE = "com.android.providers.settings";
     public static final String SHARED_BACKUP_AGENT_PACKAGE = "com.android.sharedstoragebackup";
-    private static final String SERVICE_ACTION_TRANSPORT_HOST = "android.backup.TRANSPORT_HOST";
+
+    // Pseudoname that we use for the Package Manager metadata "package".
+    public static final String PACKAGE_MANAGER_SENTINEL = "@pm@";
 
     // Retry interval for clear/init when the transport is unavailable
     private static final long TRANSPORT_RETRY_INTERVAL = 1 * AlarmManager.INTERVAL_HOUR;
@@ -210,6 +217,21 @@
     public static final String BACKUP_FINISHED_ACTION = "android.intent.action.BACKUP_FINISHED";
     public static final String BACKUP_FINISHED_PACKAGE_EXTRA = "packageName";
 
+    // Bookkeeping of in-flight operations. The operation token is the index of the entry in the
+    // pending operations list.
+    public static final int OP_PENDING = 0;
+    private static final int OP_ACKNOWLEDGED = 1;
+    private static final int OP_TIMEOUT = -1;
+
+    // Waiting for backup agent to respond during backup operation.
+    public static final int OP_TYPE_BACKUP_WAIT = 0;
+
+    // Waiting for backup agent to respond during restore operation.
+    public static final int OP_TYPE_RESTORE_WAIT = 1;
+
+    // An entire backup operation spanning multiple packages.
+    public static final int OP_TYPE_BACKUP = 2;
+
     // Time delay for initialization operations that can be delayed so as not to consume too much CPU
     // on bring-up and increase time-to-UI.
     private static final long INITIALIZATION_DELAY_MILLIS = 3000;
@@ -226,8 +248,62 @@
     private static final long BUSY_BACKOFF_MIN_MILLIS = 1000 * 60 * 60;  // one hour
     private static final int BUSY_BACKOFF_FUZZ = 1000 * 60 * 60 * 2;  // two hours
 
-    private BackupManagerConstants mConstants;
+    // The published binder is a singleton Trampoline object that calls through to the proper code.
+    // This indirection lets us turn down the heavy implementation object on the fly without
+    // disturbing binders that have been cached elsewhere in the system.
+    private static Trampoline sInstance;
+
+    static Trampoline getInstance() {
+        // Always constructed during system bring up, so no need to lazy-init.
+        return sInstance;
+    }
+
+    /** Helper to create the {@link BackupManagerService} instance. */
+    public static BackupManagerService create(
+            Context context,
+            Trampoline parent,
+            HandlerThread backupThread) {
+        // Set up our transport options and initialize the default transport
+        SystemConfig systemConfig = SystemConfig.getInstance();
+        Set<ComponentName> transportWhitelist = systemConfig.getBackupTransportWhitelist();
+        if (transportWhitelist == null) {
+            transportWhitelist = Collections.emptySet();
+        }
+
+        String transport =
+                Settings.Secure.getString(
+                        context.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT);
+        if (TextUtils.isEmpty(transport)) {
+            transport = null;
+        }
+        if (DEBUG) {
+            Slog.v(TAG, "Starting with transport " + transport);
+        }
+        TransportManager transportManager =
+                new TransportManager(
+                        context,
+                        transportWhitelist,
+                        transport);
+
+        // If encrypted file systems is enabled or disabled, this call will return the
+        // correct directory.
+        File baseStateDir = new File(Environment.getDataDirectory(), "backup");
+
+        // This dir on /cache is managed directly in init.rc
+        File dataDir = new File(Environment.getDownloadCacheDirectory(), "backup_stage");
+
+        return new BackupManagerService(
+                context,
+                parent,
+                backupThread,
+                baseStateDir,
+                dataDir,
+                transportManager);
+    }
+
     private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
+    private final TransportManager mTransportManager;
+
     private Context mContext;
     private PackageManager mPackageManager;
     private IPackageManager mPackageManagerBinder;
@@ -235,20 +311,21 @@
     private PowerManager mPowerManager;
     private AlarmManager mAlarmManager;
     private IStorageManager mStorageManager;
+    private BackupManagerConstants mConstants;
+    private PowerManager.WakeLock mWakelock;
+    private BackupHandler mBackupHandler;
 
     private IBackupManager mBackupManagerBinder;
 
-    private final TransportManager mTransportManager;
-
     private boolean mEnabled;   // access to this is synchronized on 'this'
     private boolean mProvisioned;
     private boolean mAutoRestore;
-    private PowerManager.WakeLock mWakelock;
-    private BackupHandler mBackupHandler;
+
     private PendingIntent mRunBackupIntent;
     private PendingIntent mRunInitIntent;
-    private BroadcastReceiver mRunBackupReceiver;
-    private BroadcastReceiver mRunInitReceiver;
+
+    private final ArraySet<String> mPendingInits = new ArraySet<>();  // transport names
+
     // map UIDs to the set of participating packages under that UID
     private final SparseArray<HashSet<String>> mBackupParticipants
             = new SparseArray<>();
@@ -257,9 +334,6 @@
     private HashMap<String, BackupRequest> mPendingBackups
             = new HashMap<>();
 
-    // Pseudoname that we use for the Package Manager metadata "package"
-    public static final String PACKAGE_MANAGER_SENTINEL = "@pm@";
-
     // locking around the pending-backup management
     private final Object mQueueLock = new Object();
 
@@ -269,25 +343,32 @@
     // completed.
     private final Object mAgentConnectLock = new Object();
     private IBackupAgent mConnectedAgent;
-    private volatile boolean mBackupRunning;
     private volatile boolean mConnecting;
-    private volatile long mLastBackupPass;
 
-    // For debugging, we maintain a progress trace of operations during backup
-    public static final boolean DEBUG_BACKUP_TRACE = true;
-    private final List<String> mBackupTrace = new ArrayList<>();
+    private volatile boolean mBackupRunning;
+    private volatile long mLastBackupPass;
 
     // A similar synchronization mechanism around clearing apps' data for restore
     private final Object mClearDataLock = new Object();
     private volatile boolean mClearingData;
 
+    // Used by ADB.
     private final BackupPasswordManager mBackupPasswordManager;
+    private final SparseArray<AdbParams> mAdbBackupRestoreConfirmations = new SparseArray<>();
+    private final SecureRandom mRng = new SecureRandom();
 
     // Time when we post the transport registration operation
     private final long mRegisterTransportsRequestedTime;
 
+    @GuardedBy("mQueueLock")
+    private PerformFullTransportBackupTask mRunningFullBackupTask;
+
+    @GuardedBy("mQueueLock")
+    private ArrayList<FullBackupEntry> mFullBackupQueue;
+
     @GuardedBy("mPendingRestores")
     private boolean mIsRestoreInProgress;
+
     @GuardedBy("mPendingRestores")
     private final Queue<PerformUnifiedRestoreTask> mPendingRestores = new ArrayDeque<>();
 
@@ -296,17 +377,155 @@
     // Watch the device provisioning operation during setup
     private ContentObserver mProvisionedObserver;
 
-    // The published binder is actually to a singleton trampoline object that calls
-    // through to the proper code.  This indirection lets us turn down the heavy
-    // implementation object on the fly without disturbing binders that have been
-    // cached elsewhere in the system.
-    static Trampoline sInstance;
+    /**
+     * mCurrentOperations contains the list of currently active operations.
+     *
+     * If type of operation is OP_TYPE_WAIT, it are waiting for an ack or timeout.
+     * An operation wraps a BackupRestoreTask within it.
+     * It's the responsibility of this task to remove the operation from this array.
+     *
+     * A BackupRestore task gets notified of ack/timeout for the operation via
+     * BackupRestoreTask#handleCancel, BackupRestoreTask#operationComplete and notifyAll called
+     * on the mCurrentOpLock.
+     * {@link BackupManagerService#waitUntilOperationComplete(int)} is
+     * used in various places to 'wait' for notifyAll and detect change of pending state of an
+     * operation. So typically, an operation will be removed from this array by:
+     * - BackupRestoreTask#handleCancel and
+     * - BackupRestoreTask#operationComplete OR waitUntilOperationComplete. Do not remove at both
+     * these places because waitUntilOperationComplete relies on the operation being present to
+     * determine its completion status.
+     *
+     * If type of operation is OP_BACKUP, it is a task running backups. It provides a handle to
+     * cancel backup tasks.
+     */
+    @GuardedBy("mCurrentOpLock")
+    private final SparseArray<Operation> mCurrentOperations = new SparseArray<>();
+    private final Object mCurrentOpLock = new Object();
+    private final Random mTokenGenerator = new Random();
+    final AtomicInteger mNextToken = new AtomicInteger();
 
-    static Trampoline getInstance() {
-        // Always constructed during system bringup, so no need to lazy-init
-        return sInstance;
+    // Where we keep our journal files and other bookkeeping.
+    private File mBaseStateDir;
+    private File mDataDir;
+    private File mJournalDir;
+    @Nullable
+    private DataChangedJournal mJournal;
+    private File mFullBackupScheduleFile;
+
+    // Keep a log of all the apps we've ever backed up.
+    private ProcessedPackagesJournal mProcessedPackagesJournal;
+
+    private File mTokenFile;
+    private Set<String> mAncestralPackages = null;
+    private long mAncestralToken = 0;
+    private long mCurrentToken = 0;
+
+    @VisibleForTesting
+    public BackupManagerService(
+            Context context,
+            Trampoline parent,
+            HandlerThread backupThread,
+            File baseStateDir,
+            File dataDir,
+            TransportManager transportManager) {
+        mContext = context;
+        mPackageManager = context.getPackageManager();
+        mPackageManagerBinder = AppGlobals.getPackageManager();
+        mActivityManager = ActivityManager.getService();
+
+        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
+
+        mBackupManagerBinder = Trampoline.asInterface(parent.asBinder());
+
+        mAgentTimeoutParameters = new
+                BackupAgentTimeoutParameters(Handler.getMain(), mContext.getContentResolver());
+        mAgentTimeoutParameters.start();
+
+        // spin up the backup/restore handler thread
+        mBackupHandler = new BackupHandler(this, backupThread.getLooper());
+
+        // Set up our bookkeeping
+        final ContentResolver resolver = context.getContentResolver();
+        mProvisioned = Settings.Global.getInt(resolver,
+                Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+        mAutoRestore = Settings.Secure.getInt(resolver,
+                Settings.Secure.BACKUP_AUTO_RESTORE, 1) != 0;
+
+        mProvisionedObserver = new ProvisionedObserver(this, mBackupHandler);
+        resolver.registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
+                false, mProvisionedObserver);
+
+        mBaseStateDir = baseStateDir;
+        mBaseStateDir.mkdirs();
+        if (!SELinux.restorecon(mBaseStateDir)) {
+            Slog.e(TAG, "SELinux restorecon failed on " + mBaseStateDir);
+        }
+
+        mDataDir = dataDir;
+
+        mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng);
+
+        // Alarm receivers for scheduled backups & initialization operations
+        BroadcastReceiver mRunBackupReceiver = new RunBackupReceiver(this);
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(RUN_BACKUP_ACTION);
+        context.registerReceiver(mRunBackupReceiver, filter,
+                android.Manifest.permission.BACKUP, null);
+
+        BroadcastReceiver mRunInitReceiver = new RunInitializeReceiver(this);
+        filter = new IntentFilter();
+        filter.addAction(RUN_INITIALIZE_ACTION);
+        context.registerReceiver(mRunInitReceiver, filter,
+                android.Manifest.permission.BACKUP, null);
+
+        Intent backupIntent = new Intent(RUN_BACKUP_ACTION);
+        backupIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        mRunBackupIntent = PendingIntent.getBroadcast(context, 0, backupIntent, 0);
+
+        Intent initIntent = new Intent(RUN_INITIALIZE_ACTION);
+        initIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        mRunInitIntent = PendingIntent.getBroadcast(context, 0, initIntent, 0);
+
+        // Set up the backup-request journaling
+        mJournalDir = new File(mBaseStateDir, "pending");
+        mJournalDir.mkdirs();   // creates mBaseStateDir along the way
+        mJournal = null;        // will be created on first use
+
+        mConstants = new BackupManagerConstants(mBackupHandler, mContext.getContentResolver());
+        // We are observing changes to the constants throughout the lifecycle of BMS. This is
+        // because we reference the constants in multiple areas of BMS, which otherwise would
+        // require frequent starting and stopping.
+        mConstants.start();
+
+        // Set up the various sorts of package tracking we do
+        mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule");
+        initPackageTracking();
+
+        // Build our mapping of uid to backup client services.  This implicitly
+        // schedules a backup pass on the Package Manager metadata the first
+        // time anything needs to be backed up.
+        synchronized (mBackupParticipants) {
+            addPackageParticipantsLocked(null);
+        }
+
+        mTransportManager = transportManager;
+        mTransportManager.setOnTransportRegisteredListener(this::onTransportRegistered);
+        mRegisterTransportsRequestedTime = SystemClock.elapsedRealtime();
+        mBackupHandler.postDelayed(
+                mTransportManager::registerTransports, INITIALIZATION_DELAY_MILLIS);
+
+        // Now that we know about valid backup participants, parse any leftover journal files into
+        // the pending backup set
+        mBackupHandler.postDelayed(this::parseLeftoverJournals, INITIALIZATION_DELAY_MILLIS);
+
+        // Power management
+        mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
     }
 
+
     public BackupManagerConstants getConstants() {
         return mConstants;
     }
@@ -549,6 +768,7 @@
         return mPendingInits;
     }
 
+    /** Clear all pending transport initializations. */
     public void clearPendingInits() {
         mPendingInits.clear();
     }
@@ -562,28 +782,10 @@
         mRunningFullBackupTask = runningFullBackupTask;
     }
 
-    public static final class Lifecycle extends SystemService {
-
-        public Lifecycle(Context context) {
-            super(context);
-            sInstance = new Trampoline(context);
-        }
-
-        @Override
-        public void onStart() {
-            publishBinderService(Context.BACKUP_SERVICE, sInstance);
-        }
-
-        @Override
-        public void onUnlockUser(int userId) {
-            if (userId == UserHandle.USER_SYSTEM) {
-                sInstance.unlockSystemUser();
-            }
-        }
-    }
-
-    // Called through the trampoline from onUnlockUser(), then we buck the work
-    // off to the background thread to keep the unlock time down.
+    /**
+     * Called through Trampoline from {@link Lifecycle#onUnlockUser(int)}. We run the heavy work on
+     * a background thread to keep the unlock time down.
+     */
     public void unlockSystemUser() {
         // Migrate legacy setting
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup migrate");
@@ -618,89 +820,10 @@
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
     }
 
-    // Bookkeeping of in-flight operations for timeout etc. purposes.  The operation
-    // token is the index of the entry in the pending-operations list.
-    public static final int OP_PENDING = 0;
-    private static final int OP_ACKNOWLEDGED = 1;
-    private static final int OP_TIMEOUT = -1;
-
-    // Waiting for backup agent to respond during backup operation.
-    public static final int OP_TYPE_BACKUP_WAIT = 0;
-
-    // Waiting for backup agent to respond during restore operation.
-    public static final int OP_TYPE_RESTORE_WAIT = 1;
-
-    // An entire backup operation spanning multiple packages.
-    public static final int OP_TYPE_BACKUP = 2;
-
     /**
-     * mCurrentOperations contains the list of currently active operations.
-     *
-     * If type of operation is OP_TYPE_WAIT, it are waiting for an ack or timeout.
-     * An operation wraps a BackupRestoreTask within it.
-     * It's the responsibility of this task to remove the operation from this array.
-     *
-     * A BackupRestore task gets notified of ack/timeout for the operation via
-     * BackupRestoreTask#handleCancel, BackupRestoreTask#operationComplete and notifyAll called
-     * on the mCurrentOpLock.
-     * {@link BackupManagerService#waitUntilOperationComplete(int)} is
-     * used in various places to 'wait' for notifyAll and detect change of pending state of an
-     * operation. So typically, an operation will be removed from this array by:
-     * - BackupRestoreTask#handleCancel and
-     * - BackupRestoreTask#operationComplete OR waitUntilOperationComplete. Do not remove at both
-     * these places because waitUntilOperationComplete relies on the operation being present to
-     * determine its completion status.
-     *
-     * If type of operation is OP_BACKUP, it is a task running backups. It provides a handle to
-     * cancel backup tasks.
+     *  Utility: build a new random integer token. The low bits are the ordinal of the operation for
+     *  near-time uniqueness, and the upper bits are random for app-side unpredictability.
      */
-    @GuardedBy("mCurrentOpLock")
-    private final SparseArray<Operation> mCurrentOperations = new SparseArray<>();
-    private final Object mCurrentOpLock = new Object();
-    private final Random mTokenGenerator = new Random();
-    final AtomicInteger mNextToken = new AtomicInteger();
-
-    private final SparseArray<AdbParams> mAdbBackupRestoreConfirmations = new SparseArray<>();
-
-    // Where we keep our journal files and other bookkeeping
-    private File mBaseStateDir;
-    private File mDataDir;
-    private File mJournalDir;
-    @Nullable
-    private DataChangedJournal mJournal;
-
-    private final SecureRandom mRng = new SecureRandom();
-
-    // Keep a log of all the apps we've ever backed up, and what the dataset tokens are for both
-    // the current backup dataset and the ancestral dataset.
-    private ProcessedPackagesJournal mProcessedPackagesJournal;
-
-    private static final int CURRENT_ANCESTRAL_RECORD_VERSION = 1;
-    // increment when the schema changes
-    private File mTokenFile;
-    private Set<String> mAncestralPackages = null;
-    private long mAncestralToken = 0;
-    private long mCurrentToken = 0;
-
-    // Persistently track the need to do a full init
-    private static final String INIT_SENTINEL_FILE_NAME = "_need_init_";
-    private final ArraySet<String> mPendingInits = new ArraySet<>();  // transport names
-
-    // Round-robin queue for scheduling full backup passes
-    private static final int SCHEDULE_FILE_VERSION = 1; // current version of the schedule file
-
-    private File mFullBackupScheduleFile;
-    // If we're running a schedule-driven full backup, this is the task instance doing it
-
-    @GuardedBy("mQueueLock")
-    private PerformFullTransportBackupTask mRunningFullBackupTask;
-
-    @GuardedBy("mQueueLock")
-    private ArrayList<FullBackupEntry> mFullBackupQueue;
-
-    // Utility: build a new random integer token. The low bits are the ordinal of the
-    // operation for near-time uniqueness, and the upper bits are random for app-
-    // side unpredictability.
     public int generateRandomIntegerToken() {
         int token = mTokenGenerator.nextInt();
         if (token < 0) token = -token;
@@ -709,10 +832,9 @@
         return token;
     }
 
-    /*
-     * Construct a backup agent instance for the metadata pseudopackage.  This is a
-     * process-local non-lifecycle agent instance, so we manually set up the context
-     * topology for it.
+    /**
+     * Construct a backup agent instance for the metadata pseudopackage. This is a process-local
+     * non-lifecycle agent instance, so we manually set up the context topology for it.
      */
     public BackupAgent makeMetadataAgent() {
         PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(mPackageManager);
@@ -721,8 +843,8 @@
         return pmAgent;
     }
 
-    /*
-     * Same as above but with the explicit package-set configuration.
+    /**
+     * Same as {@link #makeMetadataAgent()} but with explicit package-set configuration.
      */
     public PackageManagerBackupAgent makeMetadataAgent(List<PackageInfo> packages) {
         PackageManagerBackupAgent pmAgent =
@@ -732,172 +854,6 @@
         return pmAgent;
     }
 
-    // ----- Debug-only backup operation trace -----
-    public void addBackupTrace(String s) {
-        if (DEBUG_BACKUP_TRACE) {
-            synchronized (mBackupTrace) {
-                mBackupTrace.add(s);
-            }
-        }
-    }
-
-    public void clearBackupTrace() {
-        if (DEBUG_BACKUP_TRACE) {
-            synchronized (mBackupTrace) {
-                mBackupTrace.clear();
-            }
-        }
-    }
-
-    // ----- Main service implementation -----
-
-    public static BackupManagerService create(
-            Context context,
-            Trampoline parent,
-            HandlerThread backupThread) {
-        // Set up our transport options and initialize the default transport
-        SystemConfig systemConfig = SystemConfig.getInstance();
-        Set<ComponentName> transportWhitelist = systemConfig.getBackupTransportWhitelist();
-        if (transportWhitelist == null) {
-            transportWhitelist = Collections.emptySet();
-        }
-
-        String transport =
-                Settings.Secure.getString(
-                        context.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT);
-        if (TextUtils.isEmpty(transport)) {
-            transport = null;
-        }
-        if (DEBUG) {
-            Slog.v(TAG, "Starting with transport " + transport);
-        }
-        TransportManager transportManager =
-                new TransportManager(
-                        context,
-                        transportWhitelist,
-                        transport);
-
-        // If encrypted file systems is enabled or disabled, this call will return the
-        // correct directory.
-        File baseStateDir = new File(Environment.getDataDirectory(), "backup");
-
-        // This dir on /cache is managed directly in init.rc
-        File dataDir = new File(Environment.getDownloadCacheDirectory(), "backup_stage");
-
-        return new BackupManagerService(
-                context,
-                parent,
-                backupThread,
-                baseStateDir,
-                dataDir,
-                transportManager);
-    }
-
-    @VisibleForTesting
-    public BackupManagerService(
-            Context context,
-            Trampoline parent,
-            HandlerThread backupThread,
-            File baseStateDir,
-            File dataDir,
-            TransportManager transportManager) {
-        mContext = context;
-        mPackageManager = context.getPackageManager();
-        mPackageManagerBinder = AppGlobals.getPackageManager();
-        mActivityManager = ActivityManager.getService();
-
-        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
-        mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
-
-        mBackupManagerBinder = Trampoline.asInterface(parent.asBinder());
-
-        mAgentTimeoutParameters = new
-                BackupAgentTimeoutParameters(Handler.getMain(), mContext.getContentResolver());
-        mAgentTimeoutParameters.start();
-
-        // spin up the backup/restore handler thread
-        mBackupHandler = new BackupHandler(this, backupThread.getLooper());
-
-        // Set up our bookkeeping
-        final ContentResolver resolver = context.getContentResolver();
-        mProvisioned = Settings.Global.getInt(resolver,
-                Settings.Global.DEVICE_PROVISIONED, 0) != 0;
-        mAutoRestore = Settings.Secure.getInt(resolver,
-                Settings.Secure.BACKUP_AUTO_RESTORE, 1) != 0;
-
-        mProvisionedObserver = new ProvisionedObserver(this, mBackupHandler);
-        resolver.registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
-                false, mProvisionedObserver);
-
-        mBaseStateDir = baseStateDir;
-        mBaseStateDir.mkdirs();
-        if (!SELinux.restorecon(mBaseStateDir)) {
-            Slog.e(TAG, "SELinux restorecon failed on " + mBaseStateDir);
-        }
-
-        mDataDir = dataDir;
-
-        mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng);
-
-        // Alarm receivers for scheduled backups & initialization operations
-        mRunBackupReceiver = new RunBackupReceiver(this);
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(RUN_BACKUP_ACTION);
-        context.registerReceiver(mRunBackupReceiver, filter,
-                android.Manifest.permission.BACKUP, null);
-
-        mRunInitReceiver = new RunInitializeReceiver(this);
-        filter = new IntentFilter();
-        filter.addAction(RUN_INITIALIZE_ACTION);
-        context.registerReceiver(mRunInitReceiver, filter,
-                android.Manifest.permission.BACKUP, null);
-
-        Intent backupIntent = new Intent(RUN_BACKUP_ACTION);
-        backupIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-        mRunBackupIntent = PendingIntent.getBroadcast(context, 0, backupIntent, 0);
-
-        Intent initIntent = new Intent(RUN_INITIALIZE_ACTION);
-        initIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-        mRunInitIntent = PendingIntent.getBroadcast(context, 0, initIntent, 0);
-
-        // Set up the backup-request journaling
-        mJournalDir = new File(mBaseStateDir, "pending");
-        mJournalDir.mkdirs();   // creates mBaseStateDir along the way
-        mJournal = null;        // will be created on first use
-
-        mConstants = new BackupManagerConstants(mBackupHandler, mContext.getContentResolver());
-        // We are observing changes to the constants throughout the lifecycle of BMS. This is
-        // because we reference the constants in multiple areas of BMS, which otherwise would
-        // require frequent starting and stopping.
-        mConstants.start();
-
-        // Set up the various sorts of package tracking we do
-        mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule");
-        initPackageTracking();
-
-        // Build our mapping of uid to backup client services.  This implicitly
-        // schedules a backup pass on the Package Manager metadata the first
-        // time anything needs to be backed up.
-        synchronized (mBackupParticipants) {
-            addPackageParticipantsLocked(null);
-        }
-
-        mTransportManager = transportManager;
-        mTransportManager.setOnTransportRegisteredListener(this::onTransportRegistered);
-        mRegisterTransportsRequestedTime = SystemClock.elapsedRealtime();
-        mBackupHandler.postDelayed(
-                mTransportManager::registerTransports, INITIALIZATION_DELAY_MILLIS);
-
-        // Now that we know about valid backup participants, parse any leftover journal files into
-        // the pending backup set
-        mBackupHandler.postDelayed(this::parseLeftoverJournals, INITIALIZATION_DELAY_MILLIS);
-
-        // Power management
-        mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
-    }
-
     private void initPackageTracking() {
         if (MORE_DEBUG) Slog.v(TAG, "` tracking");
 
@@ -2750,54 +2706,6 @@
         }
     }
 
-    private static boolean backupSettingMigrated(int userId) {
-        File base = new File(Environment.getDataDirectory(), "backup");
-        File enableFile = new File(base, BACKUP_ENABLE_FILE);
-        return enableFile.exists();
-    }
-
-    private static boolean readBackupEnableState(int userId) {
-        File base = new File(Environment.getDataDirectory(), "backup");
-        File enableFile = new File(base, BACKUP_ENABLE_FILE);
-        if (enableFile.exists()) {
-            try (FileInputStream fin = new FileInputStream(enableFile)) {
-                int state = fin.read();
-                return state != 0;
-            } catch (IOException e) {
-                // can't read the file; fall through to assume disabled
-                Slog.e(TAG, "Cannot read enable state; assuming disabled");
-            }
-        } else {
-            if (DEBUG) {
-                Slog.i(TAG, "isBackupEnabled() => false due to absent settings file");
-            }
-        }
-        return false;
-    }
-
-    private static void writeBackupEnableState(boolean enable, int userId) {
-        File base = new File(Environment.getDataDirectory(), "backup");
-        File enableFile = new File(base, BACKUP_ENABLE_FILE);
-        File stage = new File(base, BACKUP_ENABLE_FILE + "-stage");
-        try (FileOutputStream fout = new FileOutputStream(stage)) {
-            fout.write(enable ? 1 : 0);
-            fout.close();
-            stage.renameTo(enableFile);
-            // will be synced immediately by the try-with-resources call to close()
-        } catch (IOException | RuntimeException e) {
-            // Whoops; looks like we're doomed.  Roll everything out, disabled,
-            // including the legacy state.
-            Slog.e(TAG, "Unable to record backup enable state; reverting to disabled: "
-                    + e.getMessage());
-
-            ContentResolver resolver = sInstance.getContext().getContentResolver();
-            Settings.Secure.putStringForUser(resolver,
-                    Settings.Secure.BACKUP_ENABLED, null, userId);
-            enableFile.delete();
-            stage.delete();
-        }
-    }
-
     // Enable/disable backups
     public void setBackupEnabled(boolean enable) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
@@ -3565,17 +3473,6 @@
                 pw.println("    " + s);
             }
 
-            if (DEBUG_BACKUP_TRACE) {
-                synchronized (mBackupTrace) {
-                    if (!mBackupTrace.isEmpty()) {
-                        pw.println("Most recent backup trace:");
-                        for (String s : mBackupTrace) {
-                            pw.println("   " + s);
-                        }
-                    }
-                }
-            }
-
             pw.print("Ancestral: ");
             pw.println(Long.toHexString(mAncestralToken));
             pw.print("Current:   ");
@@ -3627,4 +3524,71 @@
         return mBackupManagerBinder;
     }
 
+    private static boolean backupSettingMigrated(int userId) {
+        File base = new File(Environment.getDataDirectory(), "backup");
+        File enableFile = new File(base, BACKUP_ENABLE_FILE);
+        return enableFile.exists();
+    }
+
+    private static boolean readBackupEnableState(int userId) {
+        File base = new File(Environment.getDataDirectory(), "backup");
+        File enableFile = new File(base, BACKUP_ENABLE_FILE);
+        if (enableFile.exists()) {
+            try (FileInputStream fin = new FileInputStream(enableFile)) {
+                int state = fin.read();
+                return state != 0;
+            } catch (IOException e) {
+                // can't read the file; fall through to assume disabled
+                Slog.e(TAG, "Cannot read enable state; assuming disabled");
+            }
+        } else {
+            if (DEBUG) {
+                Slog.i(TAG, "isBackupEnabled() => false due to absent settings file");
+            }
+        }
+        return false;
+    }
+
+    private static void writeBackupEnableState(boolean enable, int userId) {
+        File base = new File(Environment.getDataDirectory(), "backup");
+        File enableFile = new File(base, BACKUP_ENABLE_FILE);
+        File stage = new File(base, BACKUP_ENABLE_FILE + "-stage");
+        try (FileOutputStream fout = new FileOutputStream(stage)) {
+            fout.write(enable ? 1 : 0);
+            fout.close();
+            stage.renameTo(enableFile);
+            // will be synced immediately by the try-with-resources call to close()
+        } catch (IOException | RuntimeException e) {
+            // Whoops; looks like we're doomed.  Roll everything out, disabled,
+            // including the legacy state.
+            Slog.e(TAG, "Unable to record backup enable state; reverting to disabled: "
+                    + e.getMessage());
+
+            ContentResolver resolver = sInstance.getContext().getContentResolver();
+            Settings.Secure.putStringForUser(resolver,
+                    Settings.Secure.BACKUP_ENABLED, null, userId);
+            enableFile.delete();
+            stage.delete();
+        }
+    }
+
+    /** Implementation to receive lifecycle event callbacks for system services. */
+    public static final class Lifecycle extends SystemService {
+        public Lifecycle(Context context) {
+            super(context);
+            sInstance = new Trampoline(context);
+        }
+
+        @Override
+        public void onStart() {
+            publishBinderService(Context.BACKUP_SERVICE, sInstance);
+        }
+
+        @Override
+        public void onUnlockUser(int userId) {
+            if (userId == UserHandle.USER_SYSTEM) {
+                sInstance.unlockSystemUser();
+            }
+        }
+    }
 }
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java
new file mode 100644
index 0000000..18011f6
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import com.android.server.backup.encryption.chunking.Chunker;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.util.Arrays;
+
+/** Splits a stream of bytes into variable-sized chunks, using content-defined chunking. */
+public class ContentDefinedChunker implements Chunker {
+    private static final int WINDOW_SIZE = 31;
+    private static final byte DEFAULT_OUT_BYTE = (byte) 0;
+
+    private final byte[] mChunkBuffer;
+    private final RabinFingerprint64 mRabinFingerprint64;
+    private final FingerprintMixer mFingerprintMixer;
+    private final BreakpointPredicate mBreakpointPredicate;
+    private final int mMinChunkSize;
+    private final int mMaxChunkSize;
+
+    /**
+     * Constructor.
+     *
+     * @param minChunkSize The minimum size of a chunk. No chunk will be produced of a size smaller
+     *     than this except possibly at the very end of the stream.
+     * @param maxChunkSize The maximum size of a chunk. No chunk will be produced of a larger size.
+     * @param rabinFingerprint64 Calculates fingerprints, with which to determine breakpoints.
+     * @param breakpointPredicate Given a Rabin fingerprint, returns whether this ought to be a
+     *     breakpoint.
+     */
+    public ContentDefinedChunker(
+            int minChunkSize,
+            int maxChunkSize,
+            RabinFingerprint64 rabinFingerprint64,
+            FingerprintMixer fingerprintMixer,
+            BreakpointPredicate breakpointPredicate) {
+        checkArgument(
+                minChunkSize >= WINDOW_SIZE,
+                "Minimum chunk size must be greater than window size.");
+        checkArgument(
+                maxChunkSize >= minChunkSize,
+                "Maximum chunk size cannot be smaller than minimum chunk size.");
+        mChunkBuffer = new byte[maxChunkSize];
+        mRabinFingerprint64 = rabinFingerprint64;
+        mBreakpointPredicate = breakpointPredicate;
+        mFingerprintMixer = fingerprintMixer;
+        mMinChunkSize = minChunkSize;
+        mMaxChunkSize = maxChunkSize;
+    }
+
+    /**
+     * Breaks the input stream into variable-sized chunks.
+     *
+     * @param inputStream The input bytes to break into chunks.
+     * @param chunkConsumer A function to process each chunk as it's generated.
+     * @throws IOException Thrown if there is an issue reading from the input stream.
+     * @throws GeneralSecurityException Thrown if the {@link ChunkConsumer} throws it.
+     */
+    @Override
+    public void chunkify(InputStream inputStream, ChunkConsumer chunkConsumer)
+            throws IOException, GeneralSecurityException {
+        int chunkLength;
+        int initialReadLength = mMinChunkSize - WINDOW_SIZE;
+
+        // Performance optimization - there is no reason to calculate fingerprints for windows
+        // ending before the minimum chunk size.
+        while ((chunkLength =
+                        inputStream.read(mChunkBuffer, /*off=*/ 0, /*len=*/ initialReadLength))
+                != -1) {
+            int b;
+            long fingerprint = 0L;
+
+            while ((b = inputStream.read()) != -1) {
+                byte inByte = (byte) b;
+                byte outByte = getCurrentWindowStartByte(chunkLength);
+                mChunkBuffer[chunkLength++] = inByte;
+
+                fingerprint =
+                        mRabinFingerprint64.computeFingerprint64(inByte, outByte, fingerprint);
+
+                if (chunkLength >= mMaxChunkSize
+                        || (chunkLength >= mMinChunkSize
+                                && mBreakpointPredicate.isBreakpoint(
+                                        mFingerprintMixer.mix(fingerprint)))) {
+                    chunkConsumer.accept(Arrays.copyOf(mChunkBuffer, chunkLength));
+                    chunkLength = 0;
+                    break;
+                }
+            }
+
+            if (chunkLength > 0) {
+                chunkConsumer.accept(Arrays.copyOf(mChunkBuffer, chunkLength));
+            }
+        }
+    }
+
+    private byte getCurrentWindowStartByte(int chunkLength) {
+        if (chunkLength < mMinChunkSize) {
+            return DEFAULT_OUT_BYTE;
+        } else {
+            return mChunkBuffer[chunkLength - WINDOW_SIZE];
+        }
+    }
+
+    /** Whether the current fingerprint indicates the end of a chunk. */
+    public interface BreakpointPredicate {
+
+        /**
+         * Returns {@code true} if the fingerprint of the last {@code WINDOW_SIZE} bytes indicates
+         * the chunk ought to end at this position.
+         *
+         * @param fingerprint Fingerprint of the last {@code WINDOW_SIZE} bytes.
+         * @return Whether this ought to be a chunk breakpoint.
+         */
+        boolean isBreakpoint(long fingerprint);
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java
new file mode 100644
index 0000000..e9f3050
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+
+import javax.crypto.SecretKey;
+
+/**
+ * Helper for mixing fingerprint with key material.
+ *
+ * <p>We do this as otherwise the Rabin fingerprint leaks information about the plaintext. i.e., if
+ * two users have the same file, it will be partitioned by Rabin in the same way, allowing us to
+ * infer that it is the same as another user's file.
+ *
+ * <p>By mixing the fingerprint with the user's secret key, the chunking method is different on a
+ * per key basis. Each application has its own {@link SecretKey}, so we cannot infer that a file is
+ * the same even across multiple applications owned by the same user, never mind across multiple
+ * users.
+ *
+ * <p>Instead of directly mixing the fingerprint with the user's secret, we first securely and
+ * deterministically derive a secondary chunking key. As Rabin is not a cryptographically secure
+ * hash, it might otherwise leak information about the user's secret. This prevents that from
+ * happening.
+ */
+public class FingerprintMixer {
+    public static final int SALT_LENGTH_BYTES = 256 / Byte.SIZE;
+    private static final String DERIVED_KEY_NAME = "RabinFingerprint64Mixer";
+
+    private final long mAddend;
+    private final long mMultiplicand;
+
+    /**
+     * A new instance from a given secret key and salt. Salt must be the same across incremental
+     * backups, or a different chunking strategy will be used each time, defeating the dedup.
+     *
+     * @param secretKey The application-specific secret.
+     * @param salt The salt.
+     * @throws InvalidKeyException If the encoded form of {@code secretKey} is inaccessible.
+     */
+    public FingerprintMixer(SecretKey secretKey, byte[] salt) throws InvalidKeyException {
+        checkArgument(salt.length == SALT_LENGTH_BYTES, "Requires a 256-bit salt.");
+        byte[] keyBytes = secretKey.getEncoded();
+        if (keyBytes == null) {
+            throw new InvalidKeyException("SecretKey must support encoding for FingerprintMixer.");
+        }
+        byte[] derivedKey =
+                Hkdf.hkdf(keyBytes, salt, DERIVED_KEY_NAME.getBytes(StandardCharsets.UTF_8));
+        ByteBuffer buffer = ByteBuffer.wrap(derivedKey);
+        mAddend = buffer.getLong();
+        // Multiplicand must be odd - otherwise we lose some bits of the Rabin fingerprint when
+        // mixing
+        mMultiplicand = buffer.getLong() | 1;
+    }
+
+    /**
+     * Mixes the fingerprint with the derived key material. This is performed by adding part of the
+     * derived key and multiplying by another part of the derived key (which is forced to be odd, so
+     * that the operation is reversible).
+     *
+     * @param fingerprint A 64-bit Rabin fingerprint.
+     * @return The mixed fingerprint.
+     */
+    long mix(long fingerprint) {
+        return ((fingerprint + mAddend) * mMultiplicand);
+    }
+
+    /** The addend part of the derived key. */
+    long getAddend() {
+        return mAddend;
+    }
+
+    /** The multiplicand part of the derived key. */
+    long getMultiplicand() {
+        return mMultiplicand;
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/Hkdf.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/Hkdf.java
new file mode 100644
index 0000000..6f4f549
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/Hkdf.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Secure HKDF utils. Allows client to deterministically derive additional key material from a base
+ * secret. If the derived key material is compromised, this does not in of itself compromise the
+ * root secret.
+ *
+ * <p>TODO(b/116575321): After all code is ported, rename this class to HkdfUtils.
+ */
+public final class Hkdf {
+    private static final byte[] CONSTANT_01 = {0x01};
+    private static final String HmacSHA256 = "HmacSHA256";
+    private static final String AES = "AES";
+
+    /**
+     * Implements HKDF (RFC 5869) with the SHA-256 hash and a 256-bit output key length.
+     *
+     * <p>IMPORTANT: The use or edit of this method requires a security review.
+     *
+     * @param masterKey Master key from which to derive sub-keys.
+     * @param salt A randomly generated 256-bit byte string.
+     * @param data Arbitrary information that is bound to the derived key (i.e., used in its
+     *     creation).
+     * @return Raw derived key bytes = HKDF-SHA256(masterKey, salt, data).
+     * @throws InvalidKeyException If the salt can not be used as a valid key.
+     */
+    static byte[] hkdf(byte[] masterKey, byte[] salt, byte[] data) throws InvalidKeyException {
+        checkNotNull(masterKey, "HKDF requires master key to be set.");
+        checkNotNull(salt, "HKDF requires a salt.");
+        checkNotNull(data, "No data provided to HKDF.");
+        return hkdfSha256Expand(hkdfSha256Extract(masterKey, salt), data);
+    }
+
+    private Hkdf() {}
+
+    /**
+     * The HKDF (RFC 5869) extraction function, using the SHA-256 hash function. This function is
+     * used to pre-process the {@code inputKeyMaterial} and mix it with the {@code salt}, producing
+     * output suitable for use with HKDF expansion function (which produces the actual derived key).
+     *
+     * <p>IMPORTANT: The use or edit of this method requires a security review.
+     *
+     * @see #hkdfSha256Expand(byte[], byte[])
+     * @return HMAC-SHA256(salt, inputKeyMaterial) (salt is the "key" for the HMAC)
+     * @throws InvalidKeyException If the salt can not be used as a valid key.
+     */
+    private static byte[] hkdfSha256Extract(byte[] inputKeyMaterial, byte[] salt)
+            throws InvalidKeyException {
+        // Note that the SecretKey encoding format is defined to be RAW, so the encoded form should
+        // be consistent across implementations.
+        Mac sha256;
+        try {
+            sha256 = Mac.getInstance(HmacSHA256);
+        } catch (NoSuchAlgorithmException e) {
+            // This can not happen - HmacSHA256 is supported by the platform.
+            throw new AssertionError(e);
+        }
+        sha256.init(new SecretKeySpec(salt, AES));
+
+        return sha256.doFinal(inputKeyMaterial);
+    }
+
+    /**
+     * Special case of HKDF (RFC 5869) expansion function, using the SHA-256 hash function and
+     * allowing for a maximum output length of 256 bits.
+     *
+     * <p>IMPORTANT: The use or edit of this method requires a security review.
+     *
+     * @param pseudoRandomKey Generated by {@link #hkdfSha256Extract(byte[], byte[])}.
+     * @param info Arbitrary information the derived key should be bound to.
+     * @return Raw derived key bytes = HMAC-SHA256(pseudoRandomKey, info | 0x01).
+     * @throws InvalidKeyException If the salt can not be used as a valid key.
+     */
+    private static byte[] hkdfSha256Expand(byte[] pseudoRandomKey, byte[] info)
+            throws InvalidKeyException {
+        // Note that RFC 5869 computes number of blocks N = ceil(hash length / output length), but
+        // here we only deal with a 256 bit hash up to a 256 bit output, yielding N=1.
+        Mac sha256;
+        try {
+            sha256 = Mac.getInstance(HmacSHA256);
+        } catch (NoSuchAlgorithmException e) {
+            // This can not happen - HmacSHA256 is supported by the platform.
+            throw new AssertionError(e);
+        }
+        sha256.init(new SecretKeySpec(pseudoRandomKey, AES));
+
+        sha256.update(info);
+        sha256.update(CONSTANT_01);
+        return sha256.doFinal();
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java
new file mode 100644
index 0000000..e867e7c
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import com.android.server.backup.encryption.chunking.cdc.ContentDefinedChunker.BreakpointPredicate;
+
+/**
+ * Function to determine whether a 64-bit fingerprint ought to be a chunk breakpoint.
+ *
+ * <p>This works by checking whether there are at least n leading zeros in the fingerprint. n is
+ * calculated to on average cause a breakpoint after a given number of trials (provided in the
+ * constructor). This allows us to choose a number of trials that gives a desired average chunk
+ * size. This works because the fingerprint is pseudo-randomly distributed.
+ */
+public class IsChunkBreakpoint implements BreakpointPredicate {
+    private final int mLeadingZeros;
+    private final long mBitmask;
+
+    /**
+     * A new instance that causes a breakpoint after a given number of trials on average.
+     *
+     * @param averageNumberOfTrialsUntilBreakpoint The number of trials after which on average to
+     *     create a new chunk. If this is not a power of 2, some precision is sacrificed (i.e., on
+     *     average, breaks will actually happen after the nearest power of 2 to the average number
+     *     of trials passed in).
+     */
+    public IsChunkBreakpoint(long averageNumberOfTrialsUntilBreakpoint) {
+        checkArgument(
+                averageNumberOfTrialsUntilBreakpoint >= 0,
+                "Average number of trials must be non-negative");
+
+        // Want n leading zeros after t trials.
+        // P(leading zeros = n) = 1/2^n
+        // Expected num trials to get n leading zeros = 1/2^-n
+        // t = 1/2^-n
+        // n = log2(t)
+        mLeadingZeros = (int) Math.round(log2(averageNumberOfTrialsUntilBreakpoint));
+        mBitmask = ~(~0L >>> mLeadingZeros);
+    }
+
+    /**
+     * Returns {@code true} if {@code fingerprint} indicates that there should be a chunk
+     * breakpoint.
+     */
+    @Override
+    public boolean isBreakpoint(long fingerprint) {
+        return (fingerprint & mBitmask) == 0;
+    }
+
+    /** Returns the number of leading zeros in the fingerprint that causes a breakpoint. */
+    public int getLeadingZeros() {
+        return mLeadingZeros;
+    }
+
+    /**
+     * Calculates log base 2 of x. Not the most efficient possible implementation, but it's simple,
+     * obviously correct, and is only invoked on object construction.
+     */
+    private static double log2(double x) {
+        return Math.log(x) / Math.log(2);
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java
new file mode 100644
index 0000000..1e14ffa
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+/** Helper to calculate a 64-bit Rabin fingerprint over a 31-byte window. */
+public class RabinFingerprint64 {
+    private static final long DEFAULT_IRREDUCIBLE_POLYNOMIAL_64 = 0x000000000000001BL;
+    private static final int POLYNOMIAL_DEGREE = 64;
+    private static final int SLIDING_WINDOW_SIZE_BYTES = 31;
+
+    private final long mPoly64;
+    // Auxiliary tables to speed up the computation of Rabin fingerprints.
+    private final long[] mTableFP64 = new long[256];
+    private final long[] mTableOutByte = new long[256];
+
+    /**
+     * Constructs a new instance over the given irreducible 64-degree polynomial. It is up to the
+     * caller to determine that the polynomial is irreducible. If it is not the fingerprinting will
+     * not behave as expected.
+     *
+     * @param poly64 The polynomial.
+     */
+    public RabinFingerprint64(long poly64) {
+        mPoly64 = poly64;
+    }
+
+    /** Constructs a new instance using {@code x^64 + x^4 + x + 1} as the irreducible polynomial. */
+    public RabinFingerprint64() {
+        this(DEFAULT_IRREDUCIBLE_POLYNOMIAL_64);
+        computeFingerprintTables64();
+        computeFingerprintTables64Windowed();
+    }
+
+    /**
+     * Computes the fingerprint for the new sliding window given the fingerprint of the previous
+     * sliding window, the byte sliding in, and the byte sliding out.
+     *
+     * @param inChar The new char coming into the sliding window.
+     * @param outChar The left most char sliding out of the window.
+     * @param fingerPrint Fingerprint for previous window.
+     * @return New fingerprint for the new sliding window.
+     */
+    public long computeFingerprint64(byte inChar, byte outChar, long fingerPrint) {
+        return (fingerPrint << 8)
+                ^ (inChar & 0xFF)
+                ^ mTableFP64[(int) (fingerPrint >>> 56)]
+                ^ mTableOutByte[outChar & 0xFF];
+    }
+
+    /** Compute auxiliary tables to speed up the fingerprint computation. */
+    private void computeFingerprintTables64() {
+        long[] degreesRes64 = new long[POLYNOMIAL_DEGREE];
+        degreesRes64[0] = mPoly64;
+        for (int i = 1; i < POLYNOMIAL_DEGREE; i++) {
+            if ((degreesRes64[i - 1] & (1L << 63)) == 0) {
+                degreesRes64[i] = degreesRes64[i - 1] << 1;
+            } else {
+                degreesRes64[i] = (degreesRes64[i - 1] << 1) ^ mPoly64;
+            }
+        }
+        for (int i = 0; i < 256; i++) {
+            int currIndex = i;
+            for (int j = 0; (currIndex > 0) && (j < 8); j++) {
+                if ((currIndex & 0x1) == 1) {
+                    mTableFP64[i] ^= degreesRes64[j];
+                }
+                currIndex >>>= 1;
+            }
+        }
+    }
+
+    /**
+     * Compute auxiliary table {@code mTableOutByte} to facilitate the computing of fingerprints for
+     * sliding windows. This table is to take care of the effect on the fingerprint when the
+     * leftmost byte in the window slides out.
+     */
+    private void computeFingerprintTables64Windowed() {
+        // Auxiliary array degsRes64[8] defined by: <code>degsRes64[i] = x^(8 *
+        // SLIDING_WINDOW_SIZE_BYTES + i) mod this.mPoly64.</code>
+        long[] degsRes64 = new long[8];
+        degsRes64[0] = mPoly64;
+        for (int i = 65; i < 8 * (SLIDING_WINDOW_SIZE_BYTES + 1); i++) {
+            if ((degsRes64[(i - 1) % 8] & (1L << 63)) == 0) {
+                degsRes64[i % 8] = degsRes64[(i - 1) % 8] << 1;
+            } else {
+                degsRes64[i % 8] = (degsRes64[(i - 1) % 8] << 1) ^ mPoly64;
+            }
+        }
+        for (int i = 0; i < 256; i++) {
+            int currIndex = i;
+            for (int j = 0; (currIndex > 0) && (j < 8); j++) {
+                if ((currIndex & 0x1) == 1) {
+                    mTableOutByte[i] ^= degsRes64[j];
+                }
+                currIndex >>>= 1;
+            }
+        }
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index e108026..755095e 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -45,9 +45,9 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.EventLogTags;
 import com.android.server.backup.BackupAgentTimeoutParameters;
+import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.BackupRestoreTask;
 import com.android.server.backup.FullBackupJob;
-import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.TransportManager;
 import com.android.server.backup.internal.OnTaskFinishedListener;
 import com.android.server.backup.internal.Operation;
@@ -599,7 +599,6 @@
                 cleanUpPipes(enginePipes);
                 if (currentPackage.applicationInfo != null) {
                     Slog.i(TAG, "Unbinding agent in " + packageName);
-                    backupManagerService.addBackupTrace("unbinding " + packageName);
                     try {
                         backupManagerService.getActivityManager().unbindBackupAgent(
                                 currentPackage.applicationInfo);
@@ -709,7 +708,6 @@
             try {
                 backupManagerService.prepareOperationTimeout(
                         mCurrentOpToken, fullBackupAgentTimeoutMillis, this, OP_TYPE_BACKUP_WAIT);
-                backupManagerService.addBackupTrace("preflighting");
                 if (MORE_DEBUG) {
                     Slog.d(TAG, "Preflighting full payload of " + pkg.packageName);
                 }
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index 3a5232a..d6f2a87 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -260,6 +260,10 @@
     @Nullable private ParcelFileDescriptor mSavedState;
     @Nullable private ParcelFileDescriptor mBackupData;
     @Nullable private ParcelFileDescriptor mNewState;
+    // Indicates whether there was any data to be backed up, i.e. the queue was not empty
+    // and at least one of the packages had data. Used to avoid updating current token for
+    // empty backups.
+    private boolean mHasDataToBackup;
 
     /**
      * This {@link ConditionVariable} is used to signal that the cancel operation has been
@@ -332,6 +336,8 @@
     public void run() {
         Process.setThreadPriority(THREAD_PRIORITY);
 
+        mHasDataToBackup = false;
+
         int status = BackupTransport.TRANSPORT_OK;
         try {
             startTask();
@@ -529,10 +535,10 @@
 
         String callerLogString = "KVBT.finishTask()";
 
-        // If we succeeded and this is the first time we've done a backup, we can record the current
-        // backup dataset token.
+        // If the backup data was not empty, we succeeded and this is the first time
+        // we've done a backup, we can record the current backup dataset token.
         long currentToken = mBackupManagerService.getCurrentToken();
-        if ((status == BackupTransport.TRANSPORT_OK) && (currentToken == 0)) {
+        if (mHasDataToBackup && (status == BackupTransport.TRANSPORT_OK) && (currentToken == 0)) {
             try {
                 IBackupTransport transport = mTransportClient.connectOrThrow(callerLogString);
                 mBackupManagerService.setCurrentToken(transport.getCurrentRestoreSet());
@@ -838,6 +844,8 @@
             return BackupTransport.TRANSPORT_OK;
         }
 
+        mHasDataToBackup = true;
+
         int status;
         try (ParcelFileDescriptor backupData =
                 ParcelFileDescriptor.open(backupDataFile, MODE_READ_ONLY)) {
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 888ad1d..6174300 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -3,6 +3,7 @@
 
     aidl: {
         include_dirs: [
+            "frameworks/base/cmds/idmap2/idmap2d/aidl",
             "frameworks/native/aidl/binder",
             "frameworks/native/cmds/dumpstate/binder",
             "system/core/storaged/binder",
@@ -13,6 +14,7 @@
     srcs: [
         "java/**/*.java",
         ":dumpstate_aidl",
+        ":idmap2_aidl",
         ":netd_aidl",
         ":netd_metrics_aidl",
         ":installd_aidl",
diff --git a/services/core/java/com/android/server/AbstractMasterSystemService.java b/services/core/java/com/android/server/AbstractMasterSystemService.java
index c955daf..6cae887 100644
--- a/services/core/java/com/android/server/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/AbstractMasterSystemService.java
@@ -244,7 +244,7 @@
      */
     @GuardedBy("mLock")
     @Nullable
-    protected S peekServiceForUserLocked(int userId) {
+    protected S peekServiceForUserLocked(@UserIdInt int userId) {
         final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
                 Binder.getCallingUid(), userId, false, false, null, null);
         return mServicesCache.get(resolvedUserId);
@@ -254,7 +254,7 @@
      * Updates a cached service for a given user.
      */
     @GuardedBy("mLock")
-    protected void updateCachedServiceLocked(int userId) {
+    protected void updateCachedServiceLocked(@UserIdInt int userId) {
         updateCachedServiceLocked(userId, isDisabledLocked(userId));
     }
 
@@ -262,7 +262,7 @@
      * Checks whether the service is disabled (through {@link UserManager} restrictions) for the
      * given user.
      */
-    protected boolean isDisabledLocked(int userId) {
+    protected boolean isDisabledLocked(@UserIdInt int userId) {
         return mDisabledUsers == null ? false : mDisabledUsers.get(userId);
     }
 
@@ -274,7 +274,7 @@
      * @return service for the user.
      */
     @GuardedBy("mLock")
-    protected S updateCachedServiceLocked(int userId, boolean disabled) {
+    protected S updateCachedServiceLocked(@UserIdInt int userId, boolean disabled) {
         final S service = getServiceForUserLocked(userId);
         if (service != null) {
             service.updateLocked(disabled);
@@ -304,7 +304,7 @@
      * <p>By default doesn't do anything, but can be overridden by subclasses.
      */
     @SuppressWarnings("unused")
-    protected void onServiceEnabledLocked(S service, @UserIdInt int userId) {
+    protected void onServiceEnabledLocked(@NonNull S service, @UserIdInt int userId) {
     }
 
     /**
@@ -314,15 +314,23 @@
      */
     @GuardedBy("mLock")
     @NonNull
-    protected S removeCachedServiceLocked(@UserIdInt int userId) {
+    private S removeCachedServiceLocked(@UserIdInt int userId) {
         final S service = peekServiceForUserLocked(userId);
         if (service != null) {
             mServicesCache.delete(userId);
+            onServiceRemoved(service, userId);
         }
         return service;
     }
 
     /**
+     * Called after the service is removed from the cache.
+     */
+    @SuppressWarnings("unused")
+    protected void onServiceRemoved(@NonNull S service, @UserIdInt int userId) {
+    }
+
+    /**
      * Visits all services in the cache.
      */
     @GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/AbstractPerUserSystemService.java b/services/core/java/com/android/server/AbstractPerUserSystemService.java
index 201abe6..97977df 100644
--- a/services/core/java/com/android/server/AbstractPerUserSystemService.java
+++ b/services/core/java/com/android/server/AbstractPerUserSystemService.java
@@ -167,7 +167,7 @@
     @GuardedBy("mLock")
     protected final int getServiceUidLocked() {
         if (mServiceInfo == null) {
-            Slog.w(mTag, "getServiceUidLocked(): no mServiceInfo");
+            if (mMaster.verbose) Slog.v(mTag, "getServiceUidLocked(): no mServiceInfo");
             return Process.INVALID_UID;
         }
         return mServiceInfo.applicationInfo.uid;
@@ -267,8 +267,18 @@
     @GuardedBy("mLock")
     protected void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
         pw.print(prefix); pw.print("User: "); pw.println(mUserId);
-        pw.print(prefix); pw.print("Disabled: "); pw.println(mDisabled);
+        pw.print(prefix); pw.print("Disabled by UserManager: "); pw.println(mDisabled);
         pw.print(prefix); pw.print("Setup complete: "); pw.println(mSetupComplete);
-        pw.print(prefix); pw.print("Service name: "); pw.println(getComponentNameFromSettings());
+        if (mServiceInfo != null) {
+            pw.print(prefix); pw.print("Service UID: ");
+            pw.println(mServiceInfo.applicationInfo.uid);
+        }
+        final String componentName = getComponentNameFromSettings();
+        if (componentName != null) {
+            pw.print(prefix); pw.print("Service name: ");
+            pw.println(componentName);
+        } else {
+            pw.println("No service package set");
+        }
     }
 }
diff --git a/services/core/java/com/android/server/AbstractRemoteService.java b/services/core/java/com/android/server/AbstractRemoteService.java
index 1d3a34c..181d7fd 100644
--- a/services/core/java/com/android/server/AbstractRemoteService.java
+++ b/services/core/java/com/android/server/AbstractRemoteService.java
@@ -366,11 +366,12 @@
                     mCompleted = true;
                 }
 
-                Slog.w(mTag, "timed out");
                 final S remoteService = mWeakService.get();
                 if (remoteService != null) {
-                    Slog.w(mTag, " timed out after " + service.getRemoteRequestMillis() + " ms");
+                    Slog.w(mTag, "timed out after " + service.getRemoteRequestMillis() + " ms");
                     onTimeout(remoteService);
+                } else {
+                    Slog.w(mTag, "timed out (no service)");
                 }
             };
             mServiceHandler.postAtTime(mTimeoutTrigger,
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index cd98263..fa98da5 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import static android.app.AppOpsManager.OP_PLAY_AUDIO;
 import static android.app.AppOpsManager.UID_STATE_BACKGROUND;
 import static android.app.AppOpsManager.UID_STATE_CACHED;
 import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
@@ -36,8 +37,11 @@
 import android.app.AppOpsManager.HistoricalPackageOps;
 import android.app.AppOpsManagerInternal;
 import android.app.AppOpsManagerInternal.CheckOpsDelegate;
+import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
@@ -76,6 +80,7 @@
 import android.util.TimeUtils;
 import android.util.Xml;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IAppOpsActiveCallback;
 import com.android.internal.app.IAppOpsCallback;
@@ -215,6 +220,7 @@
 
     SparseIntArray mProfileOwners;
 
+    @GuardedBy("this")
     private CheckOpsDelegate mCheckOpsDelegate;
 
     /**
@@ -645,6 +651,26 @@
             }
         }
 
+        final IntentFilter packageSuspendFilter = new IntentFilter();
+        packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_UNSUSPENDED);
+        packageSuspendFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
+        mContext.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                final int[] changedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
+                final String[] changedPkgs = intent.getStringArrayExtra(
+                        Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                final ArraySet<ModeCallback> callbacks = mOpModeWatchers.get(OP_PLAY_AUDIO);
+                for (int i = 0; i < changedUids.length; i++) {
+                    final int changedUid = changedUids[i];
+                    final String changedPkg = changedPkgs[i];
+                    // We trust packagemanager to insert matching uid and packageNames in the extras
+                    mHandler.sendMessage(PooledLambda.obtainMessage(AppOpsService::notifyOpChanged,
+                            AppOpsService.this, callbacks, OP_PLAY_AUDIO, changedUid, changedPkg));
+                }
+            }
+        }, packageSuspendFilter);
+
         PackageManagerInternal packageManagerInternal = LocalServices.getService(
                 PackageManagerInternal.class);
         packageManagerInternal.setExternalSourcesPolicy(
@@ -1210,13 +1236,29 @@
 
     @Override
     public void setMode(int code, int uid, String packageName, int mode) {
+        setMode(code, uid, packageName, mode, true, false);
+    }
+
+    /**
+     * Sets the mode for a certain op and uid.
+     *
+     * @param code The op code to set
+     * @param uid The UID for which to set
+     * @param packageName The package for which to set
+     * @param mode The new mode to set
+     * @param verifyUid Iff {@code true}, check that the package name belongs to the uid
+     * @param isPrivileged Whether the package is privileged. (Only used if {@code verifyUid ==
+     *                     false})
+     */
+    private void setMode(int code, int uid, @NonNull String packageName, int mode,
+            boolean verifyUid, boolean isPrivileged) {
         enforceManageAppOpsModes(Binder.getCallingPid(), Binder.getCallingUid(), uid);
         verifyIncomingOp(code);
         ArraySet<ModeCallback> repCbs = null;
         code = AppOpsManager.opToSwitch(code);
         synchronized (this) {
             UidState uidState = getUidStateLocked(uid, false);
-            Op op = getOpLocked(code, uid, packageName, true);
+            Op op = getOpLocked(code, uid, packageName, true, verifyUid, isPrivileged);
             if (op != null) {
                 if (op.mode != mode) {
                     op.mode = mode;
@@ -1549,24 +1591,28 @@
     public int checkOperation(int code, int uid, String packageName) {
         final CheckOpsDelegate delegate;
         synchronized (this) {
-            if (mCheckOpsDelegate == null) {
-                return checkOperationImpl(code, uid, packageName);
-            }
             delegate = mCheckOpsDelegate;
         }
+        if (delegate == null) {
+            return checkOperationImpl(code, uid, packageName);
+        }
         return delegate.checkOperation(code, uid, packageName,
                     AppOpsService.this::checkOperationImpl);
     }
 
     private int checkOperationImpl(int code, int uid, String packageName) {
+        verifyIncomingUid(uid);
+        verifyIncomingOp(code);
+        String resolvedPackageName = resolvePackageName(uid, packageName);
+        if (resolvedPackageName == null) {
+            return AppOpsManager.MODE_IGNORED;
+        }
+        return checkOperationUnchecked(code, uid, resolvedPackageName);
+    }
+
+    private int checkOperationUnchecked(int code, int uid, String packageName) {
         synchronized (this) {
-            verifyIncomingUid(uid);
-            verifyIncomingOp(code);
-            String resolvedPackageName = resolvePackageName(uid, packageName);
-            if (resolvedPackageName == null) {
-                return AppOpsManager.MODE_IGNORED;
-            }
-            if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
+            if (isOpRestrictedLocked(uid, code, packageName)) {
                 return AppOpsManager.MODE_IGNORED;
             }
             code = AppOpsManager.opToSwitch(code);
@@ -1575,7 +1621,7 @@
                     && uidState.opModes.indexOfKey(code) >= 0) {
                 return uidState.opModes.get(code);
             }
-            Op op = getOpLocked(code, uid, resolvedPackageName, false);
+            Op op = getOpLocked(code, uid, packageName, false, true, false);
             if (op == null) {
                 return AppOpsManager.opToDefaultMode(code);
             }
@@ -1587,31 +1633,31 @@
     public int checkAudioOperation(int code, int usage, int uid, String packageName) {
         final CheckOpsDelegate delegate;
         synchronized (this) {
-            if (mCheckOpsDelegate == null) {
-                return checkAudioOperationImpl(code, usage, uid, packageName);
-            }
             delegate = mCheckOpsDelegate;
         }
+        if (delegate == null) {
+            return checkAudioOperationImpl(code, usage, uid, packageName);
+        }
         return delegate.checkAudioOperation(code, usage, uid, packageName,
                 AppOpsService.this::checkAudioOperationImpl);
     }
 
     private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
+        boolean suspended;
+        try {
+            suspended = isPackageSuspendedForUser(packageName, uid);
+        } catch (IllegalArgumentException ex) {
+            // Package not found.
+            suspended = false;
+        }
+
+        if (suspended) {
+            Slog.i(TAG, "Audio disabled for suspended package=" + packageName
+                    + " for uid=" + uid);
+            return AppOpsManager.MODE_IGNORED;
+        }
+
         synchronized (this) {
-            boolean suspended;
-            try {
-                suspended = isPackageSuspendedForUser(packageName, uid);
-            } catch (IllegalArgumentException ex) {
-                // Package not found.
-                suspended = false;
-            }
-
-            if (suspended) {
-                Slog.i(TAG, "Audio disabled for suspended package=" + packageName
-                        + " for uid=" + uid);
-                return AppOpsManager.MODE_IGNORED;
-            }
-
             final int mode = checkRestrictionLocked(code, usage, uid, packageName);
             if (mode != AppOpsManager.MODE_ALLOWED) {
                 return mode;
@@ -1714,11 +1760,11 @@
     public int noteOperation(int code, int uid, String packageName) {
         final CheckOpsDelegate delegate;
         synchronized (this) {
-            if (mCheckOpsDelegate == null) {
-                return noteOperationImpl(code, uid, packageName);
-            }
             delegate = mCheckOpsDelegate;
         }
+        if (delegate == null) {
+            return noteOperationImpl(code, uid, packageName);
+        }
         return delegate.noteOperation(code, uid, packageName,
                 AppOpsService.this::noteOperationImpl);
     }
@@ -1918,7 +1964,7 @@
         }
         ClientState client = (ClientState) token;
         synchronized (this) {
-            Op op = getOpLocked(code, uid, resolvedPackageName, true);
+            Op op = getOpLocked(code, uid, resolvedPackageName, true, true, false);
             if (op == null) {
                 return;
             }
@@ -2172,6 +2218,43 @@
         return ops;
     }
 
+    /**
+     * Get the state of all ops for a package, <b>don't verify that package belongs to uid</b>.
+     *
+     * <p>Usually callers should use {@link #getOpLocked} and not call this directly.
+     *
+     * @param uid The uid the of the package
+     * @param packageName The package name for which to get the state for
+     * @param edit Iff {@code true} create the {@link Ops} object if not yet created
+     * @param isPrivileged Whether the package is privileged or not
+     *
+     * @return The {@link Ops state} of all ops for the package
+     */
+    private @Nullable Ops getOpsRawNoVerifyLocked(int uid, @NonNull String packageName,
+            boolean edit, boolean isPrivileged) {
+        UidState uidState = getUidStateLocked(uid, edit);
+        if (uidState == null) {
+            return null;
+        }
+
+        if (uidState.pkgOps == null) {
+            if (!edit) {
+                return null;
+            }
+            uidState.pkgOps = new ArrayMap<>();
+        }
+
+        Ops ops = uidState.pkgOps.get(packageName);
+        if (ops == null) {
+            if (!edit) {
+                return null;
+            }
+            ops = new Ops(packageName, uidState, isPrivileged);
+            uidState.pkgOps.put(packageName, ops);
+        }
+        return ops;
+    }
+
     private void scheduleWriteLocked() {
         if (!mWriteScheduled) {
             mWriteScheduled = true;
@@ -2188,9 +2271,29 @@
         }
     }
 
-    private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
-        Ops ops = getOpsRawLocked(uid, packageName, edit,
-                false /* uidMismatchExpected */);
+    /**
+     * Get the state of an op for a uid.
+     *
+     * @param code The code of the op
+     * @param uid The uid the of the package
+     * @param packageName The package name for which to get the state for
+     * @param edit Iff {@code true} create the {@link Op} object if not yet created
+     * @param verifyUid Iff {@code true} check that the package belongs to the uid
+     * @param isPrivileged Whether the package is privileged or not (only used if {@code verifyUid
+     *                     == false})
+     *
+     * @return The {@link Op state} of the op
+     */
+    private @Nullable Op getOpLocked(int code, int uid, @NonNull String packageName, boolean edit,
+            boolean verifyUid, boolean isPrivileged) {
+        Ops ops;
+
+        if (verifyUid) {
+            ops = getOpsRawLocked(uid, packageName, edit, false /* uidMismatchExpected */);
+        }  else {
+            ops = getOpsRawNoVerifyLocked(uid, packageName, edit, isPrivileged);
+        }
+
         if (ops == null) {
             return null;
         }
@@ -3948,5 +4051,11 @@
                 mProfileOwners = owners;
             }
         }
+
+        @Override
+        public void setMode(int code, int uid, @NonNull String packageName, int mode,
+                boolean isPrivileged) {
+            AppOpsService.this.setMode(code, uid, packageName, mode, false, isPrivileged);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 93bdcbb..046442a 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -18,6 +18,7 @@
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -83,6 +84,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
+import com.android.internal.util.Preconditions;
 import com.android.server.location.ActivityRecognitionProxy;
 import com.android.server.location.GeocoderProxy;
 import com.android.server.location.GeofenceManager;
@@ -111,6 +113,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -541,7 +544,7 @@
         }
     }
 
-    private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
+    private void ensureFallbackFusedProviderPresentLocked(String[] pkgs) {
         PackageManager pm = mContext.getPackageManager();
         String systemPackageName = mContext.getPackageName();
         ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
@@ -646,16 +649,14 @@
         that matches the signature of at least one package on this list.
         */
         Resources resources = mContext.getResources();
-        ArrayList<String> providerPackageNames = new ArrayList<>();
         String[] pkgs = resources.getStringArray(
                 com.android.internal.R.array.config_locationProviderPackageNames);
         if (D) {
             Log.d(TAG, "certificates for location providers pulled from: " +
                     Arrays.toString(pkgs));
         }
-        if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
 
-        ensureFallbackFusedProviderPresentLocked(providerPackageNames);
+        ensureFallbackFusedProviderPresentLocked(pkgs);
 
         // bind to network provider
         LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
@@ -664,8 +665,7 @@
                 NETWORK_LOCATION_SERVICE_ACTION,
                 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
                 com.android.internal.R.string.config_networkLocationProviderPackageName,
-                com.android.internal.R.array.config_locationProviderPackageNames,
-                mLocationHandler);
+                com.android.internal.R.array.config_locationProviderPackageNames);
         if (networkProvider != null) {
             mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
             mProxyProviders.add(networkProvider);
@@ -681,8 +681,7 @@
                 FUSED_LOCATION_SERVICE_ACTION,
                 com.android.internal.R.bool.config_enableFusedLocationOverlay,
                 com.android.internal.R.string.config_fusedLocationProviderPackageName,
-                com.android.internal.R.array.config_locationProviderPackageNames,
-                mLocationHandler);
+                com.android.internal.R.array.config_locationProviderPackageNames);
         if (fusedLocationProvider != null) {
             addProviderLocked(fusedLocationProvider);
             mProxyProviders.add(fusedLocationProvider);
@@ -697,8 +696,7 @@
         mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
                 com.android.internal.R.bool.config_enableGeocoderOverlay,
                 com.android.internal.R.string.config_geocoderProviderPackageName,
-                com.android.internal.R.array.config_locationProviderPackageNames,
-                mLocationHandler);
+                com.android.internal.R.array.config_locationProviderPackageNames);
         if (mGeocodeProvider == null) {
             Slog.e(TAG, "no geocoder provider found");
         }
@@ -708,7 +706,6 @@
                 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay,
                 com.android.internal.R.string.config_geofenceProviderPackageName,
                 com.android.internal.R.array.config_locationProviderPackageNames,
-                mLocationHandler,
                 mGpsGeofenceProxy,
                 null);
         if (provider == null) {
@@ -725,7 +722,6 @@
         }
         ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
                 mContext,
-                mLocationHandler,
                 activityRecognitionHardwareIsSupported,
                 activityRecognitionHardware,
                 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
@@ -3427,6 +3423,48 @@
         }
     }
 
+    @Override
+    public PendingIntent createManageLocationPermissionIntent(String packageName,
+            String permission) {
+        Preconditions.checkNotNull(packageName);
+        Preconditions.checkArgument(permission.equals(Manifest.permission.ACCESS_FINE_LOCATION)
+                || permission.equals(Manifest.permission.ACCESS_COARSE_LOCATION)
+                || permission.equals(Manifest.permission.ACCESS_BACKGROUND_LOCATION));
+
+        int callingUid = Binder.getCallingUid();
+        long token = Binder.clearCallingIdentity();
+        try {
+            String locProvider = getNetworkProviderPackage();
+            if (locProvider == null) {
+                return null;
+            }
+
+            PackageInfo locProviderInfo;
+            try {
+                locProviderInfo = mContext.getPackageManager().getPackageInfo(
+                        locProvider, PackageManager.MATCH_DIRECT_BOOT_AUTO);
+            } catch (NameNotFoundException e) {
+                Log.e(TAG, "Could not resolve " + locProvider, e);
+                return null;
+            }
+
+            if (locProviderInfo.applicationInfo.uid != callingUid) {
+                throw new SecurityException("Only " + locProvider + " can call this API");
+            }
+
+            Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
+            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+            intent.putExtra(Intent.EXTRA_PERMISSION_NAME, permission);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            return PendingIntent.getActivity(mContext,
+                    Objects.hash(packageName, permission), intent,
+                    PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     private void log(String log) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Slog.d(TAG, log);
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index 42c836e..574f54a 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -16,8 +16,10 @@
 
 package com.android.server;
 
-import android.annotation.NonNull;
+import android.annotation.MainThread;
 import android.annotation.Nullable;
+import android.annotation.WorkerThread;
+import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -30,17 +32,21 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.Signature;
 import android.content.res.Resources;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.UserHandle;
 import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
+import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
@@ -50,268 +56,54 @@
  * Handles run-time package changes.
  */
 public class ServiceWatcher implements ServiceConnection {
+
+    private static final String TAG = "ServiceWatcher";
     private static final boolean D = false;
+
     public static final String EXTRA_SERVICE_VERSION = "serviceVersion";
     public static final String EXTRA_SERVICE_IS_MULTIUSER = "serviceIsMultiuser";
 
-    private final String mTag;
-    private final Context mContext;
-    private final PackageManager mPm;
-    private final List<HashSet<Signature>> mSignatureSets;
-    private final String mAction;
-
     /**
-     * If mServicePackageName is not null, only this package will be searched for the service that
-     * implements mAction. When null, all packages in the system that matches one of the signature
-     * in mSignatureSets are searched.
+     * The runner that runs on the binder retrieved from {@link ServiceWatcher}.
      */
-    private final String mServicePackageName;
-    private final Runnable mNewServiceWork;
-    private final Handler mHandler;
-
-    private final Object mLock = new Object();
-
-    @GuardedBy("mLock")
-    private int mCurrentUserId = UserHandle.USER_SYSTEM;
-
-    @GuardedBy("mLock")
-    private IBinder mBoundService;
-    @GuardedBy("mLock")
-    private ComponentName mBoundComponent;
-    @GuardedBy("mLock")
-    private String mBoundPackageName;
-    @GuardedBy("mLock")
-    private int mBoundVersion = Integer.MIN_VALUE;
-    @GuardedBy("mLock")
-    private int mBoundUserId = UserHandle.USER_NULL;
+    public interface BinderRunner {
+        /**
+         * Runs on the retrieved binder.
+         *
+         * @param binder the binder retrieved from the {@link ServiceWatcher}.
+         */
+        void run(IBinder binder);
+    }
 
     public static ArrayList<HashSet<Signature>> getSignatureSets(Context context,
-            List<String> initialPackageNames) {
+            String... packageNames) {
         PackageManager pm = context.getPackageManager();
-        ArrayList<HashSet<Signature>> sigSets = new ArrayList<HashSet<Signature>>();
-        for (int i = 0, size = initialPackageNames.size(); i < size; i++) {
-            String pkg = initialPackageNames.get(i);
+
+        ArrayList<HashSet<Signature>> signatureSets = new ArrayList<>(packageNames.length);
+        for (String packageName : packageNames) {
             try {
-                HashSet<Signature> set = new HashSet<Signature>();
-                Signature[] sigs = pm.getPackageInfo(pkg, PackageManager.MATCH_SYSTEM_ONLY
-                        | PackageManager.GET_SIGNATURES).signatures;
-                set.addAll(Arrays.asList(sigs));
-                sigSets.add(set);
+                Signature[] signatures = pm.getPackageInfo(packageName,
+                        PackageManager.MATCH_SYSTEM_ONLY
+                                | PackageManager.GET_SIGNATURES).signatures;
+
+                HashSet<Signature> set = new HashSet<>();
+                Collections.addAll(set, signatures);
+                signatureSets.add(set);
             } catch (NameNotFoundException e) {
-                Log.w("ServiceWatcher", pkg + " not found");
+                Log.w(TAG, packageName + " not found");
             }
         }
-        return sigSets;
+        return signatureSets;
     }
 
-    public ServiceWatcher(Context context, String logTag, String action,
-            int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId, Runnable newServiceWork,
-            Handler handler) {
-        mContext = context;
-        mTag = logTag;
-        mAction = action;
-        mPm = mContext.getPackageManager();
-        mNewServiceWork = newServiceWork;
-        mHandler = handler;
-        Resources resources = context.getResources();
-
-        // Whether to enable service overlay.
-        boolean enableOverlay = resources.getBoolean(overlaySwitchResId);
-        ArrayList<String> initialPackageNames = new ArrayList<String>();
-        if (enableOverlay) {
-            // A list of package names used to create the signatures.
-            String[] pkgs = resources.getStringArray(initialPackageNamesResId);
-            if (pkgs != null) initialPackageNames.addAll(Arrays.asList(pkgs));
-            mServicePackageName = null;
-            if (D) Log.d(mTag, "Overlay enabled, packages=" + Arrays.toString(pkgs));
-        } else {
-            // The default package name that is searched for service implementation when overlay is
-            // disabled.
-            String servicePackageName = resources.getString(defaultServicePackageNameResId);
-            if (servicePackageName != null) initialPackageNames.add(servicePackageName);
-            mServicePackageName = servicePackageName;
-            if (D) Log.d(mTag, "Overlay disabled, default package=" + servicePackageName);
-        }
-        mSignatureSets = getSignatureSets(context, initialPackageNames);
-    }
-
-    /**
-     * Start this watcher, including binding to the current best match and
-     * re-binding to any better matches down the road.
-     * <p>
-     * Note that if there are no matching encryption-aware services, we may not
-     * bind to a real service until after the current user is unlocked.
-     *
-     * @returns {@code true} if a potential service implementation was found.
-     */
-    public boolean start() {
-        if (isServiceMissing()) return false;
-
-        synchronized (mLock) {
-            bindBestPackageLocked(mServicePackageName, false);
-        }
-
-        // listen for user change
-        IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
-        intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
-        mContext.registerReceiverAsUser(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                final String action = intent.getAction();
-                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
-                        UserHandle.USER_NULL);
-                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                    switchUser(userId);
-                } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
-                    unlockUser(userId);
-                }
-            }
-        }, UserHandle.ALL, intentFilter, null, mHandler);
-
-        // listen for relevant package changes if service overlay is enabled.
-        if (mServicePackageName == null) {
-            mPackageMonitor.register(mContext, null, UserHandle.ALL, true);
-        }
-
-        return true;
-    }
-
-    /**
-     * Check if any instance of this service is present on the device,
-     * regardless of it being encryption-aware or not.
-     */
-    private boolean isServiceMissing() {
-        final Intent intent = new Intent(mAction);
-        final int flags = PackageManager.MATCH_DIRECT_BOOT_AWARE
-                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
-        return mPm.queryIntentServicesAsUser(intent, flags, mCurrentUserId).isEmpty();
-    }
-
-    /**
-     * Searches and binds to the best package, or do nothing if the best package
-     * is already bound, unless force rebinding is requested.
-     *
-     * @param justCheckThisPackage Only consider this package, or consider all
-     *            packages if it is {@code null}.
-     * @param forceRebind Force a rebinding to the best package if it's already
-     *            bound.
-     * @returns {@code true} if a valid package was found to bind to.
-     */
-    @GuardedBy("mLock")
-    private boolean bindBestPackageLocked(String justCheckThisPackage, boolean forceRebind) {
-        Intent intent = new Intent(mAction);
-        if (justCheckThisPackage != null) {
-            intent.setPackage(justCheckThisPackage);
-        }
-        final List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(intent,
-                PackageManager.GET_META_DATA | PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
-                mCurrentUserId);
-        int bestVersion = Integer.MIN_VALUE;
-        ComponentName bestComponent = null;
-        boolean bestIsMultiuser = false;
-        if (rInfos != null) {
-            for (ResolveInfo rInfo : rInfos) {
-                final ComponentName component = rInfo.serviceInfo.getComponentName();
-                final String packageName = component.getPackageName();
-
-                // check signature
-                try {
-                    PackageInfo pInfo;
-                    pInfo = mPm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES
-                            | PackageManager.MATCH_DEBUG_TRIAGED_MISSING);
-                    if (!isSignatureMatch(pInfo.signatures)) {
-                        Log.w(mTag, packageName + " resolves service " + mAction
-                                + ", but has wrong signature, ignoring");
-                        continue;
-                    }
-                } catch (NameNotFoundException e) {
-                    Log.wtf(mTag, e);
-                    continue;
-                }
-
-                // check metadata
-                int version = Integer.MIN_VALUE;
-                boolean isMultiuser = false;
-                if (rInfo.serviceInfo.metaData != null) {
-                    version = rInfo.serviceInfo.metaData.getInt(
-                            EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
-                    isMultiuser = rInfo.serviceInfo.metaData.getBoolean(EXTRA_SERVICE_IS_MULTIUSER);
-                }
-
-                if (version > bestVersion) {
-                    bestVersion = version;
-                    bestComponent = component;
-                    bestIsMultiuser = isMultiuser;
-                }
-            }
-
-            if (D) {
-                Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
-                        (justCheckThisPackage == null ? ""
-                                : "(" + justCheckThisPackage + ") "), rInfos.size(),
-                        (bestComponent == null ? "no new best component"
-                                : "new best component: " + bestComponent)));
-            }
-        } else {
-            if (D) Log.d(mTag, "Unable to query intent services for action: " + mAction);
-        }
-
-        if (bestComponent == null) {
-            Slog.w(mTag, "Odd, no component found for service " + mAction);
-            unbindLocked();
-            return false;
-        }
-
-        final int userId = bestIsMultiuser ? UserHandle.USER_SYSTEM : mCurrentUserId;
-        final boolean alreadyBound = Objects.equals(bestComponent, mBoundComponent)
-                && bestVersion == mBoundVersion && userId == mBoundUserId;
-        if (forceRebind || !alreadyBound) {
-            unbindLocked();
-            bindToPackageLocked(bestComponent, bestVersion, userId);
-        }
-        return true;
-    }
-
-    @GuardedBy("mLock")
-    private void unbindLocked() {
-        ComponentName component;
-        component = mBoundComponent;
-        mBoundComponent = null;
-        mBoundPackageName = null;
-        mBoundVersion = Integer.MIN_VALUE;
-        mBoundUserId = UserHandle.USER_NULL;
-        if (component != null) {
-            if (D) Log.d(mTag, "unbinding " + component);
-            mBoundService = null;
-            mContext.unbindService(this);
-        }
-    }
-
-    @GuardedBy("mLock")
-    private void bindToPackageLocked(ComponentName component, int version, int userId) {
-        Intent intent = new Intent(mAction);
-        intent.setComponent(component);
-        mBoundComponent = component;
-        mBoundPackageName = component.getPackageName();
-        mBoundVersion = version;
-        mBoundUserId = userId;
-        if (D) Log.d(mTag, "binding " + component + " (v" + version + ") (u" + userId + ")");
-        mContext.bindServiceAsUser(intent, this,
-                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
-                new UserHandle(userId));
-    }
-
+    /** Checks if signatures match. */
     public static boolean isSignatureMatch(Signature[] signatures,
             List<HashSet<Signature>> sigSets) {
         if (signatures == null) return false;
 
         // build hashset of input to test against
-        HashSet<Signature> inputSet = new HashSet<Signature>();
-        for (Signature s : signatures) {
-            inputSet.add(s);
-        }
+        HashSet<Signature> inputSet = new HashSet<>();
+        Collections.addAll(inputSet, signatures);
 
         // test input against each of the signature sets
         for (HashSet<Signature> referenceSet : sigSets) {
@@ -322,124 +114,318 @@
         return false;
     }
 
-    private boolean isSignatureMatch(Signature[] signatures) {
-        return isSignatureMatch(signatures, mSignatureSets);
+    private final Context mContext;
+    private final String mTag;
+    private final String mAction;
+    private final String mServicePackageName;
+    private final List<HashSet<Signature>> mSignatureSets;
+
+    private final Handler mHandler;
+
+    // this lock is held to ensure the service binder is not exposed (via runOnBinder) until after
+    // the new service initialization work has completed
+    private final Object mBindLock = new Object();
+
+    // read/write from handler thread
+    private int mCurrentUserId;
+
+    // read from any thread, write from handler thread
+    private volatile ComponentName mBestComponent;
+    private volatile int mBestVersion;
+    private volatile int mBestUserId;
+    private volatile IBinder mBestService;
+
+    public ServiceWatcher(Context context, String logTag, String action,
+            int overlaySwitchResId, int defaultServicePackageNameResId,
+            int initialPackageNamesResId, Handler handler) {
+        Resources resources = context.getResources();
+
+        mContext = context;
+        mTag = logTag;
+        mAction = action;
+
+        boolean enableOverlay = resources.getBoolean(overlaySwitchResId);
+        if (enableOverlay) {
+            String[] pkgs = resources.getStringArray(initialPackageNamesResId);
+            mServicePackageName = null;
+            mSignatureSets = getSignatureSets(context, pkgs);
+            if (D) Log.d(mTag, "Overlay enabled, packages=" + Arrays.toString(pkgs));
+        } else {
+            mServicePackageName = resources.getString(defaultServicePackageNameResId);
+            mSignatureSets = getSignatureSets(context, mServicePackageName);
+            if (D) Log.d(mTag, "Overlay disabled, default package=" + mServicePackageName);
+        }
+
+        mHandler = handler;
+
+        mBestComponent = null;
+        mBestVersion = Integer.MIN_VALUE;
+        mBestUserId = UserHandle.USER_NULL;
+
+        mBestService = null;
     }
 
-    private final PackageMonitor mPackageMonitor = new PackageMonitor() {
-        /**
-         * Called when package has been reinstalled
-         */
-        @Override
-        public void onPackageUpdateFinished(String packageName, int uid) {
-            synchronized (mLock) {
-                final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
-                bindBestPackageLocked(null, forceRebind);
-            }
-        }
+    // called on handler thread
+    @GuardedBy("mBindLock")
+    protected void onBind() {
 
-        @Override
-        public void onPackageAdded(String packageName, int uid) {
-            synchronized (mLock) {
-                final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
-                bindBestPackageLocked(null, forceRebind);
-            }
-        }
+    }
 
-        @Override
-        public void onPackageRemoved(String packageName, int uid) {
-            synchronized (mLock) {
-                final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
-                bindBestPackageLocked(null, forceRebind);
-            }
-        }
+    // called on handler thread
+    @GuardedBy("mBindLock")
+    protected void onUnbind() {
 
-        @Override
-        public boolean onPackageChanged(String packageName, int uid, String[] components) {
-            synchronized (mLock) {
-                final boolean forceRebind = Objects.equals(packageName, mBoundPackageName);
-                bindBestPackageLocked(null, forceRebind);
-            }
-            return super.onPackageChanged(packageName, uid, components);
-        }
-    };
+    }
 
-    @Override
-    public void onServiceConnected(ComponentName component, IBinder binder) {
-        synchronized (mLock) {
-            if (component.equals(mBoundComponent)) {
-                if (D) Log.d(mTag, component + " connected");
-                mBoundService = binder;
-                if (mHandler !=null && mNewServiceWork != null) {
-                    mHandler.post(mNewServiceWork);
+    /**
+     * Start this watcher, including binding to the current best match and
+     * re-binding to any better matches down the road.
+     * <p>
+     * Note that if there are no matching encryption-aware services, we may not
+     * bind to a real service until after the current user is unlocked.
+     *
+     * @return {@code true} if a potential service implementation was found.
+     */
+    public final boolean start() {
+        // if we have to return false, do it before registering anything
+        if (isServiceMissing()) return false;
+
+        // listen for relevant package changes if service overlay is enabled on handler
+        if (mServicePackageName == null) {
+            new PackageMonitor() {
+                @Override
+                public void onPackageUpdateFinished(String packageName, int uid) {
+                    bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
                 }
-            } else {
-                Log.w(mTag, "unexpected onServiceConnected: " + component);
+
+                @Override
+                public void onPackageAdded(String packageName, int uid) {
+                    bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
+                }
+
+                @Override
+                public void onPackageRemoved(String packageName, int uid) {
+                        bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
+                }
+
+                @Override
+                public boolean onPackageChanged(String packageName, int uid, String[] components) {
+                        bindBestPackage(Objects.equals(packageName, getCurrentPackageName()));
+                    return super.onPackageChanged(packageName, uid, components);
+                }
+            }.register(mContext, UserHandle.ALL, true, mHandler);
+        }
+
+        // listen for user change on handler
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+        intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
+        mContext.registerReceiverAsUser(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                final String action = intent.getAction();
+                final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
+                        UserHandle.USER_NULL);
+                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                    mCurrentUserId = userId;
+                    bindBestPackage(false);
+                } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
+                    if (userId == mCurrentUserId) {
+                        bindBestPackage(false);
+                    }
+                }
+            }
+        }, UserHandle.ALL, intentFilter, null, mHandler);
+
+        mCurrentUserId = ActivityManager.getCurrentUser();
+
+        mHandler.post(() -> bindBestPackage(false));
+        return true;
+    }
+
+    /** Returns thje name of the currently connected package or null. */
+    @Nullable
+    public String getCurrentPackageName() {
+        ComponentName bestComponent = mBestComponent;
+        return bestComponent == null ? null : bestComponent.getPackageName();
+    }
+
+    public int getCurrentPackageVersion() {
+        return mBestVersion;
+    }
+
+    /**
+     * Runs the given BinderRunner if currently connected. Returns true if it was run, and false
+     * otherwise. All invocations to runOnBinder are run serially.
+     */
+    public final void runOnBinder(BinderRunner runner) {
+        synchronized (mBindLock) {
+            IBinder service = mBestService;
+            if (service != null) {
+                try {
+                    runner.run(service);
+                } catch (Exception e) {
+                    // remote exceptions cannot be allowed to crash system server
+                    Log.e(TAG, "exception while while running " + runner + " on " + service
+                            + " from " + mBestComponent.toShortString(), e);
+                }
             }
         }
     }
 
+    private boolean isServiceMissing() {
+        return mContext.getPackageManager().queryIntentServicesAsUser(new Intent(mAction),
+                PackageManager.MATCH_DIRECT_BOOT_AWARE
+                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                UserHandle.USER_SYSTEM).isEmpty();
+    }
+
+    /**
+     * Searches and binds to the best package, or do nothing if the best package
+     * is already bound, unless force rebinding is requested.
+     *
+     * @param forceRebind          Force a rebinding to the best package if it's already
+     *                             bound.
+     */
+    @WorkerThread
+    private void bindBestPackage(boolean forceRebind) {
+        Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
+
+        Intent intent = new Intent(mAction);
+        if (mServicePackageName != null) {
+            intent.setPackage(mServicePackageName);
+        }
+
+        List<ResolveInfo> rInfos = mContext.getPackageManager().queryIntentServicesAsUser(intent,
+                PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AUTO,
+                mCurrentUserId);
+        if (rInfos == null) {
+            rInfos = Collections.emptyList();
+        }
+
+        ComponentName bestComponent = null;
+        int bestVersion = Integer.MIN_VALUE;
+        boolean bestIsMultiuser = false;
+
+        for (ResolveInfo rInfo : rInfos) {
+            ComponentName component = rInfo.serviceInfo.getComponentName();
+            String packageName = component.getPackageName();
+
+            // check signature
+            try {
+                PackageInfo pInfo = mContext.getPackageManager().getPackageInfo(packageName,
+                        PackageManager.GET_SIGNATURES
+                                | PackageManager.MATCH_DIRECT_BOOT_AUTO);
+                if (!isSignatureMatch(pInfo.signatures, mSignatureSets)) {
+                    Log.w(mTag, packageName + " resolves service " + mAction
+                            + ", but has wrong signature, ignoring");
+                    continue;
+                }
+            } catch (NameNotFoundException e) {
+                Log.wtf(mTag, e);
+                continue;
+            }
+
+            // check metadata
+            Bundle metadata = rInfo.serviceInfo.metaData;
+            int version = Integer.MIN_VALUE;
+            boolean isMultiuser = false;
+            if (metadata != null) {
+                version = metadata.getInt(EXTRA_SERVICE_VERSION, Integer.MIN_VALUE);
+                isMultiuser = metadata.getBoolean(EXTRA_SERVICE_IS_MULTIUSER, false);
+            }
+
+            if (version > bestVersion) {
+                bestComponent = component;
+                bestVersion = version;
+                bestIsMultiuser = isMultiuser;
+            }
+        }
+
+        if (D) {
+            Log.d(mTag, String.format("bindBestPackage for %s : %s found %d, %s", mAction,
+                    (mServicePackageName == null ? ""
+                            : "(" + mServicePackageName + ") "), rInfos.size(),
+                    (bestComponent == null ? "no new best component"
+                            : "new best component: " + bestComponent)));
+        }
+
+        if (bestComponent == null) {
+            Slog.w(mTag, "Odd, no component found for service " + mAction);
+            unbind();
+            return;
+        }
+
+        int userId = bestIsMultiuser ? UserHandle.USER_SYSTEM : mCurrentUserId;
+        boolean alreadyBound = Objects.equals(bestComponent, mBestComponent)
+                && bestVersion == mBestVersion && userId == mBestUserId;
+        if (forceRebind || !alreadyBound) {
+            unbind();
+            bind(bestComponent, bestVersion, userId);
+        }
+    }
+
+    @WorkerThread
+    private void bind(ComponentName component, int version, int userId) {
+        Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
+
+        Intent intent = new Intent(mAction);
+        intent.setComponent(component);
+
+        mBestComponent = component;
+        mBestVersion = version;
+        mBestUserId = userId;
+
+        if (D) Log.d(mTag, "binding " + component + " (v" + version + ") (u" + userId + ")");
+        mContext.bindServiceAsUser(intent, this,
+                Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_VISIBLE,
+                UserHandle.of(userId));
+    }
+
+    @WorkerThread
+    private void unbind() {
+        Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
+
+        if (mBestComponent != null) {
+            if (D) Log.d(mTag, "unbinding " + mBestComponent);
+            mContext.unbindService(this);
+        }
+
+        mBestComponent = null;
+        mBestVersion = Integer.MIN_VALUE;
+        mBestUserId = UserHandle.USER_NULL;
+    }
+
+    @MainThread
     @Override
-    public void onServiceDisconnected(ComponentName component) {
-        synchronized (mLock) {
+    public final void onServiceConnected(ComponentName component, IBinder binder) {
+        mHandler.post(() -> {
+            if (D) Log.d(mTag, component + " connected");
+
+            // hold the lock so that mBestService cannot be used by runOnBinder until complete
+            synchronized (mBindLock) {
+                mBestService = binder;
+                onBind();
+            }
+        });
+    }
+
+    @MainThread
+    @Override
+    public final void onServiceDisconnected(ComponentName component) {
+        mHandler.post(() -> {
             if (D) Log.d(mTag, component + " disconnected");
 
-            if (component.equals(mBoundComponent)) {
-                mBoundService = null;
+            mBestService = null;
+            synchronized (mBindLock) {
+                onUnbind();
             }
-        }
+        });
     }
 
-    public @Nullable String getBestPackageName() {
-        synchronized (mLock) {
-            return mBoundPackageName;
-        }
-    }
-
-    public int getBestVersion() {
-        synchronized (mLock) {
-            return mBoundVersion;
-        }
-    }
-
-    /**
-     * The runner that runs on the binder retrieved from {@link ServiceWatcher}.
-     */
-    public interface BinderRunner {
-        /**
-         * Runs on the retrieved binder.
-         * @param binder the binder retrieved from the {@link ServiceWatcher}.
-         */
-        public void run(@NonNull IBinder binder);
-    }
-
-    /**
-     * Retrieves the binder from {@link ServiceWatcher} and runs it.
-     * @return whether a valid service exists.
-     */
-    public boolean runOnBinder(@NonNull BinderRunner runner) {
-        synchronized (mLock) {
-            if (mBoundService == null) {
-                return false;
-            } else {
-                runner.run(mBoundService);
-                return true;
-            }
-        }
-    }
-
-    public void switchUser(int userId) {
-        synchronized (mLock) {
-            mCurrentUserId = userId;
-            bindBestPackageLocked(mServicePackageName, false);
-        }
-    }
-
-    public void unlockUser(int userId) {
-        synchronized (mLock) {
-            if (userId == mCurrentUserId) {
-                bindBestPackageLocked(mServicePackageName, false);
-            }
-        }
+    @Override
+    public String toString() {
+        ComponentName bestComponent = mBestComponent;
+        return bestComponent == null ? "null" : bestComponent.toShortString() + "@" + mBestVersion;
     }
 }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 54c7d17..923ac00 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -38,6 +38,7 @@
 import android.Manifest;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
 import android.app.KeyguardManager;
@@ -185,8 +186,6 @@
     private static final boolean ENABLE_ISOLATED_STORAGE = SystemProperties
             .getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false);
 
-    private static final String SHARED_SANDBOX_ID_PREFIX = "shared:";
-
     public static class Lifecycle extends SystemService {
         private StorageManagerService mStorageManagerService;
 
@@ -450,6 +449,7 @@
 
     private PackageManagerInternal mPmInternal;
     private UserManagerInternal mUmInternal;
+    private ActivityManagerInternal mAmInternal;
 
     private final Callbacks mCallbacks;
     private final LockPatternUtils mLockPatternUtils;
@@ -1233,6 +1233,9 @@
         } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
             mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
 
+        } else if (vol.type == VolumeInfo.TYPE_STUB) {
+            vol.mountUserId = mCurrentUserId;
+            mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
         } else {
             Slog.d(TAG, "Skipping automatic mounting of " + vol);
         }
@@ -1243,6 +1246,7 @@
             case VolumeInfo.TYPE_PRIVATE:
             case VolumeInfo.TYPE_PUBLIC:
             case VolumeInfo.TYPE_EMULATED:
+            case VolumeInfo.TYPE_STUB:
                 break;
             default:
                 return false;
@@ -1319,7 +1323,8 @@
             }
         }
 
-        if (vol.type == VolumeInfo.TYPE_PUBLIC && vol.state == VolumeInfo.STATE_EJECTING) {
+        if ((vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_STUB)
+                    && vol.state == VolumeInfo.STATE_EJECTING) {
             // TODO: this should eventually be handled by new ObbVolume state changes
             /*
              * Some OBBs might have been unmounted when this volume was
@@ -1401,7 +1406,8 @@
         }
 
         boolean isTypeRestricted = false;
-        if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
+        if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE
+                || vol.type == VolumeInfo.TYPE_STUB) {
             isTypeRestricted = userManager
                     .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
                     Binder.getCallingUserHandle());
@@ -1439,6 +1445,7 @@
 
         mPmInternal = LocalServices.getService(PackageManagerInternal.class);
         mUmInternal = LocalServices.getService(UserManagerInternal.class);
+        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
 
         HandlerThread hthread = new HandlerThread(TAG);
         hthread.start();
@@ -1492,7 +1499,8 @@
     }
 
     private static String getSandboxId(String packageName, String sharedUserId) {
-        return sharedUserId == null ? packageName : SHARED_SANDBOX_ID_PREFIX + sharedUserId;
+        return sharedUserId == null
+                ? packageName : StorageManager.SHARED_SANDBOX_PREFIX + sharedUserId;
     }
 
     private void connect() {
@@ -2097,6 +2105,26 @@
                 Binder.restoreCallingIdentity(token);
             }
         }
+
+        if ((mask & StorageManager.DEBUG_ISOLATED_STORAGE) != 0) {
+            final boolean enabled = (flags & StorageManager.DEBUG_ISOLATED_STORAGE) != 0;
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE,
+                        Boolean.toString(enabled));
+
+                // Some of the storage related permissions get fiddled with during
+                // package scanning. So, delete the package cache to force PackageManagerService
+                // to do package scanning.
+                FileUtils.deleteContents(Environment.getPackageCacheDirectory());
+
+                // Perform hard reboot to kick policy into place
+                mContext.getSystemService(PowerManager.class).reboot(null);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
     }
 
     @Override
@@ -2811,6 +2839,7 @@
                 final VolumeInfo vol = mVolumes.valueAt(i);
                 switch (vol.getType()) {
                     case VolumeInfo.TYPE_PUBLIC:
+                    case VolumeInfo.TYPE_STUB:
                     case VolumeInfo.TYPE_EMULATED:
                         break;
                     default:
@@ -3040,25 +3069,25 @@
             "(?i)^(/storage/[^/]+/(?:[0-9]+/)?)(.*)");
 
     @Override
-    public String translateAppToSystem(String path, String packageName, int userId) {
-        return translateInternal(path, packageName, userId, true);
+    public String translateAppToSystem(String path, int pid, int uid) {
+        return translateInternal(path, pid, uid, true);
     }
 
     @Override
-    public String translateSystemToApp(String path, String packageName, int userId) {
-        return translateInternal(path, packageName, userId, false);
+    public String translateSystemToApp(String path, int pid, int uid) {
+        return translateInternal(path, pid, uid, false);
     }
 
-    private String translateInternal(String path, String packageName, int userId,
-            boolean toSystem) {
+    private String translateInternal(String path, int pid, int uid, boolean toSystem) {
         if (!ENABLE_ISOLATED_STORAGE) return path;
 
         if (path.contains("/../")) {
             throw new SecurityException("Shady looking path " + path);
         }
 
-        final String sharedUserId = mPmInternal.getSharedUserIdForPackage(packageName);
-        final String sandboxId = getSandboxId(packageName, sharedUserId);
+        if (!mAmInternal.isAppStorageSandboxed(pid, uid)) {
+            return path;
+        }
 
         final Matcher m = PATTERN_TRANSLATE.matcher(path);
         if (m.matches()) {
@@ -3067,9 +3096,7 @@
 
             // Does path belong to any packages belonging to this UID? If so,
             // they get to go straight through to legacy paths.
-            final String[] pkgs = (sharedUserId == null)
-                    ? new String[] {packageName}
-                    : mPmInternal.getPackagesForSharedUserId(sharedUserId, userId);
+            final String[] pkgs = mContext.getPackageManager().getPackagesForUid(uid);
             for (String pkg : pkgs) {
                 if (devicePath.startsWith("Android/data/" + pkg + "/") ||
                         devicePath.startsWith("Android/media/" + pkg + "/") ||
@@ -3078,6 +3105,9 @@
                 }
             }
 
+            final String sharedUserId = mPmInternal.getSharedUserIdForPackage(pkgs[0]);
+            final String sandboxId = getSandboxId(pkgs[0], sharedUserId);
+
             if (toSystem) {
                 // Everything else goes into sandbox.
                 return device + "Android/sandbox/" + sandboxId + "/" + devicePath;
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 65f3c03..f0b472b 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -47,7 +47,6 @@
 import android.telephony.SignalStrength;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.VoLteServiceState;
 import android.util.LocalLog;
 import android.util.StatsLog;
 
@@ -196,7 +195,7 @@
 
     private ArrayList<List<PhysicalChannelConfig>> mPhysicalChannelConfigs;
 
-    private VoLteServiceState mVoLteServiceState = new VoLteServiceState();
+    private int[] mSrvccState;
 
     private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
@@ -230,8 +229,7 @@
 
     static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
-                PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR |
-                PhoneStateListener.LISTEN_VOLTE_STATE;
+                PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
 
     static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
@@ -356,6 +354,7 @@
         mCallForwarding = new boolean[numPhones];
         mCellLocation = new Bundle[numPhones];
         mCellInfo = new ArrayList<List<CellInfo>>();
+        mSrvccState = new int[numPhones];
         mPhysicalChannelConfigs = new ArrayList<List<PhysicalChannelConfig>>();
         for (int i = 0; i < numPhones; i++) {
             mCallState[i] =  TelephonyManager.CALL_STATE_IDLE;
@@ -371,6 +370,7 @@
             mCallForwarding[i] =  false;
             mCellLocation[i] = new Bundle();
             mCellInfo.add(i, null);
+            mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
             mPhysicalChannelConfigs.add(i, new ArrayList<PhysicalChannelConfig>());
         }
 
@@ -772,6 +772,13 @@
                             remove(r.binder);
                         }
                     }
+                    if ((events & PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) != 0) {
+                        try {
+                            r.callback.onSrvccStateChanged(mSrvccState[phoneId]);
+                        } catch (RemoteException ex) {
+                            remove(r.binder);
+                        }
+                    }
                 }
             }
         } else {
@@ -1522,19 +1529,30 @@
                 TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, reason, null, failCause);
     }
 
-    public void notifyVoLteServiceStateChanged(VoLteServiceState lteState) {
-        if (!checkNotifyPermission("notifyVoLteServiceStateChanged()")) {
+    @Override
+    public void notifySrvccStateChanged(int subId, @TelephonyManager.SrvccState int state) {
+        if (!checkNotifyPermission("notifySrvccStateChanged()")) {
             return;
         }
+        if (VDBG) {
+            log("notifySrvccStateChanged: subId=" + subId + " srvccState=" + state);
+        }
+        int phoneId = SubscriptionManager.getPhoneId(subId);
         synchronized (mRecords) {
-            mVoLteServiceState = lteState;
-            for (Record r : mRecords) {
-                if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_VOLTE_STATE)) {
-                    try {
-                        r.callback.onVoLteServiceStateChanged(
-                                new VoLteServiceState(mVoLteServiceState));
-                    } catch (RemoteException ex) {
-                        mRemoveList.add(r.binder);
+            if (validatePhoneId(phoneId)) {
+                mSrvccState[phoneId]  = state;
+                for (Record r : mRecords) {
+                    if (r.matchPhoneStateListenerEvent(
+                            PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) &&
+                            idMatch(r.subId, subId, phoneId)) {
+                        try {
+                            if (DBG_LOC) {
+                                log("notifySrvccStateChanged: mSrvccState=" + state + " r=" + r);
+                            }
+                            r.callback.onSrvccStateChanged(state);
+                        } catch (RemoteException ex) {
+                            mRemoveList.add(r.binder);
+                        }
                     }
                 }
             }
@@ -1679,7 +1697,7 @@
             pw.println("mRingingCallState=" + mRingingCallState);
             pw.println("mForegroundCallState=" + mForegroundCallState);
             pw.println("mBackgroundCallState=" + mBackgroundCallState);
-            pw.println("mVoLteServiceState=" + mVoLteServiceState);
+            pw.println("mSrvccState=" + mSrvccState);
             pw.println("mPhoneCapability=" + mPhoneCapability);
             pw.println("mPreferredDataSubId=" + mPreferredDataSubId);
             pw.println("mRadioPowerState=" + mRadioPowerState);
@@ -1930,6 +1948,12 @@
                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
         }
 
+        if ((events & PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) != 0) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
+        }
+
+
         return true;
     }
 
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 5538e72..cb9d4c6 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -300,11 +300,10 @@
 
         @Override
         public void setNightMode(int mode) {
-            if (isNightModeLocked() &&  (getContext().checkCallingOrSelfPermission(
+            if (isNightModeLocked() && (getContext().checkCallingOrSelfPermission(
                     android.Manifest.permission.MODIFY_DAY_NIGHT_MODE)
                     != PackageManager.PERMISSION_GRANTED)) {
-                Slog.e(TAG,
-                        "Night mode locked, requires MODIFY_DAY_NIGHT_MODE permission");
+                Slog.e(TAG, "Night mode locked, requires MODIFY_DAY_NIGHT_MODE permission");
                 return;
             }
             switch (mode) {
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 793a177..bbb1d13 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -1193,6 +1193,8 @@
                 if (i >= timings.length) {
                     if (repeatIndex >= 0) {
                         i = repeatIndex;
+                        // prevent infinite loop
+                        repeatIndex = -1;
                     } else {
                         break;
                     }
@@ -1258,8 +1260,6 @@
 
     private final class VibratorShellCommand extends ShellCommand {
 
-        private static final long MAX_VIBRATION_MS = 200;
-
         private final IBinder mToken;
 
         private VibratorShellCommand(IBinder token) {
@@ -1270,8 +1270,13 @@
         public int onCommand(String cmd) {
             if ("vibrate".equals(cmd)) {
                 return runVibrate();
+            } else if ("waveform".equals(cmd)) {
+                return runWaveform();
             } else if ("prebaked".equals(cmd)) {
                 return runPrebaked();
+            } else if ("cancel".equals(cmd)) {
+                cancelVibrate(mToken);
+                return 0;
             }
             return handleDefaultCommands(cmd);
         }
@@ -1303,9 +1308,6 @@
                 }
 
                 final long duration = Long.parseLong(getNextArgRequired());
-                if (duration > MAX_VIBRATION_MS) {
-                    throw new IllegalArgumentException("maximum duration is " + MAX_VIBRATION_MS);
-                }
                 String description = getNextArg();
                 if (description == null) {
                     description = "Shell command";
@@ -1321,6 +1323,62 @@
             }
         }
 
+        private int runWaveform() {
+            Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runWaveform");
+            try {
+                if (checkDoNotDisturb()) {
+                    return 0;
+                }
+
+                String description = "Shell command";
+                int repeat = -1;
+                ArrayList<Integer> amplitudesList = null;
+
+                String opt;
+                while ((opt = getNextOption()) != null) {
+                    switch (opt) {
+                        case "-d":
+                            description = getNextArgRequired();
+                            break;
+                        case "-r":
+                            repeat = Integer.parseInt(getNextArgRequired());
+                            break;
+                        case "-a":
+                            if (amplitudesList == null) {
+                                amplitudesList = new ArrayList<Integer>();
+                            }
+                            break;
+                    }
+                }
+
+                ArrayList<Long> timingsList = new ArrayList<Long>();
+
+                String arg;
+                while ((arg = getNextArg()) != null) {
+                    if (amplitudesList != null && amplitudesList.size() < timingsList.size()) {
+                        amplitudesList.add(Integer.parseInt(arg));
+                    } else {
+                        timingsList.add(Long.parseLong(arg));
+                    }
+                }
+
+                VibrationEffect effect;
+                long[] timings = timingsList.stream().mapToLong(Long::longValue).toArray();
+                if (amplitudesList == null) {
+                    effect = VibrationEffect.createWaveform(timings, repeat);
+                } else {
+                    int[] amplitudes =
+                            amplitudesList.stream().mapToInt(Integer::intValue).toArray();
+                    effect = VibrationEffect.createWaveform(timings, amplitudes, repeat);
+                }
+                vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN,
+                        "Shell Command", mToken);
+                return 0;
+            } finally {
+                Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+            }
+        }
+
         private int runPrebaked() {
             Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runPrebaked");
             try {
@@ -1355,9 +1413,19 @@
                 pw.println("  vibrate duration [description]");
                 pw.println("    Vibrates for duration milliseconds; ignored when device is on DND ");
                 pw.println("    (Do Not Disturb) mode.");
+                pw.println("  waveform [-d description] [-r index] [-a] duration [amplitude] ...");
+                pw.println("    Vibrates for durations and amplitudes in list;");
+                pw.println("    ignored when device is on DND (Do Not Disturb) mode.");
+                pw.println("    If -r is provided, the waveform loops back to the specified");
+                pw.println("    index (e.g. 0 loops from the beginning)");
+                pw.println("    If -a is provided, the command accepts duration-amplitude pairs;");
+                pw.println("    otherwise, it accepts durations only and alternates off/on");
+                pw.println("    Duration is in milliseconds; amplitude is a scale of 1-255.");
                 pw.println("  prebaked effect-id [description]");
                 pw.println("    Vibrates with prebaked effect; ignored when device is on DND ");
                 pw.println("    (Do Not Disturb) mode.");
+                pw.println("  cancel");
+                pw.println("    Cancels any active vibration");
                 pw.println("");
             }
         }
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 9cc550d..d1b56e9 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -43,6 +43,7 @@
 
 import com.android.internal.os.ZygoteConnectionConstants;
 import com.android.server.am.ActivityManagerService;
+import com.android.server.wm.SurfaceAnimationThread;
 
 import java.io.File;
 import java.io.FileWriter;
@@ -280,6 +281,12 @@
         // And the display thread.
         mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(),
                 "display thread", DEFAULT_TIMEOUT));
+        // And the animation thread.
+        mHandlerCheckers.add(new HandlerChecker(AnimationThread.getHandler(),
+                "animation thread", DEFAULT_TIMEOUT));
+        // And the surface animation thread.
+        mHandlerCheckers.add(new HandlerChecker(SurfaceAnimationThread.getHandler(),
+                "surface animation thread", DEFAULT_TIMEOUT));
 
         // Initialize monitor for Binder threads.
         addMonitor(new BinderThreadMonitor());
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 2d3912b..c660cc6 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -17,40 +17,69 @@
 package com.android.server.am;
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static com.android.server.am.ActivityManagerDebugConfig.*;
 
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Predicate;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKGROUND_CHECK;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOREGROUND_SERVICE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE_EXECUTING;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SERVICE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SERVICE_EXECUTING;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
+import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityThread;
+import android.app.AppGlobals;
 import android.app.AppOpsManager;
+import android.app.IApplicationThread;
+import android.app.IServiceConnection;
+import android.app.Notification;
 import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
 import android.app.ServiceStartArgs;
+import android.content.ComponentName;
 import android.content.ComponentName.WithComponentName;
+import android.content.Context;
 import android.content.IIntentSender;
+import android.content.Intent;
 import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.DeadObjectException;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
 import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.TransactionTooLargeException;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.EventLog;
+import android.util.PrintWriterPrinter;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.StatsLog;
+import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+import android.webkit.WebViewZygote;
 
 import com.android.internal.R;
 import com.android.internal.app.procstats.ServiceState;
@@ -64,39 +93,20 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.am.ActivityManagerService.ItemMatcher;
-
-import android.app.ActivityManager;
-import android.app.AppGlobals;
-import android.app.IApplicationThread;
-import android.app.IServiceConnection;
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.util.EventLog;
-import android.util.PrintWriterPrinter;
-import android.util.Slog;
-import android.util.StatsLog;
-import android.util.SparseArray;
-import android.util.TimeUtils;
-import android.util.proto.ProtoOutputStream;
-import android.webkit.WebViewZygote;
 import com.android.server.uri.NeededUriGrants;
 import com.android.server.wm.ActivityServiceConnectionsHolder;
 
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+
 public final class ActiveServices {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM;
     private static final String TAG_MU = TAG + POSTFIX_MU;
@@ -182,10 +192,10 @@
         public void stopForegroundServicesForUidPackage(final int uid, final String packageName) {
             synchronized (mAm) {
                 final ServiceMap smap = getServiceMapLocked(UserHandle.getUserId(uid));
-                final int N = smap.mServicesByName.size();
+                final int N = smap.mServicesByInstanceName.size();
                 final ArrayList<ServiceRecord> toStop = new ArrayList<>(N);
                 for (int i = 0; i < N; i++) {
-                    final ServiceRecord r = smap.mServicesByName.valueAt(i);
+                    final ServiceRecord r = smap.mServicesByInstanceName.valueAt(i);
                     if (uid == r.serviceInfo.applicationInfo.uid
                             || packageName.equals(r.serviceInfo.packageName)) {
                         if (r.isForeground) {
@@ -236,7 +246,7 @@
      */
     final class ServiceMap extends Handler {
         final int mUserId;
-        final ArrayMap<ComponentName, ServiceRecord> mServicesByName = new ArrayMap<>();
+        final ArrayMap<ComponentName, ServiceRecord> mServicesByInstanceName = new ArrayMap<>();
         final ArrayMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent = new ArrayMap<>();
 
         final ArrayList<ServiceRecord> mDelayedStartList = new ArrayList<>();
@@ -358,7 +368,7 @@
         // TODO: Deal with global services
         if (DEBUG_MU)
             Slog.v(TAG_MU, "getServiceByNameLocked(" + name + "), callingUser = " + callingUser);
-        return getServiceMapLocked(callingUser).mServicesByName.get(name);
+        return getServiceMapLocked(callingUser).mServicesByInstanceName.get(name);
     }
 
     boolean hasBackgroundServicesLocked(int callingUser) {
@@ -376,7 +386,7 @@
     }
 
     ArrayMap<ComponentName, ServiceRecord> getServicesLocked(int callingUser) {
-        return getServiceMapLocked(callingUser).mServicesByName;
+        return getServiceMapLocked(callingUser).mServicesByInstanceName;
     }
 
     private boolean appRestrictedAnyInBackground(final int uid, final String packageName) {
@@ -406,7 +416,7 @@
         }
 
         ServiceLookupResult res =
-            retrieveServiceLocked(service, resolvedType, callingPackage,
+            retrieveServiceLocked(service, null, resolvedType, callingPackage,
                     callingPid, callingUid, userId, true, callerFg, false, false);
         if (res == null) {
             return null;
@@ -434,7 +444,7 @@
         boolean forcedStandby = false;
         if (bgLaunch && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
             if (DEBUG_FOREGROUND_SERVICE) {
-                Slog.d(TAG, "Forcing bg-only service start only for " + r.shortName
+                Slog.d(TAG, "Forcing bg-only service start only for " + r.shortInstanceName
                         + " : bgLaunch=" + bgLaunch + " callerFg=" + callerFg);
             }
             forcedStandby = true;
@@ -454,7 +464,7 @@
                     // Not allowed, fall back to normal start service, failing siliently
                     // if background check restricts that.
                     Slog.w(TAG, "startForegroundService not allowed due to app op: service "
-                            + service + " to " + r.name.flattenToShortString()
+                            + service + " to " + r.shortInstanceName
                             + " from pid=" + callingPid + " uid=" + callingUid
                             + " pkg=" + callingPackage);
                     fgRequired = false;
@@ -474,7 +484,7 @@
                     r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby);
             if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
                 Slog.w(TAG, "Background start not allowed: service "
-                        + service + " to " + r.name.flattenToShortString()
+                        + service + " to " + r.shortInstanceName
                         + " from pid=" + callingPid + " uid=" + callingUid
                         + " pkg=" + callingPackage + " startFg?=" + fgRequired);
                 if (allowed == ActivityManager.APP_START_MODE_DELAYED || forceSilentAbort) {
@@ -667,6 +677,8 @@
             stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
         }
         r.callStart = false;
+        StatsLog.write(StatsLog.SERVICE_STATE_CHANGED, r.appInfo.uid, r.name.getPackageName(),
+                r.name.getClassName(), StatsLog.SERVICE_STATE_CHANGED__STATE__START);
         synchronized (r.stats.getBatteryStats()) {
             r.stats.startRunningLocked();
         }
@@ -705,6 +717,9 @@
             service.delayedStop = true;
             return;
         }
+        StatsLog.write(StatsLog.SERVICE_STATE_CHANGED, service.appInfo.uid,
+                service.name.getPackageName(), service.name.getClassName(),
+                StatsLog.SERVICE_STATE_CHANGED__STATE__STOP);
         synchronized (service.stats.getBatteryStats()) {
             service.stats.stopRunningLocked();
         }
@@ -731,7 +746,7 @@
         }
 
         // If this service is active, make sure it is stopped.
-        ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, null,
+        ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, null,
                 Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false, false, false);
         if (r != null) {
             if (r.record != null) {
@@ -755,8 +770,8 @@
         ServiceMap services = mServiceMap.get(UserHandle.getUserId(uid));
         ArrayList<ServiceRecord> stopping = null;
         if (services != null) {
-            for (int i=services.mServicesByName.size()-1; i>=0; i--) {
-                ServiceRecord service = services.mServicesByName.valueAt(i);
+            for (int i = services.mServicesByInstanceName.size() - 1; i >= 0; i--) {
+                ServiceRecord service = services.mServicesByInstanceName.valueAt(i);
                 if (service.appInfo.uid == uid && service.startRequested) {
                     if (mAm.getAppStartModeLocked(service.appInfo.uid, service.packageName,
                             service.appInfo.targetSdkVersion, -1, false, false, false)
@@ -764,7 +779,7 @@
                         if (stopping == null) {
                             stopping = new ArrayList<>();
                         }
-                        String compName = service.name.flattenToShortString();
+                        String compName = service.shortInstanceName;
                         EventLogTags.writeAmStopIdleService(service.appInfo.uid, compName);
                         StringBuilder sb = new StringBuilder(64);
                         sb.append("Stopping service due to app idle: ");
@@ -791,7 +806,7 @@
     }
 
     IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) {
-        ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, callingPackage,
+        ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, callingPackage,
                 Binder.getCallingPid(), Binder.getCallingUid(),
                 UserHandle.getCallingUserId(), false, false, false, false);
 
@@ -846,6 +861,8 @@
                 }
             }
 
+            StatsLog.write(StatsLog.SERVICE_STATE_CHANGED, r.appInfo.uid, r.name.getPackageName(),
+                    r.name.getClassName(), StatsLog.SERVICE_STATE_CHANGED__STATE__STOP);
             synchronized (r.stats.getBatteryStats()) {
                 r.stats.stopRunningLocked();
             }
@@ -1218,7 +1235,7 @@
                     case AppOpsManager.MODE_IGNORED:
                         // Whoops, silently ignore this.
                         Slog.w(TAG, "Service.startForeground() not allowed due to app op: service "
-                                + r.shortName);
+                                + r.shortInstanceName);
                         ignoreForeground = true;
                         break;
                     default:
@@ -1229,7 +1246,7 @@
                         appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
                     Slog.w(TAG,
                             "Service.startForeground() not allowed due to bg restriction: service "
-                            + r.shortName);
+                            + r.shortInstanceName);
                     // Back off of any foreground expectations around this service, since we've
                     // just turned down its fg request.
                     updateServiceForegroundLocked(r.app, false);
@@ -1283,8 +1300,9 @@
                                 AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName,
                                 true);
                         StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
-                                r.appInfo.uid, r.shortName,
+                                r.appInfo.uid, r.shortInstanceName,
                                 StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER);
+                        mAm.updateForegroundServiceUsageStats(r.name, r.userId, true);
                     }
                     r.postNotification();
                     if (r.app != null) {
@@ -1332,8 +1350,9 @@
                         AppOpsManager.getToken(mAm.mAppOpsService),
                         AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
                 StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
-                        r.appInfo.uid, r.shortName,
+                        r.appInfo.uid, r.shortInstanceName,
                         StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
+                mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
                 if (r.app != null) {
                     mAm.updateLruProcessLocked(r.app, false, null);
                     updateServiceForegroundLocked(r.app, true);
@@ -1361,8 +1380,8 @@
             // due the other service.
             ServiceMap sm = getServiceMapLocked(r.userId);
             if (sm != null) {
-                for (int i = sm.mServicesByName.size()-1; i >= 0; i--) {
-                    ServiceRecord other = sm.mServicesByName.valueAt(i);
+                for (int i = sm.mServicesByInstanceName.size() - 1; i >= 0; i--) {
+                    ServiceRecord other = sm.mServicesByInstanceName.valueAt(i);
                     if (other != r && other.foregroundId == r.foregroundId
                             && other.packageName.equals(r.packageName)) {
                         // Found one!  Abort the cancel.
@@ -1454,7 +1473,8 @@
 
     int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
             String resolvedType, final IServiceConnection connection, int flags,
-            String callingPackage, final int userId) throws TransactionTooLargeException {
+            String instanceName, String callingPackage, final int userId)
+            throws TransactionTooLargeException {
         if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
                 + " type=" + resolvedType + " conn=" + connection.asBinder()
                 + " flags=0x" + Integer.toHexString(flags));
@@ -1518,8 +1538,9 @@
         final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
 
         ServiceLookupResult res =
-            retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
-                    Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant);
+            retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
+                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
+                    callerFg, isBindExternal, allowInstant);
         if (res == null) {
             return 0;
         }
@@ -1625,7 +1646,7 @@
 
             mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
                     callerApp.getCurProcState(), s.appInfo.uid, s.appInfo.longVersionCode,
-                    s.name, s.processName);
+                    s.instanceName, s.processName);
             // Once the apps have become associated, if one of them is caller is ephemeral
             // the target app should now be able to see the calling app
             mAm.grantEphemeralAccessLocked(callerApp.userId, service,
@@ -1697,7 +1718,7 @@
                 try {
                     c.conn.connected(s.name, b.intent.binder, false);
                 } catch (Exception e) {
-                    Slog.w(TAG, "Failure sending service " + s.shortName
+                    Slog.w(TAG, "Failure sending service " + s.shortInstanceName
                             + " to connection " + c.conn.asBinder()
                             + " (in " + c.binding.client.processName + ")", e);
                 }
@@ -1751,9 +1772,9 @@
                             try {
                                 c.conn.connected(r.name, service, false);
                             } catch (Exception e) {
-                                Slog.w(TAG, "Failure sending service " + r.name +
-                                      " to connection " + c.conn.asBinder() +
-                                      " (in " + c.binding.client.processName + ")", e);
+                                Slog.w(TAG, "Failure sending service " + r.shortInstanceName
+                                      + " to connection " + c.conn.asBinder()
+                                      + " (in " + c.binding.client.processName + ")", e);
                             }
                         }
                     }
@@ -1886,7 +1907,8 @@
     }
 
     private ServiceLookupResult retrieveServiceLocked(Intent service,
-            String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
+            String instanceName, String resolvedType, String callingPackage,
+            int callingPid, int callingUid, int userId,
             boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
             boolean allowInstant) {
         ServiceRecord r = null;
@@ -1897,12 +1919,23 @@
                 ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE, "service", null);
 
         ServiceMap smap = getServiceMapLocked(userId);
-        final ComponentName comp = service.getComponent();
+        final ComponentName comp;
+        if (instanceName == null) {
+            comp = service.getComponent();
+        } else {
+            final ComponentName realComp = service.getComponent();
+            if (realComp == null) {
+                throw new IllegalArgumentException("Can't use custom instance name '" + instanceName
+                        + "' without expicit component in Intent");
+            }
+            comp = new ComponentName(realComp.getPackageName(),
+                    realComp.getClassName() + ":" + instanceName);
+        }
         if (comp != null) {
-            r = smap.mServicesByName.get(comp);
+            r = smap.mServicesByInstanceName.get(comp);
             if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by component: " + r);
         }
-        if (r == null && !isBindExternal) {
+        if (r == null && !isBindExternal && instanceName == null) {
             Intent.FilterComparison filter = new Intent.FilterComparison(service);
             r = smap.mServicesByIntent.get(filter);
             if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by intent: " + r);
@@ -1924,24 +1957,29 @@
                 // TODO: come back and remove this assumption to triage all services
                 ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
                         resolvedType, flags, userId, callingUid);
-                ServiceInfo sInfo =
-                    rInfo != null ? rInfo.serviceInfo : null;
+                ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
                 if (sInfo == null) {
                     Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId +
                           ": not found");
                     return null;
                 }
-                ComponentName name = new ComponentName(
+                if (instanceName != null
+                        && (sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) == 0) {
+                    throw new IllegalArgumentException("Can't use instance name '" + instanceName
+                            + "' with non-isolated service '" + sInfo.name + "'");
+                }
+                ComponentName className = new ComponentName(
                         sInfo.applicationInfo.packageName, sInfo.name);
+                ComponentName name = comp != null ? comp : className;
                 if ((sInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0) {
                     if (isBindExternal) {
                         if (!sInfo.exported) {
-                            throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
-                                    " is not exported");
+                            throw new SecurityException("BIND_EXTERNAL_SERVICE failed, "
+                                    + className + " is not exported");
                         }
                         if ((sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) == 0) {
-                            throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
-                                    " is not an isolatedProcess");
+                            throw new SecurityException("BIND_EXTERNAL_SERVICE failed, "
+                                    + className + " is not an isolatedProcess");
                         }
                         // Run the service under the calling package's application.
                         ApplicationInfo aInfo = AppGlobals.getPackageManager().getApplicationInfo(
@@ -1955,6 +1993,9 @@
                         sInfo.applicationInfo.packageName = aInfo.packageName;
                         sInfo.applicationInfo.uid = aInfo.uid;
                         name = new ComponentName(aInfo.packageName, name.getClassName());
+                        className = new ComponentName(aInfo.packageName,
+                                instanceName == null ? className.getClassName()
+                                        : (className.getClassName() + ":" + instanceName));
                         service.setComponent(name);
                     } else {
                         throw new SecurityException("BIND_EXTERNAL_SERVICE required for " +
@@ -1974,7 +2015,7 @@
                     sInfo = new ServiceInfo(sInfo);
                     sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
                 }
-                r = smap.mServicesByName.get(name);
+                r = smap.mServicesByInstanceName.get(name);
                 if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE,
                         "Retrieved via pm by intent: " + r);
                 if (r == null && createIfNeeded) {
@@ -1985,19 +2026,20 @@
                     final BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
                     synchronized (stats) {
                         ss = stats.getServiceStatsLocked(
-                                sInfo.applicationInfo.uid, sInfo.packageName,
-                                sInfo.name);
+                                sInfo.applicationInfo.uid, name.getPackageName(),
+                                name.getClassName());
                     }
-                    r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
+                    r = new ServiceRecord(mAm, ss, className, name, filter, sInfo, callingFromFg,
+                            res);
                     res.setService(r);
-                    smap.mServicesByName.put(name, r);
+                    smap.mServicesByInstanceName.put(name, r);
                     smap.mServicesByIntent.put(filter, r);
 
                     // Make sure this component isn't in the pending list.
                     for (int i=mPendingServices.size()-1; i>=0; i--) {
                         final ServiceRecord pr = mPendingServices.get(i);
                         if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
-                                && pr.name.equals(name)) {
+                                && pr.instanceName.equals(name)) {
                             if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Remove pending: " + pr);
                             mPendingServices.remove(i);
                         }
@@ -2012,14 +2054,14 @@
             if (mAm.checkComponentPermission(r.permission,
                     callingPid, callingUid, r.appInfo.uid, r.exported) != PERMISSION_GRANTED) {
                 if (!r.exported) {
-                    Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+                    Slog.w(TAG, "Permission Denial: Accessing service " + r.shortInstanceName
                             + " from pid=" + callingPid
                             + ", uid=" + callingUid
                             + " that is not exported from uid " + r.appInfo.uid);
                     return new ServiceLookupResult(null, "not exported from uid "
                             + r.appInfo.uid);
                 }
-                Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+                Slog.w(TAG, "Permission Denial: Accessing service " + r.shortInstanceName
                         + " from pid=" + callingPid
                         + ", uid=" + callingUid
                         + " requires " + r.permission);
@@ -2028,7 +2070,7 @@
                 final int opCode = AppOpsManager.permissionToOpCode(r.permission);
                 if (opCode != AppOpsManager.OP_NONE && mAm.mAppOpsService.noteOperation(
                         opCode, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
-                    Slog.w(TAG, "Appop Denial: Accessing service " + r.name
+                    Slog.w(TAG, "Appop Denial: Accessing service " + r.shortInstanceName
                             + " from pid=" + callingPid
                             + ", uid=" + callingUid
                             + " requires appop " + AppOpsManager.opToName(opCode));
@@ -2049,7 +2091,7 @@
         if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING "
                 + why + " of " + r + " in app " + r.app);
         else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING "
-                + why + " of " + r.shortName);
+                + why + " of " + r.shortInstanceName);
 
         // For b/34123235: Services within the system server won't start until SystemServer
         // does Looper.loop(), so we shouldn't try to start/bind to them too early in the boot
@@ -2134,14 +2176,14 @@
         boolean canceled = false;
 
         if (mAm.mAtmInternal.isShuttingDown()) {
-            Slog.w(TAG, "Not scheduling restart of crashed service " + r.shortName
+            Slog.w(TAG, "Not scheduling restart of crashed service " + r.shortInstanceName
                     + " - system is shutting down");
             return false;
         }
 
         ServiceMap smap = getServiceMapLocked(r.userId);
-        if (smap.mServicesByName.get(r.name) != r) {
-            ServiceRecord cur = smap.mServicesByName.get(r.name);
+        if (smap.mServicesByInstanceName.get(r.instanceName) != r) {
+            ServiceRecord cur = smap.mServicesByInstanceName.get(r.instanceName);
             Slog.wtf(TAG, "Attempting to schedule restart of " + r
                     + " when found in map: " + cur);
             return false;
@@ -2172,7 +2214,7 @@
                         if (resetTime < dur) resetTime = dur;
                     } else {
                         Slog.w(TAG, "Canceling start item " + si.intent + " in service "
-                                + r.name);
+                                + r.shortInstanceName);
                         canceled = true;
                     }
                 }
@@ -2244,9 +2286,9 @@
         mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
         r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
         Slog.w(TAG, "Scheduling restart of crashed service "
-                + r.shortName + " in " + r.restartDelay + "ms");
+                + r.shortInstanceName + " in " + r.restartDelay + "ms");
         EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
-                r.userId, r.shortName, r.restartDelay);
+                r.userId, r.shortInstanceName, r.restartDelay);
 
         return canceled;
     }
@@ -2381,7 +2423,7 @@
                 } catch (TransactionTooLargeException e) {
                     throw e;
                 } catch (RemoteException e) {
-                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
+                    Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
                 }
 
                 // If a dead object exception was thrown -- fall through to
@@ -2405,7 +2447,7 @@
         // to be executed when the app comes up.
         if (app == null && !permissionsReviewRequired) {
             if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
-                    hostingType, r.name, false, isolated, false)) == null) {
+                    hostingType, r.instanceName, false, isolated, false)) == null) {
                 String msg = "Unable to launch app "
                         + r.appInfo.packageName + "/"
                         + r.appInfo.uid + " for service "
@@ -2476,11 +2518,14 @@
         try {
             if (LOG_SERVICE_START_STOP) {
                 String nameTerm;
-                int lastPeriod = r.shortName.lastIndexOf('.');
-                nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
+                int lastPeriod = r.shortInstanceName.lastIndexOf('.');
+                nameTerm = lastPeriod >= 0 ? r.shortInstanceName.substring(lastPeriod)
+                        : r.shortInstanceName;
                 EventLogTags.writeAmCreateService(
                         r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
             }
+            StatsLog.write(StatsLog.SERVICE_LAUNCH_REPORTED, r.appInfo.uid, r.name.getPackageName(),
+                    r.name.getClassName());
             synchronized (r.stats.getBatteryStats()) {
                 r.stats.startLaunchedLocked();
             }
@@ -2693,9 +2738,9 @@
                 try {
                     cr.conn.connected(r.name, null, true);
                 } catch (Exception e) {
-                    Slog.w(TAG, "Failure disconnecting service " + r.name +
-                          " to connection " + c.get(i).conn.asBinder() +
-                          " (in " + c.get(i).binding.client.processName + ")", e);
+                    Slog.w(TAG, "Failure disconnecting service " + r.shortInstanceName
+                          + " to connection " + c.get(i).conn.asBinder()
+                          + " (in " + c.get(i).binding.client.processName + ")", e);
                 }
             }
         }
@@ -2716,7 +2761,7 @@
                                 ibr.intent.getIntent());
                     } catch (Exception e) {
                         Slog.w(TAG, "Exception when unbinding service "
-                                + r.shortName, e);
+                                + r.shortInstanceName, e);
                         serviceProcessGoneLocked(r);
                     }
                 }
@@ -2761,14 +2806,14 @@
         }
 
         final ServiceMap smap = getServiceMapLocked(r.userId);
-        ServiceRecord found = smap.mServicesByName.remove(r.name);
+        ServiceRecord found = smap.mServicesByInstanceName.remove(r.instanceName);
 
         // Note when this method is called by bringUpServiceLocked(), the service is not found
-        // in mServicesByName and found will be null.
+        // in mServicesByInstanceName and found will be null.
         if (found != null && found != r) {
             // This is not actually the service we think is running...  this should not happen,
             // but if it does, fail hard.
-            smap.mServicesByName.put(r.name, found);
+            smap.mServicesByInstanceName.put(r.instanceName, found);
             throw new IllegalStateException("Bringing down " + r + " but actually running "
                     + found);
         }
@@ -2795,8 +2840,9 @@
             mAm.mAppOpsService.finishOperation(
                     AppOpsManager.getToken(mAm.mAppOpsService),
                     AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
-            StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName,
-                    StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
+            StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid,
+                    r.shortInstanceName, StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
+            mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
         }
 
         r.isForeground = false;
@@ -2825,7 +2871,7 @@
                     r.app.thread.scheduleStopService(r);
                 } catch (Exception e) {
                     Slog.w(TAG, "Exception when destroying service "
-                            + r.shortName, e);
+                            + r.shortInstanceName, e);
                     serviceProcessGoneLocked(r);
                 }
             } else {
@@ -2902,7 +2948,7 @@
         }
 
         mAm.stopAssociationLocked(b.client.uid, b.client.processName, s.appInfo.uid,
-                s.appInfo.longVersionCode, s.name, s.processName);
+                s.appInfo.longVersionCode, s.instanceName, s.processName);
 
         if (b.connections.size() == 0) {
             b.intent.apps.remove(b.client);
@@ -2929,7 +2975,7 @@
                     b.intent.doRebind = false;
                     s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
                 } catch (Exception e) {
-                    Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
+                    Slog.w(TAG, "Exception when unbinding service " + s.shortInstanceName, e);
                     serviceProcessGoneLocked(s);
                 }
             }
@@ -3048,17 +3094,17 @@
                 + ": nesting=" + r.executeNesting
                 + ", inDestroying=" + inDestroying + ", app=" + r.app);
         else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
-                "<<< DONE EXECUTING " + r.shortName);
+                "<<< DONE EXECUTING " + r.shortInstanceName);
         r.executeNesting--;
         if (r.executeNesting <= 0) {
             if (r.app != null) {
                 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
-                        "Nesting at 0 of " + r.shortName);
+                        "Nesting at 0 of " + r.shortInstanceName);
                 r.app.execServicesFg = false;
                 r.app.executingServices.remove(r);
                 if (r.app.executingServices.size() == 0) {
                     if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
-                            "No more executingServices of " + r.shortName);
+                            "No more executingServices of " + r.shortInstanceName);
                     mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
                 } else if (r.executeFg) {
                     // Need to re-evaluate whether the app still needs to be in the foreground.
@@ -3128,7 +3174,7 @@
                 }
             } catch (RemoteException e) {
                 Slog.w(TAG, "Exception in new application when starting service "
-                        + sr.shortName, e);
+                        + sr.shortInstanceName, e);
                 throw e;
             }
         }
@@ -3214,7 +3260,8 @@
         if (userId == UserHandle.USER_ALL) {
             for (int i = mServiceMap.size() - 1; i >= 0; i--) {
                 didSomething |= collectPackageServicesLocked(packageName, filterByClasses,
-                        evenPersistent, doit, killProcess, mServiceMap.valueAt(i).mServicesByName);
+                        evenPersistent, doit, killProcess,
+                        mServiceMap.valueAt(i).mServicesByInstanceName);
                 if (!doit && didSomething) {
                     return true;
                 }
@@ -3225,7 +3272,7 @@
         } else {
             ServiceMap smap = mServiceMap.get(userId);
             if (smap != null) {
-                ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByName;
+                ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByInstanceName;
                 didSomething = collectPackageServicesLocked(packageName, filterByClasses,
                         evenPersistent, doit, killProcess, items);
             }
@@ -3275,7 +3322,7 @@
             ServiceRecord sr = services.get(i);
             if (sr.startRequested) {
                 if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
-                    Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
+                    Slog.i(TAG, "Stopping service " + sr.shortInstanceName + ": remove task");
                     stopServiceLocked(sr);
                 } else {
                     sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
@@ -3313,7 +3360,7 @@
                                 } catch (Exception e) {
                                     // todo: this should be asynchronous!
                                     Slog.w(TAG, "Exception thrown disconnected servce "
-                                          + r.shortName
+                                          + r.shortInstanceName
                                           + " from app " + app.processName, e);
                                 }
                             }
@@ -3387,7 +3434,7 @@
                     if (false && proc != null && !proc.isPersistent() && proc.thread != null
                             && proc.pid != 0 && proc.pid != ActivityManagerService.MY_PID
                             && proc.setProcState >= ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
-                        proc.kill("bound to service " + sr.name.flattenToShortString()
+                        proc.kill("bound to service " + sr.shortInstanceName
                                 + " in dying proc " + (app != null ? app.processName : "??"), true);
                     }
                 }
@@ -3408,7 +3455,7 @@
 
             // Sanity check: if the service listed for the app is not one
             // we actually are maintaining, just let it drop.
-            final ServiceRecord curRec = smap.mServicesByName.get(sr.name);
+            final ServiceRecord curRec = smap.mServicesByInstanceName.get(sr.instanceName);
             if (curRec != sr) {
                 if (curRec != null) {
                     Slog.wtf(TAG, "Service " + sr + " in process " + app
@@ -3425,7 +3472,7 @@
                 Slog.w(TAG, "Service crashed " + sr.crashCount
                         + " times, stopping: " + sr);
                 EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
-                        sr.userId, sr.crashCount, sr.shortName, app.pid);
+                        sr.userId, sr.crashCount, sr.shortInstanceName, app.pid);
                 bringDownServiceLocked(sr);
             } else if (!allowRestart
                     || !mAm.mUserController.isUserRunning(sr.userId, 0)) {
@@ -3631,7 +3678,7 @@
                 mLastAnrDump = sw.toString();
                 mAm.mHandler.removeCallbacks(mLastAnrDumpClearer);
                 mAm.mHandler.postDelayed(mLastAnrDumpClearer, LAST_ANR_LIFETIME_DURATION_MSECS);
-                anrMessage = "executing service " + timeout.shortName;
+                anrMessage = "executing service " + timeout.shortInstanceName;
             } else {
                 Message msg = mAm.mHandler.obtainMessage(
                         ActivityManagerService.SERVICE_TIMEOUT_MSG);
@@ -3677,7 +3724,8 @@
         final int userId = UserHandle.getUserId(applicationInfo.uid);
         ServiceMap serviceMap = mServiceMap.get(userId);
         if (serviceMap != null) {
-            ArrayMap<ComponentName, ServiceRecord> servicesByName = serviceMap.mServicesByName;
+            ArrayMap<ComponentName, ServiceRecord> servicesByName
+                    = serviceMap.mServicesByInstanceName;
             for (int j = servicesByName.size() - 1; j >= 0; j--) {
                 ServiceRecord serviceRecord = servicesByName.valueAt(j);
                 if (applicationInfo.packageName.equals(serviceRecord.appInfo.packageName)) {
@@ -3748,9 +3796,9 @@
             final int[] users = mAm.mUserController.getUsers();
             for (int user : users) {
                 ServiceMap smap = getServiceMapLocked(user);
-                if (smap.mServicesByName.size() > 0) {
-                    for (int si=0; si<smap.mServicesByName.size(); si++) {
-                        ServiceRecord r = smap.mServicesByName.valueAt(si);
+                if (smap.mServicesByInstanceName.size() > 0) {
+                    for (int si=0; si<smap.mServicesByInstanceName.size(); si++) {
+                        ServiceRecord r = smap.mServicesByInstanceName.valueAt(si);
                         if (!matcher.match(r, r.name)) {
                             continue;
                         }
@@ -4151,7 +4199,7 @@
                 }
                 long token = proto.start(ActiveServicesProto.SERVICES_BY_USERS);
                 proto.write(ActiveServicesProto.ServicesByUser.USER_ID, user);
-                ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByName;
+                ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByInstanceName;
                 for (int i=0; i<alls.size(); i++) {
                     alls.valueAt(i).writeToProto(proto,
                             ActiveServicesProto.ServicesByUser.SERVICE_RECORDS);
@@ -4184,7 +4232,7 @@
                 if (smap == null) {
                     continue;
                 }
-                ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByName;
+                ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByInstanceName;
                 for (int i=0; i<alls.size(); i++) {
                     ServiceRecord r1 = alls.valueAt(i);
 
@@ -4222,7 +4270,7 @@
         String innerPrefix = prefix + "  ";
         synchronized (mAm) {
             pw.print(prefix); pw.print("SERVICE ");
-                    pw.print(r.shortName); pw.print(" ");
+                    pw.print(r.shortInstanceName); pw.print(" ");
                     pw.print(Integer.toHexString(System.identityHashCode(r)));
                     pw.print(" pid=");
                     if (r.app != null) pw.println(r.app.pid);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 52b0275..aa96082 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -68,9 +68,7 @@
 import static android.os.Process.THREAD_GROUP_RESTRICTED;
 import static android.os.Process.THREAD_GROUP_TOP_APP;
 import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
-import static android.os.Process.getPidsForCommands;
 import static android.os.Process.getTotalMemory;
-import static android.os.Process.getUidForPid;
 import static android.os.Process.isThreadInProcess;
 import static android.os.Process.killProcess;
 import static android.os.Process.killProcessQuiet;
@@ -127,6 +125,8 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_UID_OBSERVERS;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.MemoryStatUtil.hasMemcg;
+import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
@@ -144,11 +144,6 @@
 import static com.android.server.wm.ActivityTaskManagerService.KEY_DISPATCHING_TIMEOUT_MS;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 import static com.android.server.wm.ActivityTaskManagerService.relaunchReasonToString;
-import static com.android.server.am.MemoryStatUtil.MEMORY_STAT_INTERESTING_NATIVE_PROCESSES;
-import static com.android.server.am.MemoryStatUtil.hasMemcg;
-import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs;
-import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
-import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs;
 
 import android.Manifest;
 import android.Manifest.permission;
@@ -318,6 +313,7 @@
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.os.ProcessCpuTracker;
 import com.android.internal.os.TransferPipe;
+import com.android.internal.os.Zygote;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
@@ -1134,9 +1130,46 @@
     boolean mOrigWaitForDebugger = false;
     boolean mAlwaysFinishActivities = false;
 
-    String mProfileApp = null;
-    ProcessRecord mProfileProc = null;
-    ProfilerInfo mProfilerInfo = null;
+    class ProfileData {
+        private String mProfileApp = null;
+        private ProcessRecord mProfileProc = null;
+        private ProfilerInfo mProfilerInfo = null;
+
+        void setProfileApp(String profileApp) {
+            mProfileApp = profileApp;
+            if (mAtmInternal != null) {
+                mAtmInternal.setProfileApp(profileApp);
+            }
+        }
+
+        String getProfileApp() {
+            return mProfileApp;
+        }
+
+        void setProfileProc(ProcessRecord profileProc) {
+            mProfileProc = profileProc;
+            if (mAtmInternal != null) {
+                mAtmInternal.setProfileProc(
+                        profileProc.getWindowProcessController());
+            }
+        }
+
+        ProcessRecord getProfileProc() {
+            return mProfileProc;
+        }
+
+        void setProfilerInfo(ProfilerInfo profilerInfo) {
+            mProfilerInfo = profilerInfo;
+            if (mAtmInternal != null) {
+                mAtmInternal.setProfilerInfo(profilerInfo);
+            }
+        }
+
+        ProfilerInfo getProfilerInfo() {
+            return mProfilerInfo;
+        }
+    }
+    final ProfileData mProfileData = new ProfileData();
 
     /**
      * Stores a map of process name -> agent string. When a process is started and mAgentAppMap
@@ -1299,7 +1332,7 @@
                 IApplicationThread thread) {
             if (DEBUG_ALL) Slog.v(
                 TAG, "New death recipient " + this
-                + " for thread " + thread.asBinder());
+                 + " for thread " + thread.asBinder());
             mApp = app;
             mPid = pid;
             mAppThread = thread;
@@ -2022,8 +2055,7 @@
         private String mExemptionsStr;
         private List<String> mExemptions = Collections.emptyList();
         private int mLogSampleRate = -1;
-        @HiddenApiEnforcementPolicy private int mPolicyPreP = HIDDEN_API_ENFORCEMENT_DEFAULT;
-        @HiddenApiEnforcementPolicy private int mPolicyP = HIDDEN_API_ENFORCEMENT_DEFAULT;
+        @HiddenApiEnforcementPolicy private int mPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT;
 
         public HiddenApiSettings(Handler handler, Context context) {
             super(handler);
@@ -2040,11 +2072,7 @@
                     false,
                     this);
             mContext.getContentResolver().registerContentObserver(
-                    Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS),
-                    false,
-                    this);
-            mContext.getContentResolver().registerContentObserver(
-                    Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY_P_APPS),
+                    Settings.Global.getUriFor(Settings.Global.HIDDEN_API_POLICY),
                     false,
                     this);
             update();
@@ -2079,8 +2107,7 @@
                 mLogSampleRate = logSampleRate;
                 zygoteProcess.setHiddenApiAccessLogSampleRate(mLogSampleRate);
             }
-            mPolicyPreP = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY_PRE_P_APPS);
-            mPolicyP = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY_P_APPS);
+            mPolicy = getValidEnforcementPolicy(Settings.Global.HIDDEN_API_POLICY);
         }
 
         private @HiddenApiEnforcementPolicy int getValidEnforcementPolicy(String settingsKey) {
@@ -2097,12 +2124,8 @@
             return mBlacklistDisabled;
         }
 
-        @HiddenApiEnforcementPolicy int getPolicyForPrePApps() {
-            return mPolicyPreP;
-        }
-
-        @HiddenApiEnforcementPolicy int getPolicyForPApps() {
-            return mPolicyP;
+        @HiddenApiEnforcementPolicy int getPolicy() {
+            return mPolicy;
         }
 
         public void onChange(boolean selfChange) {
@@ -2225,8 +2248,7 @@
         mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
 
         mActivityTaskManager = atm;
-        mActivityTaskManager.setActivityManagerService(this, mHandlerThread.getLooper(),
-                mIntentFirewall, mPendingIntentController);
+        mActivityTaskManager.setActivityManagerService(mIntentFirewall, mPendingIntentController);
         mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
 
         mProcessCpuThread = new Thread("CpuTracker") {
@@ -2654,8 +2676,10 @@
     }
 
     void updateUsageStats(ComponentName activity, int uid, int userId, boolean resumed) {
-        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH,
-                "updateUsageStats: comp=" + activity + "res=" + resumed);
+        if (DEBUG_SWITCH) {
+            Slog.d(TAG_SWITCH,
+                    "updateUsageStats: comp=" + activity + "res=" + resumed);
+        }
         final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
         StatsLog.write(StatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED,
             uid, activity.getPackageName(),
@@ -2682,6 +2706,20 @@
         }
     }
 
+    void updateForegroundServiceUsageStats(ComponentName service, int userId, boolean started) {
+        if (DEBUG_SWITCH) {
+            Slog.d(TAG_SWITCH, "updateForegroundServiceUsageStats: comp="
+                    + service + "started=" + started);
+        }
+        synchronized (this) {
+            if (mUsageStatsService != null) {
+                mUsageStatsService.reportEvent(service, userId,
+                        started ? UsageEvents.Event.FOREGROUND_SERVICE_START
+                                : UsageEvents.Event.FOREGROUND_SERVICE_STOP);
+            }
+        }
+    }
+
     CompatibilityInfo compatibilityInfoForPackage(ApplicationInfo ai) {
         return mAtmInternal.compatibilityInfoForPackage(ai);
     }
@@ -3010,35 +3048,18 @@
     public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
             int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
-        synchronized (this) {
-            /**
-             * Flags like {@link android.app.ActivityManager#START_FLAG_DEBUG} maybe be set on this
-             * call when called/invoked from the shell command. To avoid deadlock, we go ahead and
-             * acquire the AMS lock now since ATMS will need to synchronously call back into AMS
-             * later to modify process settings due to the flags.
-             * TODO(b/80414790): Investigate a better way of untangling this.
-             */
+
             return mActivityTaskManager.startActivityAsUser(caller, callingPackage, intent,
                     resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo,
                     bOptions, userId);
-        }
     }
 
     WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
             int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
-        synchronized (this) {
-            /**
-             * Flags like {@link android.app.ActivityManager#START_FLAG_DEBUG} maybe be set on this
-             * call when called/invoked from the shell command. To avoid deadlock, we go ahead and
-             * acquire the AMS lock now since ATMS will need to synchronously call back into AMS
-             * later to modify process settings due to the flags.
-             * TODO(b/80414790): Investigate a better way of untangling this.
-             */
             return mActivityTaskManager.startActivityAndWait(caller, callingPackage, intent,
                     resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo,
                     bOptions, userId);
-        }
     }
 
     @Override
@@ -3129,7 +3150,7 @@
             }
         }
 
-        if (mProfileProc == app) {
+        if (mProfileData.getProfileProc() == app) {
             clearProfilerLocked();
         }
 
@@ -3852,7 +3873,7 @@
 
         final int callingPid = Binder.getCallingPid();
         final int callingUid = Binder.getCallingUid();
-        final int userId = UserHandle.getUserId(callingUid);
+        final int callingUserId = UserHandle.getUserId(callingUid);
         final boolean allUsers = ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL,
                 callingUid) == PackageManager.PERMISSION_GRANTED;
         // Check REAL_GET_TASKS to see if they are allowed to access other uids
@@ -3870,11 +3891,17 @@
                     oomAdj = proc != null ? proc.setAdj : 0;
                 }
             }
-            if (!allUids || (!allUsers && (proc == null
-                    || UserHandle.getUserId(proc.uid) != userId))) {
-                // The caller is not allow to get information about this other process...
-                // just leave it empty.
-                continue;
+            final int targetUid = (proc != null) ? proc.uid : -1;
+            final int targetUserId = (proc != null) ? UserHandle.getUserId(targetUid) : -1;
+
+            if (callingUid != targetUid) {
+                if (!allUids) {
+                    continue; // Not allowed to see other UIDs.
+                }
+
+                if (!allUsers && (targetUserId != callingUserId)) {
+                    continue; // Not allowed to see other users.
+                }
             }
             if (proc != null && proc.lastMemInfoTime >= lastNow && proc.lastMemInfo != null) {
                 // It hasn't been long enough that we want to take another sample; return
@@ -4410,16 +4437,18 @@
 
             ProfilerInfo profilerInfo = null;
             String preBindAgent = null;
-            if (mProfileApp != null && mProfileApp.equals(processName)) {
-                mProfileProc = app;
-                if (mProfilerInfo != null) {
+            if (mProfileData.getProfileApp() != null
+                    && mProfileData.getProfileApp().equals(processName)) {
+                mProfileData.setProfileProc(app);
+                if (mProfileData.getProfilerInfo() != null) {
                     // Send a profiler info object to the app if either a file is given, or
                     // an agent should be loaded at bind-time.
-                    boolean needsInfo = mProfilerInfo.profileFile != null
-                            || mProfilerInfo.attachAgentDuringBind;
-                    profilerInfo = needsInfo ? new ProfilerInfo(mProfilerInfo) : null;
-                    if (mProfilerInfo.agent != null) {
-                        preBindAgent = mProfilerInfo.agent;
+                    boolean needsInfo = mProfileData.getProfilerInfo().profileFile != null
+                            || mProfileData.getProfilerInfo().attachAgentDuringBind;
+                    profilerInfo = needsInfo
+                            ? new ProfilerInfo(mProfileData.getProfilerInfo()) : null;
+                    if (mProfileData.getProfilerInfo().agent != null) {
+                        preBindAgent = mProfileData.getProfilerInfo().agent;
                     }
                 }
             } else if (instr != null && instr.mProfileFile != null) {
@@ -4443,7 +4472,8 @@
 
             if (profilerInfo != null && profilerInfo.profileFd != null) {
                 profilerInfo.profileFd = profilerInfo.profileFd.dup();
-                if (TextUtils.equals(mProfileApp, processName) && mProfilerInfo != null) {
+                if (TextUtils.equals(mProfileData.getProfileApp(), processName)
+                        && mProfileData.getProfilerInfo() != null) {
                     clearProfilerLocked();
                 }
             }
@@ -4790,6 +4820,10 @@
             String packageName, IBinder token, String resultWho,
             int requestCode, Intent[] intents, String[] resolvedTypes,
             int flags, Bundle bOptions, int userId) {
+
+        // NOTE: The service lock isn't held in this method because nothing in the method requires
+        // the service lock to be held.
+
         enforceNotIsolatedCaller("getIntentSender");
         // Refuse possible leaked file descriptors
         if (intents != null) {
@@ -4821,43 +4855,41 @@
             }
         }
 
-        synchronized(this) {
-            int callingUid = Binder.getCallingUid();
-            int origUserId = userId;
-            userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
-                    type == ActivityManager.INTENT_SENDER_BROADCAST,
-                    ALLOW_NON_FULL, "getIntentSender", null);
-            if (origUserId == UserHandle.USER_CURRENT) {
-                // We don't want to evaluate this until the pending intent is
-                // actually executed.  However, we do want to always do the
-                // security checking for it above.
-                userId = UserHandle.USER_CURRENT;
-            }
-            try {
-                if (callingUid != 0 && callingUid != SYSTEM_UID) {
-                    final int uid = AppGlobals.getPackageManager().getPackageUid(packageName,
-                            MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callingUid));
-                    if (!UserHandle.isSameApp(callingUid, uid)) {
-                        String msg = "Permission Denial: getIntentSender() from pid="
-                            + Binder.getCallingPid()
-                            + ", uid=" + Binder.getCallingUid()
-                            + ", (need uid=" + uid + ")"
-                            + " is not allowed to send as package " + packageName;
-                        Slog.w(TAG, msg);
-                        throw new SecurityException(msg);
-                    }
+        int callingUid = Binder.getCallingUid();
+        int origUserId = userId;
+        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
+                type == ActivityManager.INTENT_SENDER_BROADCAST,
+                ALLOW_NON_FULL, "getIntentSender", null);
+        if (origUserId == UserHandle.USER_CURRENT) {
+            // We don't want to evaluate this until the pending intent is
+            // actually executed.  However, we do want to always do the
+            // security checking for it above.
+            userId = UserHandle.USER_CURRENT;
+        }
+        try {
+            if (callingUid != 0 && callingUid != SYSTEM_UID) {
+                final int uid = AppGlobals.getPackageManager().getPackageUid(packageName,
+                        MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callingUid));
+                if (!UserHandle.isSameApp(callingUid, uid)) {
+                    String msg = "Permission Denial: getIntentSender() from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid()
+                        + ", (need uid=" + uid + ")"
+                        + " is not allowed to send as package " + packageName;
+                    Slog.w(TAG, msg);
+                    throw new SecurityException(msg);
                 }
+            }
 
-                if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) {
-                    return mAtmInternal.getIntentSender(type, packageName, callingUid, userId,
-                            token, resultWho, requestCode, intents, resolvedTypes, flags, bOptions);
-                }
-                return mPendingIntentController.getIntentSender(type, packageName, callingUid,
-                        userId, token, resultWho, requestCode, intents, resolvedTypes, flags,
-                        bOptions);
-            } catch (RemoteException e) {
-                throw new SecurityException(e);
+            if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) {
+                return mAtmInternal.getIntentSender(type, packageName, callingUid, userId,
+                        token, resultWho, requestCode, intents, resolvedTypes, flags, bOptions);
             }
+            return mPendingIntentController.getIntentSender(type, packageName, callingUid,
+                    userId, token, resultWho, requestCode, intents, resolvedTypes, flags,
+                    bOptions);
+        } catch (RemoteException e) {
+            throw new SecurityException(e);
         }
     }
 
@@ -6972,7 +7004,7 @@
         mCoreSettingsObserver = new CoreSettingsObserver(this);
         mActivityTaskManager.installSystemProviders();
         mDevelopmentSettingsObserver = new DevelopmentSettingsObserver();
-        GlobalSettingsToPropertiesMapper.start(mContext.getContentResolver());
+        SettingsToPropertiesMapper.start(mContext.getContentResolver());
 
         // Now that the settings provider is published we can consider sending
         // in a rescue party.
@@ -7320,13 +7352,6 @@
     }
 
     @Override
-    public void setLockScreenShown(boolean keyguardShowing, boolean aodShowing,
-            int secondaryDisplayShowing) {
-        mActivityTaskManager.setLockScreenShown(
-                keyguardShowing, aodShowing, secondaryDisplayShowing);
-    }
-
-    @Override
     public void notifyLockedProfile(@UserIdInt int userId) {
         mAtmInternal.notifyLockedProfile(userId, mUserController.getCurrentUserId());
     }
@@ -7451,17 +7476,17 @@
                     throw new SecurityException("Process not debuggable: " + app.packageName);
                 }
             }
-            mProfileApp = processName;
+            mProfileData.setProfileApp(processName);
 
-            if (mProfilerInfo != null) {
-                if (mProfilerInfo.profileFd != null) {
+            if (mProfileData.getProfilerInfo() != null) {
+                if (mProfileData.getProfilerInfo().profileFd != null) {
                     try {
-                        mProfilerInfo.profileFd.close();
+                        mProfileData.getProfilerInfo().profileFd.close();
                     } catch (IOException e) {
                     }
                 }
             }
-            mProfilerInfo = new ProfilerInfo(profilerInfo);
+            mProfileData.setProfilerInfo(new ProfilerInfo(profilerInfo));
             mProfileType = 0;
         }
     }
@@ -9978,20 +10003,25 @@
                 pw.println("  mTrackAllocationApp=" + mTrackAllocationApp);
             }
         }
-        if (mProfileApp != null || mProfileProc != null || (mProfilerInfo != null &&
-                (mProfilerInfo.profileFile != null || mProfilerInfo.profileFd != null))) {
-            if (dumpPackage == null || dumpPackage.equals(mProfileApp)) {
+        if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null
+                || (mProfileData.getProfilerInfo() != null &&
+                (mProfileData.getProfilerInfo().profileFile != null
+                        || mProfileData.getProfilerInfo().profileFd != null))) {
+            if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) {
                 if (needSep) {
                     pw.println();
                     needSep = false;
                 }
-                pw.println("  mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
-                if (mProfilerInfo != null) {
-                    pw.println("  mProfileFile=" + mProfilerInfo.profileFile + " mProfileFd=" +
-                            mProfilerInfo.profileFd);
-                    pw.println("  mSamplingInterval=" + mProfilerInfo.samplingInterval +
-                            " mAutoStopProfiler=" + mProfilerInfo.autoStopProfiler +
-                            " mStreamingOutput=" + mProfilerInfo.streamingOutput);
+                pw.println("  mProfileApp=" + mProfileData.getProfileApp()
+                        + " mProfileProc=" + mProfileData.getProfileProc());
+                if (mProfileData.getProfilerInfo() != null) {
+                    pw.println("  mProfileFile=" + mProfileData.getProfilerInfo().profileFile
+                            + " mProfileFd=" + mProfileData.getProfilerInfo().profileFd);
+                    pw.println("  mSamplingInterval="
+                            + mProfileData.getProfilerInfo().samplingInterval +
+                            " mAutoStopProfiler="
+                            + mProfileData.getProfilerInfo().autoStopProfiler +
+                            " mStreamingOutput=" + mProfileData.getProfilerInfo().streamingOutput);
                     pw.println("  mProfileType=" + mProfileType);
                 }
             }
@@ -10271,19 +10301,26 @@
 
         if (mTrackAllocationApp != null) {
             if (dumpPackage == null || dumpPackage.equals(mTrackAllocationApp)) {
-                proto.write(ActivityManagerServiceDumpProcessesProto.TRACK_ALLOCATION_APP, mTrackAllocationApp);
+                proto.write(ActivityManagerServiceDumpProcessesProto.TRACK_ALLOCATION_APP,
+                        mTrackAllocationApp);
             }
         }
 
-        if (mProfileApp != null || mProfileProc != null || (mProfilerInfo != null &&
-                (mProfilerInfo.profileFile != null || mProfilerInfo.profileFd != null))) {
-            if (dumpPackage == null || dumpPackage.equals(mProfileApp)) {
+        if (mProfileData.getProfileApp() != null || mProfileData.getProfileProc() != null
+                || (mProfileData.getProfilerInfo() != null &&
+                (mProfileData.getProfilerInfo().profileFile != null
+                        || mProfileData.getProfilerInfo().profileFd != null))) {
+            if (dumpPackage == null || dumpPackage.equals(mProfileData.getProfileApp())) {
                 final long token = proto.start(ActivityManagerServiceDumpProcessesProto.PROFILE);
-                proto.write(ActivityManagerServiceDumpProcessesProto.Profile.APP_NAME, mProfileApp);
-                mProfileProc.writeToProto(proto,ActivityManagerServiceDumpProcessesProto.Profile.PROC);
-                if (mProfilerInfo != null) {
-                    mProfilerInfo.writeToProto(proto, ActivityManagerServiceDumpProcessesProto.Profile.INFO);
-                    proto.write(ActivityManagerServiceDumpProcessesProto.Profile.TYPE, mProfileType);
+                proto.write(ActivityManagerServiceDumpProcessesProto.Profile.APP_NAME,
+                        mProfileData.getProfileApp());
+                mProfileData.getProfileProc().writeToProto(proto,
+                        ActivityManagerServiceDumpProcessesProto.Profile.PROC);
+                if (mProfileData.getProfilerInfo() != null) {
+                    mProfileData.getProfilerInfo().writeToProto(proto,
+                            ActivityManagerServiceDumpProcessesProto.Profile.INFO);
+                    proto.write(ActivityManagerServiceDumpProcessesProto.Profile.TYPE,
+                            mProfileType);
                 }
                 proto.end(token);
             }
@@ -13148,8 +13185,15 @@
     }
 
     public int bindService(IApplicationThread caller, IBinder token, Intent service,
-            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
-            int userId) throws TransactionTooLargeException {
+            String resolvedType, IServiceConnection connection, int flags,
+            String callingPackage, int userId) throws TransactionTooLargeException {
+        return bindIsolatedService(caller, token, service, resolvedType, connection, flags,
+                null, callingPackage, userId);
+    }
+
+    public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
+            String resolvedType, IServiceConnection connection, int flags, String instanceName,
+            String callingPackage, int userId) throws TransactionTooLargeException {
         enforceNotIsolatedCaller("bindService");
 
         // Refuse possible leaked file descriptors
@@ -13163,7 +13207,7 @@
 
         synchronized(this) {
             return mServices.bindServiceLocked(caller, token, service,
-                    resolvedType, connection, flags, callingPackage, userId);
+                    resolvedType, connection, flags, instanceName, callingPackage, userId);
         }
     }
 
@@ -15796,7 +15840,7 @@
                                     mayBeTop = true;
                                     mayBeTopType = "service";
                                     mayBeTopSource = cr.binding.client;
-                                    mayBeTopTarget = s.name;
+                                    mayBeTopTarget = s.instanceName;
                                     clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                                 } else {
                                     // Special handling for above-top states (persistent
@@ -15850,7 +15894,7 @@
                                     .REASON_SERVICE_IN_USE;
                             app.adjSource = cr.binding.client;
                             app.adjSourceProcState = clientProcState;
-                            app.adjTarget = s.name;
+                            app.adjTarget = s.instanceName;
                             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                 reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
                                         + ": " + app + ", due to " + cr.binding.client
@@ -15880,7 +15924,7 @@
                                     .REASON_SERVICE_IN_USE;
                             app.adjSource = a;
                             app.adjSourceProcState = procState;
-                            app.adjTarget = s.name;
+                            app.adjTarget = s.instanceName;
                             if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                 reportOomAdjMessageLocked(TAG_OOM_ADJ,
                                         "Raise to service w/activity: " + app);
@@ -17128,6 +17172,179 @@
     }
 
     @GuardedBy("this")
+    final boolean updateLowMemStateLocked(int numCached, int numEmpty, int numTrimming) {
+        final int N = mProcessList.getLruSizeLocked();
+        final long now = SystemClock.uptimeMillis();
+        // Now determine the memory trimming level of background processes.
+        // Unfortunately we need to start at the back of the list to do this
+        // properly.  We only do this if the number of background apps we
+        // are managing to keep around is less than half the maximum we desire;
+        // if we are keeping a good number around, we'll let them use whatever
+        // memory they want.
+        final int numCachedAndEmpty = numCached + numEmpty;
+        int memFactor;
+        if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
+                && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
+            if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
+                memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
+            } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
+                memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
+            } else {
+                memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
+            }
+        } else {
+            memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+        }
+        // We always allow the memory level to go up (better).  We only allow it to go
+        // down if we are in a state where that is allowed, *and* the total number of processes
+        // has gone down since last time.
+        if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor
+                + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
+                + " numProcs=" + mProcessList.getLruSizeLocked() + " last=" + mLastNumProcesses);
+        if (memFactor > mLastMemoryLevel) {
+            if (!mAllowLowerMemLevel || mProcessList.getLruSizeLocked() >= mLastNumProcesses) {
+                memFactor = mLastMemoryLevel;
+                if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
+            }
+        }
+        if (memFactor != mLastMemoryLevel) {
+            EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
+            StatsLog.write(StatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
+        }
+        mLastMemoryLevel = memFactor;
+        mLastNumProcesses = mProcessList.getLruSizeLocked();
+        boolean allChanged = mProcessStats.setMemFactorLocked(
+                memFactor, mAtmInternal != null ? !mAtmInternal.isSleeping() : true, now);
+        final int trackerMemFactor = mProcessStats.getMemFactorLocked();
+        if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
+            if (mLowRamStartTime == 0) {
+                mLowRamStartTime = now;
+            }
+            int step = 0;
+            int fgTrimLevel;
+            switch (memFactor) {
+                case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
+                    fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
+                    break;
+                case ProcessStats.ADJ_MEM_FACTOR_LOW:
+                    fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
+                    break;
+                default:
+                    fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
+                    break;
+            }
+            int factor = numTrimming/3;
+            int minFactor = 2;
+            if (mAtmInternal.getHomeProcess() != null) minFactor++;
+            if (mAtmInternal.getPreviousProcess() != null) minFactor++;
+            if (factor < minFactor) factor = minFactor;
+            int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
+            for (int i=N-1; i>=0; i--) {
+                ProcessRecord app = mProcessList.mLruProcesses.get(i);
+                if (allChanged || app.procStateChanged) {
+                    setProcessTrackerStateLocked(app, trackerMemFactor, now);
+                    app.procStateChanged = false;
+                }
+                if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
+                        && !app.killedByAm) {
+                    if (app.trimMemoryLevel < curLevel && app.thread != null) {
+                        try {
+                            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
+                                    "Trimming memory of " + app.processName + " to " + curLevel);
+                            app.thread.scheduleTrimMemory(curLevel);
+                        } catch (RemoteException e) {
+                        }
+                    }
+                    app.trimMemoryLevel = curLevel;
+                    step++;
+                    if (step >= factor) {
+                        step = 0;
+                        switch (curLevel) {
+                            case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
+                                curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
+                                break;
+                            case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
+                                curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
+                                break;
+                        }
+                    }
+                } else if (app.getCurProcState() == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
+                        && !app.killedByAm) {
+                    if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
+                            && app.thread != null) {
+                        try {
+                            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
+                                    "Trimming memory of heavy-weight " + app.processName
+                                    + " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
+                            app.thread.scheduleTrimMemory(
+                                    ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
+                        } catch (RemoteException e) {
+                        }
+                    }
+                    app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
+                } else {
+                    if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
+                            || app.systemNoUi) && app.hasPendingUiClean()) {
+                        // If this application is now in the background and it
+                        // had done UI, then give it the special trim level to
+                        // have it free UI resources.
+                        final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
+                        if (app.trimMemoryLevel < level && app.thread != null) {
+                            try {
+                                if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
+                                        "Trimming memory of bg-ui " + app.processName
+                                        + " to " + level);
+                                app.thread.scheduleTrimMemory(level);
+                            } catch (RemoteException e) {
+                            }
+                        }
+                        app.setPendingUiClean(false);
+                    }
+                    if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
+                        try {
+                            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
+                                    "Trimming memory of fg " + app.processName
+                                    + " to " + fgTrimLevel);
+                            app.thread.scheduleTrimMemory(fgTrimLevel);
+                        } catch (RemoteException e) {
+                        }
+                    }
+                    app.trimMemoryLevel = fgTrimLevel;
+                }
+            }
+        } else {
+            if (mLowRamStartTime != 0) {
+                mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
+                mLowRamStartTime = 0;
+            }
+            for (int i=N-1; i>=0; i--) {
+                ProcessRecord app = mProcessList.mLruProcesses.get(i);
+                if (allChanged || app.procStateChanged) {
+                    setProcessTrackerStateLocked(app, trackerMemFactor, now);
+                    app.procStateChanged = false;
+                }
+                if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
+                        || app.systemNoUi) && app.hasPendingUiClean()) {
+                    if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
+                            && app.thread != null) {
+                        try {
+                            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
+                                    "Trimming memory of ui hidden " + app.processName
+                                    + " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+                            app.thread.scheduleTrimMemory(
+                                    ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+                        } catch (RemoteException e) {
+                        }
+                    }
+                    app.setPendingUiClean(false);
+                }
+                app.trimMemoryLevel = 0;
+            }
+        }
+        return allChanged;
+    }
+
+    @GuardedBy("this")
     final void updateOomAdjLocked() {
         mOomAdjProfiler.oomAdjStarted();
         final ProcessRecord TOP_APP = getTopAppLocked();
@@ -17359,172 +17576,7 @@
 
         mNumServiceProcs = mNewNumServiceProcs;
 
-        // Now determine the memory trimming level of background processes.
-        // Unfortunately we need to start at the back of the list to do this
-        // properly.  We only do this if the number of background apps we
-        // are managing to keep around is less than half the maximum we desire;
-        // if we are keeping a good number around, we'll let them use whatever
-        // memory they want.
-        final int numCachedAndEmpty = numCached + numEmpty;
-        int memFactor;
-        if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
-                && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
-            if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
-                memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
-            } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
-                memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
-            } else {
-                memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
-            }
-        } else {
-            memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
-        }
-        // We always allow the memory level to go up (better).  We only allow it to go
-        // down if we are in a state where that is allowed, *and* the total number of processes
-        // has gone down since last time.
-        if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor
-                + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
-                + " numProcs=" + mProcessList.getLruSizeLocked() + " last=" + mLastNumProcesses);
-        if (memFactor > mLastMemoryLevel) {
-            if (!mAllowLowerMemLevel || mProcessList.getLruSizeLocked() >= mLastNumProcesses) {
-                memFactor = mLastMemoryLevel;
-                if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
-            }
-        }
-        if (memFactor != mLastMemoryLevel) {
-            EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
-            StatsLog.write(StatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
-        }
-        mLastMemoryLevel = memFactor;
-        mLastNumProcesses = mProcessList.getLruSizeLocked();
-        boolean allChanged = mProcessStats.setMemFactorLocked(
-                memFactor, mAtmInternal != null ? !mAtmInternal.isSleeping() : true, now);
-        final int trackerMemFactor = mProcessStats.getMemFactorLocked();
-        if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
-            if (mLowRamStartTime == 0) {
-                mLowRamStartTime = now;
-            }
-            int step = 0;
-            int fgTrimLevel;
-            switch (memFactor) {
-                case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
-                    fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
-                    break;
-                case ProcessStats.ADJ_MEM_FACTOR_LOW:
-                    fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
-                    break;
-                default:
-                    fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
-                    break;
-            }
-            int factor = numTrimming/3;
-            int minFactor = 2;
-            if (mAtmInternal.getHomeProcess() != null) minFactor++;
-            if (mAtmInternal.getPreviousProcess() != null) minFactor++;
-            if (factor < minFactor) factor = minFactor;
-            int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
-            for (int i=N-1; i>=0; i--) {
-                ProcessRecord app = mProcessList.mLruProcesses.get(i);
-                if (allChanged || app.procStateChanged) {
-                    setProcessTrackerStateLocked(app, trackerMemFactor, now);
-                    app.procStateChanged = false;
-                }
-                if (app.getCurProcState() >= ActivityManager.PROCESS_STATE_HOME
-                        && !app.killedByAm) {
-                    if (app.trimMemoryLevel < curLevel && app.thread != null) {
-                        try {
-                            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
-                                    "Trimming memory of " + app.processName + " to " + curLevel);
-                            app.thread.scheduleTrimMemory(curLevel);
-                        } catch (RemoteException e) {
-                        }
-                    }
-                    app.trimMemoryLevel = curLevel;
-                    step++;
-                    if (step >= factor) {
-                        step = 0;
-                        switch (curLevel) {
-                            case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
-                                curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
-                                break;
-                            case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
-                                curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
-                                break;
-                        }
-                    }
-                } else if (app.getCurProcState() == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
-                        && !app.killedByAm) {
-                    if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
-                            && app.thread != null) {
-                        try {
-                            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
-                                    "Trimming memory of heavy-weight " + app.processName
-                                    + " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
-                            app.thread.scheduleTrimMemory(
-                                    ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
-                        } catch (RemoteException e) {
-                        }
-                    }
-                    app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
-                } else {
-                    if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
-                            || app.systemNoUi) && app.hasPendingUiClean()) {
-                        // If this application is now in the background and it
-                        // had done UI, then give it the special trim level to
-                        // have it free UI resources.
-                        final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
-                        if (app.trimMemoryLevel < level && app.thread != null) {
-                            try {
-                                if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
-                                        "Trimming memory of bg-ui " + app.processName
-                                        + " to " + level);
-                                app.thread.scheduleTrimMemory(level);
-                            } catch (RemoteException e) {
-                            }
-                        }
-                        app.setPendingUiClean(false);
-                    }
-                    if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
-                        try {
-                            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
-                                    "Trimming memory of fg " + app.processName
-                                    + " to " + fgTrimLevel);
-                            app.thread.scheduleTrimMemory(fgTrimLevel);
-                        } catch (RemoteException e) {
-                        }
-                    }
-                    app.trimMemoryLevel = fgTrimLevel;
-                }
-            }
-        } else {
-            if (mLowRamStartTime != 0) {
-                mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
-                mLowRamStartTime = 0;
-            }
-            for (int i=N-1; i>=0; i--) {
-                ProcessRecord app = mProcessList.mLruProcesses.get(i);
-                if (allChanged || app.procStateChanged) {
-                    setProcessTrackerStateLocked(app, trackerMemFactor, now);
-                    app.procStateChanged = false;
-                }
-                if ((app.getCurProcState() >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
-                        || app.systemNoUi) && app.hasPendingUiClean()) {
-                    if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
-                            && app.thread != null) {
-                        try {
-                            if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
-                                    "Trimming memory of ui hidden " + app.processName
-                                    + " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
-                            app.thread.scheduleTrimMemory(
-                                    ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
-                        } catch (RemoteException e) {
-                        }
-                    }
-                    app.setPendingUiClean(false);
-                }
-                app.trimMemoryLevel = 0;
-            }
-        }
+        boolean allChanged = updateLowMemStateLocked(numCached, numEmpty, numTrimming);
 
         if (mAlwaysFinishActivities) {
             // Need to do this on its own message because the stack may not
@@ -18040,8 +18092,8 @@
     }
 
     private void stopProfilerLocked(ProcessRecord proc, int profileType) {
-        if (proc == null || proc == mProfileProc) {
-            proc = mProfileProc;
+        if (proc == null || proc == mProfileData.getProfileProc()) {
+            proc = mProfileData.getProfileProc();
             profileType = mProfileType;
             clearProfilerLocked();
         }
@@ -18056,15 +18108,16 @@
     }
 
     void clearProfilerLocked() {
-        if (mProfilerInfo !=null && mProfilerInfo.profileFd != null) {
+        if (mProfileData.getProfilerInfo() != null
+                && mProfileData.getProfilerInfo().profileFd != null) {
             try {
-                mProfilerInfo.profileFd.close();
+                mProfileData.getProfilerInfo().profileFd.close();
             } catch (IOException e) {
             }
         }
-        mProfileApp = null;
-        mProfileProc = null;
-        mProfilerInfo = null;
+        mProfileData.setProfileApp(null);
+        mProfileData.setProfileProc(null);
+        mProfileData.setProfilerInfo(null);
     }
 
     public boolean profileControl(String process, int userId, boolean start,
@@ -18096,7 +18149,7 @@
                 if (start) {
                     stopProfilerLocked(null, 0);
                     setProfileApp(proc.info, proc.processName, profilerInfo);
-                    mProfileProc = proc;
+                    mProfileData.setProfileProc(proc);
                     mProfileType = profileType;
                     ParcelFileDescriptor fd = profilerInfo.profileFd;
                     try {
@@ -18108,10 +18161,10 @@
                     proc.thread.profilerControl(start, profilerInfo, profileType);
                     fd = null;
                     try {
-                        mProfilerInfo.profileFd.close();
+                        mProfileData.getProfilerInfo().profileFd.close();
                     } catch (IOException e) {
                     }
-                    mProfilerInfo.profileFd = null;
+                    mProfileData.getProfilerInfo().profileFd = null;
 
                     if (proc.pid == MY_PID) {
                         // When profiling the system server itself, avoid closing the file
@@ -18724,28 +18777,6 @@
         }
 
         @Override
-        public List<ProcessMemoryState> getMemoryStateForNativeProcesses() {
-            List<ProcessMemoryState> processMemoryStates = new ArrayList<>();
-            int[] pids = getPidsForCommands(MEMORY_STAT_INTERESTING_NATIVE_PROCESSES);
-            for (int i = 0; i < pids.length; i++) {
-                int pid = pids[i];
-                MemoryStat memoryStat = readMemoryStatFromProcfs(pid);
-                if (memoryStat == null) {
-                    continue;
-                }
-                int uid = getUidForPid(pid);
-                String processName = readCmdlineFromProcfs(pid);
-                int oomScore = -1; // Unused, not included in the NativeProcessMemoryState atom.
-                ProcessMemoryState processMemoryState = new ProcessMemoryState(uid, processName,
-                        oomScore, memoryStat.pgfault, memoryStat.pgmajfault,
-                        memoryStat.rssInBytes, memoryStat.cacheInBytes, memoryStat.swapInBytes,
-                        memoryStat.rssHighWatermarkInBytes, memoryStat.startTimeNanos);
-                processMemoryStates.add(processMemoryState);
-            }
-            return processMemoryStates;
-        }
-
-        @Override
         public int handleIncomingUser(int callingPid, int callingUid, int userId,
                 boolean allowAll, int allowMode, String name, String callerPackage) {
             return mUserController.handleIncomingUser(callingPid, callingUid, userId, allowAll,
@@ -19115,25 +19146,47 @@
 
         @Override
         public void setDebugFlagsForStartingActivity(ActivityInfo aInfo, int startFlags,
-                ProfilerInfo profilerInfo) {
+                ProfilerInfo profilerInfo, Object wmLock) {
             synchronized (ActivityManagerService.this) {
-                if ((startFlags & ActivityManager.START_FLAG_DEBUG) != 0) {
-                    setDebugApp(aInfo.processName, true, false);
-                }
+                /**
+                 * This function is called from the window manager context and needs to be executed
+                 * synchronously.  To avoid deadlock, we pass a message to AMS to execute the
+                 * function and notify the passed in lock when it has been completed.
+                 */
+                synchronized (wmLock) {
+                    if ((startFlags & ActivityManager.START_FLAG_DEBUG) != 0) {
+                        setDebugApp(aInfo.processName, true, false);
+                    }
 
-                if ((startFlags & ActivityManager.START_FLAG_NATIVE_DEBUGGING) != 0) {
-                    setNativeDebuggingAppLocked(aInfo.applicationInfo, aInfo.processName);
-                }
+                    if ((startFlags & ActivityManager.START_FLAG_NATIVE_DEBUGGING) != 0) {
+                        setNativeDebuggingAppLocked(aInfo.applicationInfo, aInfo.processName);
+                    }
 
-                if ((startFlags & ActivityManager.START_FLAG_TRACK_ALLOCATION) != 0) {
-                    setTrackAllocationApp(aInfo.applicationInfo, aInfo.processName);
-                }
+                    if ((startFlags & ActivityManager.START_FLAG_TRACK_ALLOCATION) != 0) {
+                        setTrackAllocationApp(aInfo.applicationInfo, aInfo.processName);
+                    }
 
-                if (profilerInfo != null) {
-                    setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo);
+                    if (profilerInfo != null) {
+                        setProfileApp(aInfo.applicationInfo, aInfo.processName, profilerInfo);
+                    }
+                    wmLock.notify();
                 }
             }
         }
+
+        @Override
+        public boolean isAppStorageSandboxed(int pid, int uid) {
+            if (!SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+                return false;
+            }
+            if (uid == SHELL_UID || uid == ROOT_UID) {
+                return false;
+            }
+            synchronized (mPidsSelfLocked) {
+                final ProcessRecord pr = mPidsSelfLocked.get(pid);
+                return pr == null || pr.mountMode != Zygote.MOUNT_EXTERNAL_FULL;
+            }
+        }
     }
 
     long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
@@ -19422,7 +19475,8 @@
     }
 
     @Override
-    public void startDelegateShellPermissionIdentity(int delegateUid) {
+    public void startDelegateShellPermissionIdentity(int delegateUid,
+            @Nullable String[] permissions) {
         if (UserHandle.getCallingAppId() != Process.SHELL_UID
                 && UserHandle.getCallingAppId() != Process.ROOT_UID) {
             throw new SecurityException("Only the shell can delegate its permissions");
@@ -19441,11 +19495,13 @@
                 if (!(mAppOpsService.getAppOpsServiceDelegate() instanceof ShellDelegate)) {
                     throw new IllegalStateException("Bad shell delegate state");
                 }
-                if (((ShellDelegate) mAppOpsService.getAppOpsServiceDelegate())
-                        .getDelegateUid() != delegateUid) {
+                final ShellDelegate delegate = (ShellDelegate) mAppOpsService
+                        .getAppOpsServiceDelegate();
+                if (delegate.getDelegateUid() != delegateUid) {
                     throw new SecurityException("Shell can delegate permissions only "
                             + "to one instrumentation at a time");
                 }
+                delegate.setPermissions(permissions);
                 return;
             }
 
@@ -19463,7 +19519,7 @@
 
                 // Hook them up...
                 final ShellDelegate shellDelegate = new ShellDelegate(
-                        instr.mTargetInfo.packageName, delegateUid);
+                        instr.mTargetInfo.packageName, delegateUid, permissions);
                 mAppOpsService.setAppOpsServiceDelegate(shellDelegate);
                 getPackageManagerInternalLocked().setCheckPermissionDelegate(shellDelegate);
                 return;
@@ -19486,20 +19542,26 @@
     private class ShellDelegate implements CheckOpsDelegate, CheckPermissionDelegate {
         private final String mTargetPackageName;
         private final int mTargetUid;
+        private @Nullable String[] mPermissions;
 
-        ShellDelegate(String targetPacakgeName, int targetUid) {
+        ShellDelegate(String targetPacakgeName, int targetUid, @Nullable String[] permissions) {
             mTargetPackageName = targetPacakgeName;
             mTargetUid = targetUid;
+            mPermissions = permissions;
         }
 
         int getDelegateUid() {
             return mTargetUid;
         }
 
+        void setPermissions(@Nullable String[] permissions) {
+            mPermissions = permissions;
+        }
+
         @Override
         public int checkOperation(int code, int uid, String packageName,
                 TriFunction<Integer, Integer, String, Integer> superImpl) {
-            if (uid == mTargetUid) {
+            if (uid == mTargetUid && isTargetOp(code)) {
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     return superImpl.apply(code, Process.SHELL_UID,
@@ -19514,7 +19576,7 @@
         @Override
         public int checkAudioOperation(int code, int usage, int uid, String packageName,
                 QuadFunction<Integer, Integer, Integer, String, Integer> superImpl) {
-            if (uid == mTargetUid) {
+            if (uid == mTargetUid && isTargetOp(code)) {
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     return superImpl.apply(code, usage, Process.SHELL_UID,
@@ -19529,7 +19591,7 @@
         @Override
         public int noteOperation(int code, int uid, String packageName,
                 TriFunction<Integer, Integer, String, Integer> superImpl) {
-            if (uid == mTargetUid) {
+            if (uid == mTargetUid && isTargetOp(code)) {
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     return mAppOpsService.noteProxyOperation(code, Process.SHELL_UID,
@@ -19544,7 +19606,7 @@
         @Override
         public int checkPermission(String permName, String pkgName, int userId,
                 TriFunction<String, String, Integer, Integer> superImpl) {
-            if (mTargetPackageName.equals(pkgName)) {
+            if (mTargetPackageName.equals(pkgName) && isTargetPermission(permName)) {
                 return superImpl.apply(permName, "com.android.shell", userId);
             }
             return superImpl.apply(permName, pkgName, userId);
@@ -19553,11 +19615,29 @@
         @Override
         public int checkUidPermission(String permName, int uid,
                 BiFunction<String, Integer, Integer> superImpl) {
-            if (uid == mTargetUid) {
+            if (uid == mTargetUid  && isTargetPermission(permName)) {
                 return superImpl.apply(permName, Process.SHELL_UID);
             }
             return superImpl.apply(permName, uid);
         }
+
+        private boolean isTargetOp(int code) {
+            // null permissions means all ops are targeted
+            if (mPermissions == null) {
+                return true;
+            }
+            // no permission for the op means the op is targeted
+            final String permission = AppOpsManager.opToPermission(code);
+            if (permission == null) {
+                return true;
+            }
+            return isTargetPermission(permission);
+        }
+
+        private boolean isTargetPermission(@NonNull String permission) {
+            // null permissions means all permissions are targeted
+            return (mPermissions == null || ArrayUtils.contains(mPermissions, permission));
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index fe402ea..9018006 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2105,8 +2105,13 @@
         }
 
         FeatureInfo[] features = pm.getSystemAvailableFeatures();
-        Arrays.sort(features, (o1, o2) ->
-                (o1.name == o2.name ? 0 : (o1.name == null ? -1 : o1.name.compareTo(o2.name))));
+        Arrays.sort(features, (o1, o2) -> {
+            if (o1.name == o2.name) return 0;
+            if (o1.name == null) return -1;
+            if (o2.name == null) return 1;
+            return o1.name.compareTo(o2.name);
+        });
+
         for (int i = 0; i < features.length; i++) {
             if (features[i].name != null) {
                 if (protoOutputStream != null) {
diff --git a/services/core/java/com/android/server/am/AppBindRecord.java b/services/core/java/com/android/server/am/AppBindRecord.java
index 4eaebd0..9870420 100644
--- a/services/core/java/com/android/server/am/AppBindRecord.java
+++ b/services/core/java/com/android/server/am/AppBindRecord.java
@@ -59,12 +59,12 @@
     public String toString() {
         return "AppBindRecord{"
             + Integer.toHexString(System.identityHashCode(this))
-            + " " + service.shortName + ":" + client.processName + "}";
+            + " " + service.shortInstanceName + ":" + client.processName + "}";
     }
 
     void writeToProto(ProtoOutputStream proto, long fieldId) {
         long token = proto.start(fieldId);
-        proto.write(AppBindRecordProto.SERVICE_NAME, service.shortName);
+        proto.write(AppBindRecordProto.SERVICE_NAME, service.shortInstanceName);
         proto.write(AppBindRecordProto.CLIENT_PROC_NAME, client.processName);
         final int N = connections.size();
         for (int i=0; i<N; i++) {
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index 37d07bb..bfa3f66 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -115,16 +115,16 @@
                 && (binding.service.appInfo.uid != clientUid
                         || !binding.service.processName.equals(clientProcessName))) {
             ProcessStats.ProcessStateHolder holder = binding.service.app.pkgList.get(
-                    binding.service.name.getPackageName());
+                    binding.service.instanceName.getPackageName());
             if (holder == null) {
                 Slog.wtf(TAG_AM, "No package in referenced service "
-                        + binding.service.name.toShortString() + ": proc=" + binding.service.app);
+                        + binding.service.shortInstanceName + ": proc=" + binding.service.app);
             } else if (holder.pkg == null) {
                 Slog.wtf(TAG_AM, "Inactive holder in referenced service "
-                        + binding.service.name.toShortString() + ": proc=" + binding.service.app);
+                        + binding.service.shortInstanceName + ": proc=" + binding.service.app);
             } else {
                 association = holder.pkg.getAssociationStateLocked(holder.state,
-                        binding.service.name.getClassName()).startSource(clientUid,
+                        binding.service.instanceName.getClassName()).startSource(clientUid,
                         clientProcessName);
 
             }
@@ -202,7 +202,7 @@
         if (serviceDead) {
             sb.append("DEAD ");
         }
-        sb.append(binding.service.shortName);
+        sb.append(binding.service.shortInstanceName);
         sb.append(":@");
         sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
         sb.append('}');
@@ -223,7 +223,7 @@
             proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.DEAD);
         }
         if (binding.service != null) {
-            proto.write(ConnectionRecordProto.SERVICE_NAME, binding.service.shortName);
+            proto.write(ConnectionRecordProto.SERVICE_NAME, binding.service.shortInstanceName);
         }
         proto.end(token);
     }
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 968c17f..9cfd39c 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -61,6 +61,9 @@
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS, String.class);
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS_GLES, String.class);
         sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYER_APP, String.class);
+        sGlobalSettingToTypeMap.put(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, int.class);
+        sGlobalSettingToTypeMap.put(Settings.Global.UPDATED_GFX_DRIVER_DEV_OPT_IN_APP,
+                                    String.class);
         // add other global settings here...
     }
 
diff --git a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
deleted file mode 100644
index 1366c21..0000000
--- a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2018 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.content.ContentResolver;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Build;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Slog;
-import android.view.ThreadedRenderer;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
-
-/**
- * Maps global system settings to system properties.
- * <p>The properties are dynamically updated when settings change.
- */
-class GlobalSettingsToPropertiesMapper {
-
-    private static final String TAG = "GlobalSettingsToPropertiesMapper";
-
-    // List mapping entries in the following format:
-    // {Settings.Global.SETTING_NAME, "system_property_name"}
-    // Important: Property being added should be whitelisted by SELinux policy or have one of the
-    // already whitelisted prefixes in system_server.te, e.g. sys.
-    private static final String[][] sGlobalSettingsMapping = new String[][] {
-        {Settings.Global.SYS_VDSO, "sys.vdso"},
-        {Settings.Global.FPS_DEVISOR, ThreadedRenderer.DEBUG_FPS_DIVISOR},
-        {Settings.Global.DISPLAY_PANEL_LPM, "sys.display_panel_lpm"},
-        {Settings.Global.SYS_UIDCPUPOWER, "sys.uidcpupower"},
-        {Settings.Global.SYS_TRACED, "sys.traced.enable_override"},
-    };
-
-
-    private final ContentResolver mContentResolver;
-    private final String[][] mGlobalSettingsMapping;
-
-    @VisibleForTesting
-    GlobalSettingsToPropertiesMapper(ContentResolver contentResolver,
-            String[][] globalSettingsMapping) {
-        mContentResolver = contentResolver;
-        mGlobalSettingsMapping = globalSettingsMapping;
-    }
-
-    void updatePropertiesFromGlobalSettings() {
-        for (String[] entry : mGlobalSettingsMapping) {
-            final String settingName = entry[0];
-            final String propName = entry[1];
-            Uri settingUri = Settings.Global.getUriFor(settingName);
-            Preconditions.checkNotNull(settingUri, "Setting " + settingName + " not found");
-            ContentObserver co = new ContentObserver(null) {
-                @Override
-                public void onChange(boolean selfChange) {
-                    updatePropertyFromSetting(settingName, propName);
-                }
-            };
-            updatePropertyFromSetting(settingName, propName);
-            mContentResolver.registerContentObserver(settingUri, false, co);
-        }
-    }
-
-    public static void start(ContentResolver contentResolver) {
-        new GlobalSettingsToPropertiesMapper(contentResolver, sGlobalSettingsMapping)
-                .updatePropertiesFromGlobalSettings();
-    }
-
-    private String getGlobalSetting(String name) {
-        return Settings.Global.getString(mContentResolver, name);
-    }
-
-    private void setProperty(String key, String value) {
-        // Check if need to clear the property
-        if (value == null) {
-            // It's impossible to remove system property, therefore we check previous value to
-            // avoid setting an empty string if the property wasn't set.
-            if (TextUtils.isEmpty(systemPropertiesGet(key))) {
-                return;
-            }
-            value = "";
-        }
-        try {
-            systemPropertiesSet(key, value);
-        } catch (Exception e) {
-            // Failure to set a property can be caused by SELinux denial. This usually indicates
-            // that the property wasn't whitelisted in sepolicy.
-            // No need to report it on all user devices, only on debug builds.
-            if (Build.IS_DEBUGGABLE) {
-                Slog.wtf(TAG, "Unable to set property " + key + " value '" + value + "'", e);
-            } else {
-                Slog.e(TAG, "Unable to set property " + key + " value '" + value + "'", e);
-            }
-        }
-    }
-
-    @VisibleForTesting
-    protected String systemPropertiesGet(String key) {
-        return SystemProperties.get(key);
-    }
-
-    @VisibleForTesting
-    protected void systemPropertiesSet(String key, String value) {
-        SystemProperties.set(key, value);
-    }
-
-    @VisibleForTesting
-    void updatePropertyFromSetting(String settingName, String propName) {
-        String settingValue = getGlobalSetting(settingName);
-        setProperty(propName, settingValue);
-    }
-}
diff --git a/services/core/java/com/android/server/am/IntentBindRecord.java b/services/core/java/com/android/server/am/IntentBindRecord.java
index 839b6e1..90aef3e 100644
--- a/services/core/java/com/android/server/am/IntentBindRecord.java
+++ b/services/core/java/com/android/server/am/IntentBindRecord.java
@@ -99,7 +99,7 @@
         if ((collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
             sb.append("CR ");
         }
-        sb.append(service.shortName);
+        sb.append(service.shortInstanceName);
         sb.append(':');
         if (intent != null) {
             intent.getIntent().toShortString(sb, false, false, false, false);
diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java
index c978c13..80b4f77 100644
--- a/services/core/java/com/android/server/am/MemoryStatUtil.java
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -16,9 +16,9 @@
 
 package com.android.server.am;
 
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
 
 import android.annotation.Nullable;
 import android.os.FileUtils;
@@ -45,7 +45,7 @@
      * <p>Processes are matched by their cmdline in procfs. Example: cat /proc/pid/cmdline returns
      * /system/bin/statsd for the stats daemon.
      */
-    static final String[] MEMORY_STAT_INTERESTING_NATIVE_PROCESSES = new String[]{
+    public static final String[] MEMORY_STAT_INTERESTING_NATIVE_PROCESSES = new String[]{
             "/system/bin/statsd",  // Stats daemon.
             "/system/bin/surfaceflinger",
             "/system/bin/apexd",  // APEX daemon.
@@ -146,7 +146,7 @@
      * Returns null if file is not found in procfs or if file has unrecognized contents.
      */
     @Nullable
-    static MemoryStat readMemoryStatFromProcfs(int pid) {
+    public static MemoryStat readMemoryStatFromProcfs(int pid) {
         final String statPath = String.format(Locale.US, PROC_STAT_FILE_FMT, pid);
         MemoryStat stat = parseMemoryStatFromProcfs(readFileContents(statPath));
         if (stat == null) {
@@ -163,7 +163,7 @@
      * Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
      * if the file is not available.
      */
-    static String readCmdlineFromProcfs(int pid) {
+    public static String readCmdlineFromProcfs(int pid) {
         String path = String.format(Locale.US, PROC_CMDLINE_FILE_FMT, pid);
         String cmdline = readFileContents(path);
         return cmdline != null ? cmdline : "";
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 79c98e5..5208ca5 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -27,4 +27,4 @@
 michaelwr@google.com
 narayan@google.com
 
-per-file GlobalSettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com
+per-file SettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 93c8391..84b364b 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -97,18 +97,18 @@
 
 import dalvik.system.VMRuntime;
 
+import libcore.io.IoUtils;
+
 import java.io.File;
 import java.io.IOException;
-import java.io.OutputStream;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import libcore.io.IoUtils;
-
 /**
  * Activity manager code dealing with processes.
  *
@@ -1311,6 +1311,7 @@
                 if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2];
                 if (gids[1] == UserHandle.ERR_GID) gids[1] = gids[2];
             }
+            app.mountMode = mountExternal;
             checkSlow(startTime, "startProcess: building args");
             if (mService.mAtmInternal.isFactoryTestProcess(app.getWindowProcessController())) {
                 uid = 0;
@@ -1362,8 +1363,7 @@
 
             if (!disableHiddenApiChecks && !mService.mHiddenApiBlacklist.isDisabled()) {
                 app.info.maybeUpdateHiddenApiEnforcementPolicy(
-                        mService.mHiddenApiBlacklist.getPolicyForPrePApps(),
-                        mService.mHiddenApiBlacklist.getPolicyForPApps());
+                        mService.mHiddenApiBlacklist.getPolicy());
                 @ApplicationInfo.HiddenApiEnforcementPolicy int policy =
                         app.info.getHiddenApiEnforcementPolicy();
                 int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index bb87ad0..745c1263 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -28,7 +28,6 @@
 import android.app.ApplicationErrorReport;
 import android.app.Dialog;
 import android.app.IApplicationThread;
-import android.app.ProfilerInfo;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -57,11 +56,11 @@
 import com.android.internal.app.procstats.ProcessStats;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.ProcessCpuTracker;
+import com.android.internal.os.Zygote;
 import com.android.server.wm.WindowProcessController;
 import com.android.server.wm.WindowProcessListener;
 
 import java.io.File;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -263,6 +262,7 @@
     boolean pendingStart;       // Process start is pending.
     long startSeq;              // Seq no. indicating the latest process start associated with
                                 // this process record.
+    int mountMode;              // Indicates how the external storage was mounted for this process.
 
     // These reports are generated & stored when an app gets into an error condition.
     // They will be "null" when all is OK.
@@ -443,6 +443,8 @@
             pw.print(prefix); pw.print("pendingStart="); pw.println(pendingStart);
         }
         pw.print(prefix); pw.print("startSeq="); pw.println(startSeq);
+        pw.print(prefix); pw.print("mountMode="); pw.println(
+                DebugUtils.valueToString(Zygote.class, "MOUNT_EXTERNAL_", mountMode));
         if (setProcState > ActivityManager.PROCESS_STATE_SERVICE) {
             pw.print(prefix); pw.print("lastCpuTime="); pw.print(lastCpuTime);
                     if (lastCpuTime > 0) {
@@ -1123,8 +1125,9 @@
     @Override
     public void clearProfilerIfNeeded() {
         synchronized (mService) {
-            if (mService.mProfileProc == null || mService.mProfilerInfo == null
-                    || mService.mProfileProc != this) {
+            if (mService.mProfileData.getProfileProc() == null
+                    || mService.mProfileData.getProfilerInfo() == null
+                    || mService.mProfileData.getProfileProc() != this) {
                 return;
             }
             mService.clearProfilerLocked();
@@ -1198,32 +1201,15 @@
     }
 
     @Override
-    public ProfilerInfo onStartActivity(int topProcessState) {
+    public void onStartActivity(int topProcessState, boolean setProfileProc) {
         synchronized (mService) {
-            ProfilerInfo profilerInfo = null;
-            if (mService.mProfileApp != null && mService.mProfileApp.equals(processName)) {
-                if (mService.mProfileProc == null || mService.mProfileProc == this) {
-                    mService.mProfileProc = this;
-                    final ProfilerInfo profilerInfoSvc = mService.mProfilerInfo;
-                    if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) {
-                        if (profilerInfoSvc.profileFd != null) {
-                            try {
-                                profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup();
-                            } catch (IOException e) {
-                                profilerInfoSvc.closeFd();
-                            }
-                        }
-
-                        profilerInfo = new ProfilerInfo(profilerInfoSvc);
-                    }
-                }
+            if (setProfileProc) {
+                mService.mProfileData.setProfileProc(this);
             }
 
             hasShownUi = true;
             setPendingUiClean(true);
             forceProcessStateUpTo(topProcessState);
-
-            return profilerInfo;
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index d8f94c9..09f8c3e 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -70,7 +70,8 @@
     final ActivityManagerService ams;
     final BatteryStatsImpl.Uid.Pkg.Serv stats;
     final ComponentName name; // service component.
-    final String shortName; // name.flattenToShortString().
+    final ComponentName instanceName; // service component's per-instance name.
+    final String shortInstanceName; // instanceName.flattenToShortString().
     final Intent.FilterComparison intent;
                             // original intent used to find service.
     final ServiceInfo serviceInfo;
@@ -190,7 +191,7 @@
             StringBuilder sb = new StringBuilder(128);
             sb.append("ServiceRecord{")
                 .append(Integer.toHexString(System.identityHashCode(sr)))
-                .append(' ').append(sr.shortName)
+                .append(' ').append(sr.shortInstanceName)
                 .append(" StartItem ")
                 .append(Integer.toHexString(System.identityHashCode(this)))
                 .append(" id=").append(id).append('}');
@@ -235,7 +236,7 @@
 
     void writeToProto(ProtoOutputStream proto, long fieldId) {
         long token = proto.start(fieldId);
-        proto.write(ServiceRecordProto.SHORT_NAME, this.shortName);
+        proto.write(ServiceRecordProto.SHORT_NAME, this.shortInstanceName);
         proto.write(ServiceRecordProto.IS_RUNNING, app != null);
         if (app != null) {
             proto.write(ServiceRecordProto.PID, app.pid);
@@ -448,12 +449,14 @@
 
     ServiceRecord(ActivityManagerService ams,
             BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name,
+            ComponentName instanceName,
             Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg,
             Runnable restarter) {
         this.ams = ams;
         this.stats = servStats;
         this.name = name;
-        shortName = name.flattenToShortString();
+        this.instanceName = instanceName;
+        shortInstanceName = instanceName.flattenToShortString();
         this.intent = intent;
         serviceInfo = sInfo;
         appInfo = sInfo.applicationInfo;
@@ -618,7 +621,7 @@
                             // those dirty apps we will create a notification clearly
                             // blaming the app.
                             Slog.v(TAG, "Attempted to start a foreground service ("
-                                    + name
+                                    + shortInstanceName
                                     + ") with a broken notification (no icon: "
                                     + localForegroundNoti
                                     + ")");
@@ -701,7 +704,7 @@
                         Slog.w(TAG, "Error showing notification for service", e);
                         // If it gave us a garbage notification, it doesn't
                         // get to be foreground.
-                        ams.setServiceForeground(name, ServiceRecord.this,
+                        ams.setServiceForeground(instanceName, ServiceRecord.this,
                                 0, null, 0);
                         ams.crashApplication(appUid, appPid, localPackageName, -1,
                                 "Bad notification for startForeground: " + e);
@@ -773,7 +776,7 @@
         sb.append("ServiceRecord{")
             .append(Integer.toHexString(System.identityHashCode(this)))
             .append(" u").append(userId)
-            .append(' ').append(shortName).append('}');
+            .append(' ').append(shortInstanceName).append('}');
         return stringName = sb.toString();
     }
 
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
new file mode 100644
index 0000000..a5848ca
--- /dev/null
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2018 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.content.ContentResolver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Build;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashSet;
+
+/**
+ * Maps system settings to system properties.
+ * <p>The properties are dynamically updated when settings change.
+ */
+class SettingsToPropertiesMapper {
+
+    private static final String TAG = "SettingsToPropertiesMapper";
+
+    private static final String SYSTEM_PROPERTY_PREFIX = "persist.device_config.";
+
+    private static final String RESET_PERFORMED_PROPERTY = "device_config.reset_performed";
+
+    private static final String RESET_RECORD_FILE_PATH =
+            "/data/server_configurable_flags/reset_flags";
+
+    private static final String SYSTEM_PROPERTY_VALID_CHARACTERS_REGEX = "^[\\w\\.\\-@:]*$";
+
+    private static final String SYSTEM_PROPERTY_INVALID_SUBSTRING = "..";
+
+    private static final int SYSTEM_PROPERTY_MAX_LENGTH = 92;
+
+    // experiment flags added to Global.Settings(before new "Config" provider table is available)
+    // will be added under this category.
+    private static final String GLOBAL_SETTINGS_CATEGORY = "global_settings";
+
+    // Add the global setting you want to push to native level as experiment flag into this list.
+    //
+    // NOTE: please grant write permission system property prefix
+    // with format persist.experiment.[experiment_category_name]. in system_server.te and grant read
+    // permission in the corresponding .te file your feature belongs to.
+    @VisibleForTesting
+    static final String[] sGlobalSettings = new String[] {
+    };
+
+    @VisibleForTesting
+    static final String[] sDeviceConfigScopes = new String[] {
+    };
+
+    private final String[] mGlobalSettings;
+
+    private final String[] mDeviceConfigScopes;
+
+    private final ContentResolver mContentResolver;
+
+    @VisibleForTesting
+    protected SettingsToPropertiesMapper(ContentResolver contentResolver,
+            String[] globalSettings,
+            String[] deviceConfigScopes) {
+        mContentResolver = contentResolver;
+        mGlobalSettings = globalSettings;
+        mDeviceConfigScopes = deviceConfigScopes;
+    }
+
+    @VisibleForTesting
+    void updatePropertiesFromSettings() {
+        for (String globalSetting : mGlobalSettings) {
+            Uri settingUri = Settings.Global.getUriFor(globalSetting);
+            String propName = makePropertyName(GLOBAL_SETTINGS_CATEGORY, globalSetting);
+            if (settingUri == null) {
+                log("setting uri is null for globalSetting " + globalSetting);
+                continue;
+            }
+            if (propName == null) {
+                log("invalid prop name for globalSetting " + globalSetting);
+                continue;
+            }
+
+            ContentObserver co = new ContentObserver(null) {
+                @Override
+                public void onChange(boolean selfChange) {
+                    updatePropertyFromSetting(globalSetting, propName, true);
+                }
+            };
+
+            // only updating on starting up when no native flags reset is performed during current
+            // booting.
+            if (!isNativeFlagsResetPerformed()) {
+                updatePropertyFromSetting(globalSetting, propName, true);
+            }
+            mContentResolver.registerContentObserver(settingUri, false, co);
+        }
+
+        // TODO: address sDeviceConfigScopes after DeviceConfig APIs are available.
+    }
+
+    public static SettingsToPropertiesMapper start(ContentResolver contentResolver) {
+        SettingsToPropertiesMapper mapper =  new SettingsToPropertiesMapper(
+                contentResolver, sGlobalSettings, sDeviceConfigScopes);
+        mapper.updatePropertiesFromSettings();
+        return mapper;
+    }
+
+    /**
+     * If native level flags reset has been performed as an attempt to recover from a crash loop
+     * during current device booting.
+     * @return
+     */
+    public boolean isNativeFlagsResetPerformed() {
+        String value = systemPropertiesGet(RESET_PERFORMED_PROPERTY);
+        return "true".equals(value);
+    }
+
+    /**
+     * return an array of native flag categories under which flags got reset during current device
+     * booting.
+     * @return
+     */
+    public String[] getResetNativeCategories() {
+        if (!isNativeFlagsResetPerformed()) {
+            return new String[0];
+        }
+
+        String content = getResetFlagsFileContent();
+        if (TextUtils.isEmpty(content)) {
+            return new String[0];
+        }
+
+        String[] property_names = content.split(";");
+        HashSet<String> categories = new HashSet<>();
+        for (String property_name : property_names) {
+            String[] segments = property_name.split("\\.");
+            if (segments.length < 3) {
+                log("failed to extract category name from property " + property_name);
+                continue;
+            }
+            categories.add(segments[2]);
+        }
+        return categories.toArray(new String[0]);
+    }
+
+    /**
+     * system property name constructing rule: "persist.device_config.[category_name].[flag_name]".
+     * If the name contains invalid characters or substrings for system property name,
+     * will return null.
+     * @param categoryName
+     * @param flagName
+     * @return
+     */
+    @VisibleForTesting
+    static String makePropertyName(String categoryName, String flagName) {
+        String propertyName = SYSTEM_PROPERTY_PREFIX + categoryName + "." + flagName;
+
+        if (!propertyName.matches(SYSTEM_PROPERTY_VALID_CHARACTERS_REGEX)
+                || propertyName.contains(SYSTEM_PROPERTY_INVALID_SUBSTRING)) {
+            return null;
+        }
+
+        return propertyName;
+    }
+
+    private String getSetting(String name, boolean isGlobalSetting) {
+        if (isGlobalSetting) {
+            return Settings.Global.getString(mContentResolver, name);
+        } else {
+            // TODO: complete the code after DeviceConfig APIs implemented.
+            return null;
+        }
+    }
+
+    private void setProperty(String key, String value) {
+        // Check if need to clear the property
+        if (value == null) {
+            // It's impossible to remove system property, therefore we check previous value to
+            // avoid setting an empty string if the property wasn't set.
+            if (TextUtils.isEmpty(systemPropertiesGet(key))) {
+                return;
+            }
+            value = "";
+        } else if (value.length() > SYSTEM_PROPERTY_MAX_LENGTH) {
+            log(value + " exceeds system property max length.");
+            return;
+        }
+
+        try {
+            systemPropertiesSet(key, value);
+        } catch (Exception e) {
+            // Failure to set a property can be caused by SELinux denial. This usually indicates
+            // that the property wasn't whitelisted in sepolicy.
+            // No need to report it on all user devices, only on debug builds.
+            log("Unable to set property " + key + " value '" + value + "'", e);
+        }
+    }
+
+    private static void log(String msg, Exception e) {
+        if (Build.IS_DEBUGGABLE) {
+            Slog.wtf(TAG, msg, e);
+        } else {
+            Slog.e(TAG, msg, e);
+        }
+    }
+
+    private static void log(String msg) {
+        if (Build.IS_DEBUGGABLE) {
+            Slog.wtf(TAG, msg);
+        } else {
+            Slog.e(TAG, msg);
+        }
+    }
+
+    @VisibleForTesting
+    protected String systemPropertiesGet(String key) {
+        return SystemProperties.get(key);
+    }
+
+    @VisibleForTesting
+    protected void systemPropertiesSet(String key, String value) {
+        SystemProperties.set(key, value);
+    }
+
+    @VisibleForTesting
+    protected String getResetFlagsFileContent() {
+        String content = null;
+        try {
+            File reset_flag_file = new File(RESET_RECORD_FILE_PATH);
+            BufferedReader br = new BufferedReader(new FileReader(reset_flag_file));
+            content = br.readLine();
+
+            br.close();
+        } catch (IOException ioe) {
+            log("failed to read file " + RESET_RECORD_FILE_PATH, ioe);
+        }
+        return content;
+    }
+
+    @VisibleForTesting
+    void updatePropertyFromSetting(String settingName, String propName, boolean isGlobalSetting) {
+        String settingValue = getSetting(settingName, isGlobalSetting);
+        setProperty(propName, settingValue);
+    }
+}
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
index 61836fdd..2c2d404 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
@@ -358,7 +358,7 @@
             if (mBundle != null) {
                 try {
                     mStatusBarService.showBiometricDialog(mBundle, mDialogReceiver,
-                            getBiometricType(), mRequireConfirmation);
+                            getBiometricType(), mRequireConfirmation, getTargetUserId());
                 } catch (RemoteException e) {
                     Slog.e(getLogTag(), "Unable to show biometric dialog", e);
                 }
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 278c55f..5f09189 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -246,9 +246,20 @@
         public void authenticate(IBinder token, long sessionId, int userId,
                 IBiometricServiceReceiver receiver, int flags, String opPackageName,
                 Bundle bundle, IBiometricPromptReceiver dialogReceiver) throws RemoteException {
-            // Check the USE_BIOMETRIC permission here. In the BiometricServiceBase, check do the
-            // AppOps and foreground check.
-            checkPermission();
+            final int callingUid = Binder.getCallingUid();
+            final int callingPid = Binder.getCallingPid();
+            final int callingUserId = UserHandle.getCallingUserId();
+
+            // In the BiometricServiceBase, check do the AppOps and foreground check.
+            if (userId == callingUserId) {
+                // Check the USE_BIOMETRIC permission here.
+                checkPermission();
+            } else {
+                // Only allow internal clients to authenticate with a different userId
+                Slog.w(TAG, "User " + callingUserId + " is requesting authentication of userid: "
+                        + userId);
+                checkInternalPermission();
+            }
 
             if (token == null || receiver == null || opPackageName == null || bundle == null
                     || dialogReceiver == null) {
@@ -262,10 +273,6 @@
                 checkInternalPermission();
             }
 
-            final int callingUid = Binder.getCallingUid();
-            final int callingPid = Binder.getCallingPid();
-            final int callingUserId = UserHandle.getCallingUserId();
-
             mHandler.post(() -> {
                 final Pair<Integer, Integer> result = checkAndGetBiometricModality(callingUserId);
                 final int modality = result.first;
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 5d4263b..7aa2e47 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -70,7 +70,7 @@
 /**
  * A service to manage multiple clients that want to access the face HAL API.
  * The service is responsible for maintaining a list of clients and dispatching all
- * face -related events.
+ * face-related events.
  *
  * @hide
  */
@@ -485,7 +485,7 @@
                 BiometricAuthenticator.Identifier biometric, int userId)
                 throws RemoteException {
             if (mFaceServiceReceiver != null) {
-                if (biometric instanceof Face) {
+                if (biometric == null || biometric instanceof Face) {
                     mFaceServiceReceiver.onAuthenticationSucceeded(deviceId, (Face)biometric);
                 } else {
                     Slog.e(TAG, "onAuthenticationSucceeded received non-face biometric");
diff --git a/services/core/java/com/android/server/biometrics/iris/IrisService.java b/services/core/java/com/android/server/biometrics/iris/IrisService.java
new file mode 100644
index 0000000..37cdc2a
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/iris/IrisService.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2018 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.biometrics.iris;
+
+import android.content.Context;
+
+import com.android.server.biometrics.BiometricServiceBase;
+import com.android.server.biometrics.BiometricUtils;
+import com.android.server.biometrics.Metrics;
+
+/**
+ * A service to manage multiple clients that want to access the Iris HAL API.
+ * The service is responsible for maintaining a list of clients and dispatching all
+ * iris-related events.
+ *
+ * TODO: The vendor is expected to fill in the service. See
+ * {@link com.android.server.biometrics.fingerprint.FingerprintService}
+ *
+ * @hide
+ */
+public class IrisService extends BiometricServiceBase {
+
+    private static final String TAG = "IrisService";
+
+    /**
+     * Initializes the system service.
+     * <p>
+     * Subclasses must define a single argument constructor that accepts the context
+     * and passes it to super.
+     * </p>
+     *
+     * @param context The system server context.
+     */
+    public IrisService(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+    }
+
+    @Override
+    protected String getTag() {
+        return TAG;
+    }
+
+    @Override
+    protected BiometricUtils getBiometricUtils() {
+        return null;
+    }
+
+    @Override
+    protected int getFailedAttemptsLockoutTimed() {
+        return 0;
+    }
+
+    @Override
+    protected int getFailedAttemptsLockoutPermanent() {
+        return 0;
+    }
+
+    @Override
+    protected Metrics getMetrics() {
+        return null;
+    }
+
+    @Override
+    protected boolean hasReachedEnrollmentLimit(int userId) {
+        return false;
+    }
+
+    @Override
+    protected void updateActiveGroup(int userId, String clientPackage) {
+
+    }
+
+    @Override
+    protected String getLockoutResetIntent() {
+        return null;
+    }
+
+    @Override
+    protected String getLockoutBroadcastPermission() {
+        return null;
+    }
+
+    @Override
+    protected long getHalDeviceId() {
+        return 0;
+    }
+
+    @Override
+    protected void handleUserSwitching(int userId) {
+
+    }
+
+    @Override
+    protected boolean hasEnrolledBiometrics(int userId) {
+        return false;
+    }
+
+    @Override
+    protected String getManageBiometricPermission() {
+        return null;
+    }
+
+    @Override
+    protected void checkUseBiometricPermission() {
+
+    }
+
+    @Override
+    protected boolean checkAppOps(int uid, String opPackageName) {
+        return false;
+    }
+}
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 0ee55ed..527539d 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -21,6 +21,7 @@
 import android.content.IntentFilter;
 import android.hardware.ICameraService;
 import android.hardware.ICameraServiceProxy;
+import android.media.AudioManager;
 import android.metrics.LogMaker;
 import android.nfc.INfcAdapter;
 import android.os.Binder;
@@ -393,6 +394,19 @@
             boolean wasEmpty = mActiveCameraUsage.isEmpty();
             switch (newCameraState) {
                 case ICameraServiceProxy.CAMERA_STATE_OPEN:
+                    // Notify the audio subsystem about the facing of the most-recently opened
+                    // camera This can be used to select the best audio tuning in case video
+                    // recording with that camera will happen.  Since only open events are used, if
+                    // multiple cameras are opened at once, the one opened last will be used to
+                    // select audio tuning.
+                    AudioManager audioManager = getContext().getSystemService(AudioManager.class);
+                    if (audioManager != null) {
+                        // Map external to front for audio tuning purposes
+                        String facingStr = (facing == ICameraServiceProxy.CAMERA_FACING_BACK) ?
+                                "back" : "front";
+                        String facingParameter = "cameraFacing=" + facingStr;
+                        audioManager.setParameters(facingParameter);
+                    }
                     break;
                 case ICameraServiceProxy.CAMERA_STATE_ACTIVE:
                     CameraUsageEvent newEvent = new CameraUsageEvent(facing, clientName, apiLevel);
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index a769590..65537ad 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -55,6 +55,7 @@
 
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.intelligence.IntelligenceManagerInternal;
 import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -157,6 +158,7 @@
     private final IUserManager mUm;
     private final PackageManager mPm;
     private final AppOpsManager mAppOps;
+    private final IntelligenceManagerInternal mIm;
     private final IBinder mPermissionOwner;
     private HostClipboardMonitor mHostClipboardMonitor = null;
     private Thread mHostMonitorThread = null;
@@ -176,6 +178,7 @@
         mPm = getContext().getPackageManager();
         mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
+        mIm = LocalServices.getService(IntelligenceManagerInternal.class);
         final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard");
         mPermissionOwner = permOwner;
         if (IS_EMULATOR) {
@@ -635,8 +638,9 @@
             return true;
         }
         // The default IME is always allowed to access the clipboard.
+        int userId = UserHandle.getUserId(callingUid);
         String defaultIme = Settings.Secure.getStringForUser(getContext().getContentResolver(),
-                Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.getUserId(callingUid));
+                Settings.Secure.DEFAULT_INPUT_METHOD, userId);
         if (!TextUtils.isEmpty(defaultIme)) {
             final String imePkg = ComponentName.unflattenFromString(defaultIme).getPackageName();
             if (imePkg.equals(callingPackage)) {
@@ -646,13 +650,18 @@
 
         switch (op) {
             case AppOpsManager.OP_READ_CLIPBOARD:
-                // Clipboard can only be read by applications with focus.
-                boolean uidFocused = mWm.isUidFocused(callingUid);
-                if (!uidFocused) {
-                    Slog.e(TAG, "Denying clipboard access to " + callingPackage
-                            + ", application is not in focus.");
+                // Clipboard can only be read by applications with focus..
+                boolean allowed = mWm.isUidFocused(callingUid);
+                if (!allowed && mIm != null) {
+                    // ...or the Intelligence Service
+                    allowed = mIm.isIntelligenceServiceForUser(callingUid, userId);
                 }
-                return uidFocused;
+                if (!allowed) {
+                    Slog.e(TAG, "Denying clipboard access to " + callingPackage
+                            + ", application is not in focus neither is the IntelligeService for "
+                            + "user " + userId);
+                }
+                return allowed;
             case AppOpsManager.OP_WRITE_CLIPBOARD:
                 // Writing is allowed without focus.
                 return true;
diff --git a/services/core/java/com/android/server/connectivity/LingerMonitor.java b/services/core/java/com/android/server/connectivity/LingerMonitor.java
index 635db19..0e727c5 100644
--- a/services/core/java/com/android/server/connectivity/LingerMonitor.java
+++ b/services/core/java/com/android/server/connectivity/LingerMonitor.java
@@ -90,6 +90,8 @@
         mNotifier = notifier;
         mDailyLimit = dailyLimit;
         mRateLimitMillis = rateLimitMillis;
+        // Ensure that (now - mFirstNotificationMillis) >= rateLimitMillis at first
+        mFirstNotificationMillis = -rateLimitMillis;
     }
 
     private static HashMap<String, Integer> makeTransportToNameMap() {
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index f96f6e8..6596d27 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -94,7 +94,7 @@
         final boolean hasIPv4Address =
                 (nai.linkProperties != null) && nai.linkProperties.hasIPv4Address();
         final boolean skip464xlat =
-                (nai.networkMisc != null) && nai.networkMisc.skip464xlat;
+                (nai.netMisc() != null) && nai.netMisc().skip464xlat;
         return supported && connected && !hasIPv4Address && !skip464xlat;
     }
 
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 505480e..262184b 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -266,6 +266,10 @@
         return mConnService;
     }
 
+    public NetworkMisc netMisc() {
+        return networkMisc;
+    }
+
     public Handler handler() {
         return mHandler;
     }
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index de4f2d8..c3e3842 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -313,6 +313,7 @@
 
     private int mReevaluateDelayMs = INITIAL_REEVALUATE_DELAY_MS;
     private int mEvaluateAttempts = 0;
+    private volatile int mProbeToken = 0;
 
     public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo,
             NetworkRequest defaultRequest) {
@@ -838,7 +839,8 @@
 
         @Override
         public void enter() {
-            mThread = new Thread(() -> sendMessage(obtainMessage(CMD_PROBE_COMPLETE,
+            final int token = ++mProbeToken;
+            mThread = new Thread(() -> sendMessage(obtainMessage(CMD_PROBE_COMPLETE, token, 0,
                     isCaptivePortal())));
             mThread.start();
         }
@@ -847,16 +849,13 @@
         public boolean processMessage(Message message) {
             switch (message.what) {
                 case CMD_PROBE_COMPLETE:
-                    // Currently, it's not possible to exit this state without mThread having
-                    // terminated. Therefore, this state can never get CMD_PROBE_COMPLETE from a
-                    // stale thread that is not mThread.
-                    // TODO: As soon as it's possible to exit this state without mThread having
-                    // terminated, ensure that CMD_PROBE_COMPLETE from stale threads are ignored.
-                    // This could be done via a sequence number, or by changing mThread to a class
-                    // that has a stopped volatile boolean or AtomicBoolean.
+                    // Ensure that CMD_PROBE_COMPLETE from stale threads are ignored.
+                    if (message.arg1 != mProbeToken) {
+                        return HANDLED;
+                    }
+
                     final CaptivePortalProbeResult probeResult =
                             (CaptivePortalProbeResult) message.obj;
-
                     if (probeResult.isSuccessful()) {
                         // Transit EvaluatingPrivateDnsState to get to Validated
                         // state (even if no Private DNS validation required).
@@ -883,6 +882,7 @@
                 case CMD_REEVALUATE:
                     // Leave the event to EvaluatingState. Defer this message will result in reset
                     // of mReevaluateDelayMs and mEvaluateAttempts.
+                case CMD_NETWORK_DISCONNECTED:
                     return NOT_HANDLED;
                 default:
                     // TODO: Some events may able to handle in this state, instead of deferring to
@@ -894,11 +894,9 @@
 
         @Override
         public void exit() {
-            // If StateMachine get here, the probe started in enter() is guaranteed to have
-            // completed, because in this state, all messages except CMD_PROBE_COMPLETE and
-            // CMD_REEVALUATE are deferred. CMD_REEVALUATE cannot be in the queue, because it is
-            // only ever sent in EvaluatingState#enter, and the StateMachine reach this state by
-            // processing it. Therefore, there is no need to stop the thread.
+            if (mThread.isAlive()) {
+                mThread.interrupt();
+            }
             mThread = null;
         }
     }
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index deaa334..94c94a5 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -165,7 +165,7 @@
     }
 
     @VisibleForTesting
-    int getDeviceFirstSdkInt() {
+    protected int getDeviceFirstSdkInt() {
         return Build.VERSION.FIRST_SDK_INT;
     }
 
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index c51dc52..ab64f61 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -95,12 +95,14 @@
     /**
      * Flag: This display can show its content when non-secure keyguard is shown.
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#shouldShowWithInsecureKeyguard
     public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 9;
 
     /**
      * Flag: This display will destroy its content on removal.
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_DESTROY
     public static final int FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 10;
 
     /**
@@ -114,6 +116,7 @@
      * status bar, navigation bar, home activity or IME.
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors
     public static final int FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 12;
 
     /**
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index c20079e..3a31c9c 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -72,6 +72,8 @@
 import android.view.IInputFilterHost;
 import android.view.IWindow;
 import android.view.InputChannel;
+import android.view.InputApplicationHandle;
+import android.view.InputWindowHandle;
 import android.view.InputDevice;
 import android.view.InputEvent;
 import android.view.KeyEvent;
@@ -197,7 +199,7 @@
     private static native boolean nativeHasKeys(long ptr,
             int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
     private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel,
-            InputWindowHandle inputWindowHandle, int displayId);
+            int displayId);
     private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
     private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
     private static native int nativeInjectInputEvent(long ptr, InputEvent event,
@@ -486,8 +488,7 @@
         }
 
         InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
-        // Register channel for monitor.
-        nativeRegisterInputChannel(mPtr, inputChannels[0], null, displayId);
+        nativeRegisterInputChannel(mPtr, inputChannels[0], displayId);
         inputChannels[0].dispose(); // don't need to retain the Java object reference
         return inputChannels[1];
     }
@@ -498,14 +499,17 @@
      * @param inputWindowHandle The handle of the input window associated with the
      * input channel, or null if none.
      */
-    public void registerInputChannel(InputChannel inputChannel,
-            InputWindowHandle inputWindowHandle) {
+    public void registerInputChannel(InputChannel inputChannel, IBinder token) {
         if (inputChannel == null) {
             throw new IllegalArgumentException("inputChannel must not be null.");
         }
 
-        // Register channel for normal.
-        nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, Display.INVALID_DISPLAY);
+        if (token == null) {
+            token = new Binder();
+        }
+        inputChannel.setToken(token);
+
+        nativeRegisterInputChannel(mPtr, inputChannel, Display.INVALID_DISPLAY);
     }
 
     /**
@@ -1791,15 +1795,15 @@
     }
 
     // Native callback.
-    private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
-        mWindowManagerCallbacks.notifyInputChannelBroken(inputWindowHandle);
+    private void notifyInputChannelBroken(IBinder token) {
+        mWindowManagerCallbacks.notifyInputChannelBroken(token);
     }
 
     // Native callback.
     private long notifyANR(InputApplicationHandle inputApplicationHandle,
-            InputWindowHandle inputWindowHandle, String reason) {
+            IBinder token, String reason) {
         return mWindowManagerCallbacks.notifyANR(
-                inputApplicationHandle, inputWindowHandle, reason);
+                inputApplicationHandle, token, reason);
     }
 
     // Native callback.
@@ -1830,13 +1834,13 @@
     }
 
     // Native callback.
-    private long interceptKeyBeforeDispatching(InputWindowHandle focus,
+    private long interceptKeyBeforeDispatching(IBinder focus,
             KeyEvent event, int policyFlags) {
         return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
     }
 
     // Native callback.
-    private KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
+    private KeyEvent dispatchUnhandledKey(IBinder focus,
             KeyEvent event, int policyFlags) {
         return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
     }
@@ -1987,19 +1991,19 @@
 
         public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
 
-        public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
+        public void notifyInputChannelBroken(IBinder token);
 
         public long notifyANR(InputApplicationHandle inputApplicationHandle,
-                InputWindowHandle inputWindowHandle, String reason);
+                IBinder token, String reason);
 
         public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
 
         public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
 
-        public long interceptKeyBeforeDispatching(InputWindowHandle focus,
+        public long interceptKeyBeforeDispatching(IBinder token,
                 KeyEvent event, int policyFlags);
 
-        public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
+        public KeyEvent dispatchUnhandledKey(IBinder token,
                 KeyEvent event, int policyFlags);
 
         public int getPointerLayer();
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
new file mode 100644
index 0000000..2b67fe7
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -0,0 +1,1630 @@
+/*
+ * Copyright (C) 2018 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.inputmethod;
+
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.AnyThread;
+import android.annotation.BinderThread;
+import android.annotation.IntDef;
+import android.annotation.MainThread;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.annotation.WorkerThread;
+import android.app.AppOpsManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.inputmethodservice.MultiClientInputMethodServiceDelegate;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Build;
+import android.os.Debug;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.text.style.SuggestionSpan;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.InputChannel;
+import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.IMultiClientInputMethod;
+import com.android.internal.inputmethod.IMultiClientInputMethodPrivilegedOperations;
+import com.android.internal.inputmethod.IMultiClientInputMethodSession;
+import com.android.internal.inputmethod.StartInputFlags;
+import com.android.internal.inputmethod.StartInputReason;
+import com.android.internal.inputmethod.UnbindReason;
+import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.internal.view.IInputContext;
+import com.android.internal.view.IInputMethodClient;
+import com.android.internal.view.IInputMethodManager;
+import com.android.internal.view.IInputMethodSession;
+import com.android.internal.view.InputBindResult;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+import com.android.server.wm.WindowManagerInternal;
+
+import java.io.FileDescriptor;
+import java.lang.annotation.Retention;
+import java.util.Collections;
+import java.util.List;
+import java.util.WeakHashMap;
+
+/**
+ * Actual implementation of multi-client InputMethodManagerService.
+ *
+ * <p>This system service is intentionally compatible with {@link InputMethodManagerService} so that
+ * we can switch the implementation at the boot time.</p>
+ */
+public final class MultiClientInputMethodManagerService {
+    static final String TAG = "MultiClientInputMethodManagerService";
+    static final boolean DEBUG = false;
+
+    /**
+     * System property key for the production use. The value must be either empty or a valid
+     * (flattened) component name of the multi-client IME.
+     */
+    private static final String PROP_PROD_MULTI_CLIENT_IME = "ro.sys.multi_client_ime";
+
+    /**
+     * System property key for debugging purpose. The value must be either empty or a valid
+     * (flattened) component name of the multi-client IME.
+     *
+     * <p>This value will be ignored when {@link Build#IS_DEBUGGABLE} returns {@code false}</p>
+     */
+    private static final String PROP_DEBUG_MULTI_CLIENT_IME = "persist.debug.multi_client_ime";
+
+    private static final long RECONNECT_DELAY_MSEC = 1000;
+
+    /**
+     * Unlike {@link InputMethodManagerService}, {@link MultiClientInputMethodManagerService}
+     * always binds to the IME with {@link Context#BIND_FOREGROUND_SERVICE} for now for simplicity.
+     */
+    private static final int IME_CONNECTION_UNIFIED_BIND_FLAGS =
+            Context.BIND_AUTO_CREATE
+                    | Context.BIND_NOT_VISIBLE
+                    | Context.BIND_NOT_FOREGROUND
+                    | Context.BIND_FOREGROUND_SERVICE;
+
+    /**
+     * Inner class to read system property on demand, not when
+     * {@link MultiClientInputMethodManagerService} class is accessed.
+     */
+    private static final class ImeComponentName {
+        private static ComponentName evaluate() {
+            if (Build.IS_DEBUGGABLE) {
+                // If debuggable, allow developers to override the multi-client IME component name
+                // with a different (writable) key.
+                final ComponentName debugIme = ComponentName.unflattenFromString(
+                        SystemProperties.get(PROP_DEBUG_MULTI_CLIENT_IME, ""));
+                if (debugIme != null) {
+                    return debugIme;
+                }
+            }
+            return ComponentName.unflattenFromString(
+                    SystemProperties.get(PROP_PROD_MULTI_CLIENT_IME, ""));
+        }
+
+        /**
+         * {@link ComponentName} of the multi-client IME.  {@code null} when the system is not
+         * configured to use multi-client IME.
+         */
+        @Nullable
+        static final ComponentName sValue = evaluate();
+    }
+
+    public static boolean isConfiguredToUse() {
+        return ImeComponentName.sValue != null;
+    }
+
+    private static void reportNotSupported() {
+        if (DEBUG) {
+            Slog.d(TAG, "non-supported operation. callers=" + Debug.getCallers(3));
+        }
+    }
+
+    /**
+     * {@link MultiClientInputMethodManagerService} is not intended to be instantiated.
+     */
+    private MultiClientInputMethodManagerService() {
+    }
+
+    /**
+     * The implementation of {@link SystemService} for multi-client IME.
+     */
+    public static final class Lifecycle extends SystemService {
+        private final ApiCallbacks mApiCallbacks;
+        private final OnWorkerThreadCallback mOnWorkerThreadCallback;
+
+        @MainThread
+        public Lifecycle(Context context) {
+            super(context);
+
+            final UserToInputMethodInfoMap userIdToInputMethodInfoMapper =
+                    new UserToInputMethodInfoMap();
+            final UserDataMap userDataMap = new UserDataMap();
+            final HandlerThread workerThread = new HandlerThread(TAG);
+            workerThread.start();
+            mApiCallbacks = new ApiCallbacks(context, userDataMap, userIdToInputMethodInfoMapper);
+            mOnWorkerThreadCallback = new OnWorkerThreadCallback(
+                    context, userDataMap, userIdToInputMethodInfoMapper,
+                    new Handler(workerThread.getLooper(), msg -> false, true));
+
+            LocalServices.addService(InputMethodManagerInternal.class,
+                    new InputMethodManagerInternal() {
+                        @Override
+                        public void setInteractive(boolean interactive) {
+                            reportNotSupported();
+                        }
+
+                        @Override
+                        public void hideCurrentInputMethod() {
+                            reportNotSupported();
+                        }
+
+                        @Override
+                        public void startVrInputMethodNoCheck(ComponentName componentName) {
+                            reportNotSupported();
+                        }
+                    });
+        }
+
+        @MainThread
+        @Override
+        public void onBootPhase(int phase) {
+            mOnWorkerThreadCallback.getHandler().sendMessage(PooledLambda.obtainMessage(
+                    OnWorkerThreadCallback::onBootPhase, mOnWorkerThreadCallback, phase));
+        }
+
+        @MainThread
+        @Override
+        public void onStart() {
+            publishBinderService(Context.INPUT_METHOD_SERVICE, mApiCallbacks);
+        }
+
+        @MainThread
+        @Override
+        public void onStartUser(@UserIdInt int userId) {
+            mOnWorkerThreadCallback.getHandler().sendMessage(PooledLambda.obtainMessage(
+                    OnWorkerThreadCallback::onStartUser, mOnWorkerThreadCallback, userId));
+        }
+
+        @MainThread
+        @Override
+        public void onUnlockUser(@UserIdInt int userId) {
+            mOnWorkerThreadCallback.getHandler().sendMessage(PooledLambda.obtainMessage(
+                    OnWorkerThreadCallback::onUnlockUser, mOnWorkerThreadCallback, userId));
+        }
+
+        @MainThread
+        @Override
+        public void onStopUser(@UserIdInt int userId) {
+            mOnWorkerThreadCallback.getHandler().sendMessage(PooledLambda.obtainMessage(
+                    OnWorkerThreadCallback::onStopUser, mOnWorkerThreadCallback, userId));
+        }
+    }
+
+    private static final class OnWorkerThreadCallback {
+        private final Context mContext;
+        private final UserDataMap mUserDataMap;
+        private final UserToInputMethodInfoMap mInputMethodInfoMap;
+        private final Handler mHandler;
+
+        OnWorkerThreadCallback(Context context, UserDataMap userDataMap,
+                UserToInputMethodInfoMap inputMethodInfoMap, Handler handler) {
+            mContext = context;
+            mUserDataMap = userDataMap;
+            mInputMethodInfoMap = inputMethodInfoMap;
+            mHandler = handler;
+        }
+
+        @AnyThread
+        Handler getHandler() {
+            return mHandler;
+        }
+
+        @WorkerThread
+        private void tryBindInputMethodService(@UserIdInt int userId) {
+            final PerUserData data = mUserDataMap.get(userId);
+            if (data == null) {
+                Slog.i(TAG, "tryBindInputMethodService is called for an unknown user=" + userId);
+                return;
+            }
+
+            final InputMethodInfo imi = queryInputMethod(mContext, userId, ImeComponentName.sValue);
+            if (imi == null) {
+                Slog.w(TAG, "Multi-client InputMethod is not found. component="
+                        + ImeComponentName.sValue);
+                synchronized (data.mLock) {
+                    switch (data.mState) {
+                        case PerUserState.USER_LOCKED:
+                        case PerUserState.SERVICE_NOT_QUERIED:
+                        case PerUserState.SERVICE_RECOGNIZED:
+                        case PerUserState.UNBIND_CALLED:
+                            // Safe to clean up.
+                            mInputMethodInfoMap.remove(userId);
+                            break;
+                    }
+                }
+                return;
+            }
+
+            synchronized (data.mLock) {
+                switch (data.mState) {
+                    case PerUserState.USER_LOCKED:
+                        // If the user is still locked, we currently do not try to start IME.
+                        return;
+                    case PerUserState.SERVICE_NOT_QUERIED:
+                    case PerUserState.SERVICE_RECOGNIZED:
+                    case PerUserState.UNBIND_CALLED:
+                        break;
+                    case PerUserState.WAITING_SERVICE_CONNECTED:
+                    case PerUserState.SERVICE_CONNECTED:
+                        // OK, nothing to do.
+                        return;
+                    default:
+                        Slog.wtf(TAG, "Unknown state=" + data.mState);
+                        return;
+                }
+                data.mState = PerUserState.SERVICE_RECOGNIZED;
+                data.mCurrentInputMethodInfo = imi;
+                mInputMethodInfoMap.put(userId, imi);
+                final boolean bindResult = data.bindServiceLocked(mContext, userId);
+                if (!bindResult) {
+                    Slog.e(TAG, "Failed to bind Multi-client InputMethod.");
+                    return;
+                }
+                data.mState = PerUserState.WAITING_SERVICE_CONNECTED;
+            }
+        }
+
+        @WorkerThread
+        void onStartUser(@UserIdInt int userId) {
+            if (DEBUG) {
+                Slog.v(TAG, "onStartUser userId=" + userId);
+            }
+            final PerUserData data = new PerUserData(userId, null, PerUserState.USER_LOCKED, this);
+            mUserDataMap.put(userId, data);
+        }
+
+        @WorkerThread
+        void onUnlockUser(@UserIdInt int userId) {
+            if (DEBUG) {
+                Slog.v(TAG, "onUnlockUser() userId=" + userId);
+            }
+            final PerUserData data = mUserDataMap.get(userId);
+            if (data == null) {
+                Slog.i(TAG, "onUnlockUser is called for an unknown user=" + userId);
+                return;
+            }
+            synchronized (data.mLock) {
+                switch (data.mState) {
+                    case PerUserState.USER_LOCKED:
+                        data.mState = PerUserState.SERVICE_NOT_QUERIED;
+                        tryBindInputMethodService(userId);
+                        break;
+                    default:
+                        Slog.wtf(TAG, "Unknown state=" + data.mState);
+                        break;
+                }
+            }
+        }
+
+        @WorkerThread
+        void onStopUser(@UserIdInt int userId) {
+            if (DEBUG) {
+                Slog.v(TAG, "onStopUser() userId=" + userId);
+            }
+            mInputMethodInfoMap.remove(userId);
+            final PerUserData data = mUserDataMap.removeReturnOld(userId);
+            if (data == null) {
+                Slog.i(TAG, "onStopUser is called for an unknown user=" + userId);
+                return;
+            }
+            synchronized (data.mLock) {
+                switch (data.mState) {
+                    case PerUserState.USER_LOCKED:
+                    case PerUserState.SERVICE_RECOGNIZED:
+                    case PerUserState.UNBIND_CALLED:
+                        // OK, nothing to do.
+                        return;
+                    case PerUserState.SERVICE_CONNECTED:
+                    case PerUserState.WAITING_SERVICE_CONNECTED:
+                        break;
+                    default:
+                        Slog.wtf(TAG, "Unknown state=" + data.mState);
+                        break;
+                }
+                data.unbindServiceLocked(mContext);
+                data.mState = PerUserState.UNBIND_CALLED;
+                data.mCurrentInputMethod = null;
+
+                // When a Service is explicitly unbound with Context.unbindService(),
+                // onServiceDisconnected() will not be triggered.  Hence here we explicitly call
+                // onInputMethodDisconnectedLocked() as if the Service is already gone.
+                data.onInputMethodDisconnectedLocked();
+            }
+        }
+
+        @WorkerThread
+        void onServiceConnected(PerUserData data, IMultiClientInputMethod service) {
+            if (DEBUG) {
+                Slog.v(TAG, "onServiceConnected() data.mUserId=" + data.mUserId);
+            }
+            synchronized (data.mLock) {
+                switch (data.mState) {
+                    case PerUserState.UNBIND_CALLED:
+                        // We should ignore this callback.
+                        return;
+                    case PerUserState.WAITING_SERVICE_CONNECTED:
+                        // OK.
+                        data.mState = PerUserState.SERVICE_CONNECTED;
+                        data.mCurrentInputMethod = service;
+                        try {
+                            data.mCurrentInputMethod.initialize(new ImeCallbacks(data));
+                        } catch (RemoteException e) {
+                        }
+                        data.onInputMethodConnectedLocked();
+                        break;
+                    default:
+                        Slog.wtf(TAG, "Unknown state=" + data.mState);
+                        return;
+                }
+            }
+        }
+
+        @WorkerThread
+        void onServiceDisconnected(PerUserData data) {
+            if (DEBUG) {
+                Slog.v(TAG, "onServiceDisconnected() data.mUserId=" + data.mUserId);
+            }
+            final WindowManagerInternal windowManagerInternal =
+                    LocalServices.getService(WindowManagerInternal.class);
+            synchronized (data.mLock) {
+                // We assume the number of tokens would not be that large (up to 10 or so) hence
+                // linear search should be acceptable.
+                final int numTokens = data.mDisplayIdToImeWindowTokenMap.size();
+                for (int i = 0; i < numTokens; ++i) {
+                    final TokenInfo info = data.mDisplayIdToImeWindowTokenMap.valueAt(i);
+                    windowManagerInternal.removeWindowToken(info.mToken, false, info.mDisplayId);
+                }
+                data.mDisplayIdToImeWindowTokenMap.clear();
+                switch (data.mState) {
+                    case PerUserState.UNBIND_CALLED:
+                        // We should ignore this callback.
+                        return;
+                    case PerUserState.WAITING_SERVICE_CONNECTED:
+                    case PerUserState.SERVICE_CONNECTED:
+                        // onServiceDisconnected() means the biding is still alive.
+                        data.mState = PerUserState.WAITING_SERVICE_CONNECTED;
+                        data.mCurrentInputMethod = null;
+                        data.onInputMethodDisconnectedLocked();
+                        break;
+                    default:
+                        Slog.wtf(TAG, "Unknown state=" + data.mState);
+                        return;
+                }
+            }
+        }
+
+        @WorkerThread
+        void onBindingDied(PerUserData data) {
+            if (DEBUG) {
+                Slog.v(TAG, "onBindingDied() data.mUserId=" + data.mUserId);
+            }
+            final WindowManagerInternal windowManagerInternal =
+                    LocalServices.getService(WindowManagerInternal.class);
+            synchronized (data.mLock) {
+                // We assume the number of tokens would not be that large (up to 10 or so) hence
+                // linear search should be acceptable.
+                final int numTokens = data.mDisplayIdToImeWindowTokenMap.size();
+                for (int i = 0; i < numTokens; ++i) {
+                    final TokenInfo info = data.mDisplayIdToImeWindowTokenMap.valueAt(i);
+                    windowManagerInternal.removeWindowToken(info.mToken, false, info.mDisplayId);
+                }
+                data.mDisplayIdToImeWindowTokenMap.clear();
+                switch (data.mState) {
+                    case PerUserState.UNBIND_CALLED:
+                        // We should ignore this callback.
+                        return;
+                    case PerUserState.WAITING_SERVICE_CONNECTED:
+                    case PerUserState.SERVICE_CONNECTED: {
+                        // onBindingDied() means the biding is dead.
+                        data.mState = PerUserState.UNBIND_CALLED;
+                        data.mCurrentInputMethod = null;
+                        data.onInputMethodDisconnectedLocked();
+                        // Schedule a retry
+                        mHandler.sendMessageDelayed(PooledLambda.obtainMessage(
+                                OnWorkerThreadCallback::tryBindInputMethodService,
+                                this, data.mUserId), RECONNECT_DELAY_MSEC);
+                        break;
+                    }
+                    default:
+                        Slog.wtf(TAG, "Unknown state=" + data.mState);
+                        return;
+                }
+            }
+        }
+
+        @WorkerThread
+        void onBootPhase(int phase) {
+            if (DEBUG) {
+                Slog.v(TAG, "onBootPhase() phase=" + phase);
+            }
+            switch (phase) {
+                case SystemService.PHASE_ACTIVITY_MANAGER_READY: {
+                    final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+                    filter.addDataScheme("package");
+                    mContext.registerReceiver(new BroadcastReceiver() {
+                        @Override
+                        public void onReceive(Context context, Intent intent) {
+                            onPackageAdded(intent);
+                        }
+                    }, filter, null, mHandler);
+                }
+                break;
+            }
+        }
+
+        @WorkerThread
+        void onPackageAdded(Intent intent) {
+            if (DEBUG) {
+                Slog.v(TAG, "onPackageAdded() intent=" + intent);
+            }
+            final Uri uri = intent.getData();
+            if (uri == null) {
+                return;
+            }
+            if (!intent.hasExtra(Intent.EXTRA_UID)) {
+                return;
+            }
+            final String packageName = uri.getSchemeSpecificPart();
+            if (ImeComponentName.sValue == null
+                    || packageName == null
+                    || !TextUtils.equals(ImeComponentName.sValue.getPackageName(), packageName)) {
+                return;
+            }
+            final int userId = UserHandle.getUserId(intent.getIntExtra(Intent.EXTRA_UID, 0));
+            tryBindInputMethodService(userId);
+        }
+    }
+
+    private static final class WindowInfo {
+        final IBinder mWindowToken;
+        final int mWindowHandle;
+
+        WindowInfo(IBinder windowToken, int windowCookie) {
+            mWindowToken = windowToken;
+            mWindowHandle = windowCookie;
+        }
+    }
+
+    /**
+     * Describes the state of each IME client.
+     */
+    @Retention(SOURCE)
+    @IntDef({InputMethodClientState.REGISTERED,
+            InputMethodClientState.WAITING_FOR_IME_SESSION,
+            InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT,
+            InputMethodClientState.ALREADY_SENT_BIND_RESULT,
+            InputMethodClientState.UNREGISTERED})
+    private @interface InputMethodClientState {
+        /**
+         * {@link IInputMethodManager#addClient(IInputMethodClient, IInputContext, int)} is called
+         * and this client is now recognized by the system.  When the system lost the connection to
+         * the current IME, all the clients need to be re-initialized from this state.
+         */
+        int REGISTERED = 1;
+        /**
+         * This client is notified to the current IME with {@link
+         * IMultiClientInputMethod#addClient(int, int, int, int)} but the IME is not yet responded
+         * with {@link IMultiClientInputMethodPrivilegedOperations#acceptClient(int,
+         * IInputMethodSession, IMultiClientInputMethodSession, InputChannel)}.
+         */
+        int WAITING_FOR_IME_SESSION = 2;
+        /**
+         * This client is already accepted by the IME but a valid {@link InputBindResult} has not
+         * been returned to the client yet.
+         */
+        int READY_TO_SEND_FIRST_BIND_RESULT = 3;
+        /**
+         * This client has already received a valid {@link InputBindResult} at least once. This
+         * means that the client can directly call {@link IInputMethodSession} IPCs and key events
+         * via {@link InputChannel}. When the current IME is unbound, these client end points also
+         * need to be cleared.
+         */
+        int ALREADY_SENT_BIND_RESULT = 4;
+        /**
+         * The client process is dying.
+         */
+        int UNREGISTERED = 5;
+    }
+
+    private static final class InputMethodClientIdSource {
+        @GuardedBy("InputMethodClientIdSource.class")
+        private static int sNextValue = 0;
+
+        private InputMethodClientIdSource() {
+        }
+
+        static synchronized int getNext() {
+            final int result = sNextValue;
+            sNextValue++;
+            if (sNextValue < 0) {
+                sNextValue = 0;
+            }
+            return result;
+        }
+    }
+
+    private static final class WindowHandleSource {
+        @GuardedBy("WindowHandleSource.class")
+        private static int sNextValue = 0;
+
+        private WindowHandleSource() {
+        }
+
+        static synchronized int getNext() {
+            final int result = sNextValue;
+            sNextValue++;
+            if (sNextValue < 0) {
+                sNextValue = 0;
+            }
+            return result;
+        }
+    }
+
+    private static final class InputMethodClientInfo {
+        final IInputMethodClient mClient;
+        final int mUid;
+        final int mPid;
+        final int mSelfReportedDisplayId;
+        final int mClientId;
+
+        @GuardedBy("PerUserData.mLock")
+        @InputMethodClientState
+        int mState;
+        @GuardedBy("PerUserData.mLock")
+        int mBindingSequence;
+        @GuardedBy("PerUserData.mLock")
+        InputChannel mWriteChannel;
+        @GuardedBy("PerUserData.mLock")
+        IInputMethodSession mInputMethodSession;
+        @GuardedBy("PerUserData.mLock")
+        IMultiClientInputMethodSession mMSInputMethodSession;
+        @GuardedBy("PerUserData.mLock")
+        final WeakHashMap<IBinder, WindowInfo> mWindowMap = new WeakHashMap<>();
+
+        InputMethodClientInfo(IInputMethodClient client, int uid, int pid,
+                int selfReportedDisplayId) {
+            mClient = client;
+            mUid = uid;
+            mPid = pid;
+            mSelfReportedDisplayId = selfReportedDisplayId;
+            mClientId = InputMethodClientIdSource.getNext();
+        }
+    }
+
+    private static final class UserDataMap {
+        @GuardedBy("mMap")
+        private final SparseArray<PerUserData> mMap = new SparseArray<>();
+
+        @AnyThread
+        @Nullable
+        PerUserData get(@UserIdInt int userId) {
+            synchronized (mMap) {
+                return mMap.get(userId);
+            }
+        }
+
+        @AnyThread
+        void put(@UserIdInt int userId, PerUserData data) {
+            synchronized (mMap) {
+                mMap.put(userId, data);
+            }
+        }
+
+        @AnyThread
+        @Nullable
+        PerUserData removeReturnOld(@UserIdInt int userId) {
+            synchronized (mMap) {
+                return mMap.removeReturnOld(userId);
+            }
+        }
+    }
+
+    private static final class TokenInfo {
+        final Binder mToken;
+        final int mDisplayId;
+        TokenInfo(Binder token, int displayId) {
+            mToken = token;
+            mDisplayId = displayId;
+        }
+    }
+
+    @Retention(SOURCE)
+    @IntDef({
+            PerUserState.USER_LOCKED,
+            PerUserState.SERVICE_NOT_QUERIED,
+            PerUserState.SERVICE_RECOGNIZED,
+            PerUserState.WAITING_SERVICE_CONNECTED,
+            PerUserState.SERVICE_CONNECTED,
+            PerUserState.UNBIND_CALLED})
+    private @interface PerUserState {
+        /**
+         * The user is still locked.
+         */
+        int USER_LOCKED = 1;
+        /**
+         * The system has not queried whether there is a multi-client IME or not.
+         */
+        int SERVICE_NOT_QUERIED = 2;
+        /**
+         * A multi-client IME specified in {@link #PROP_DEBUG_MULTI_CLIENT_IME} is found in the
+         * system, but not bound yet.
+         */
+        int SERVICE_RECOGNIZED = 3;
+        /**
+         * {@link Context#bindServiceAsUser(Intent, ServiceConnection, int, Handler, UserHandle)} is
+         * already called for the IME but
+         * {@link ServiceConnection#onServiceConnected(ComponentName, IBinder)} is not yet called
+         * back. This includes once the IME is bound but temporarily disconnected as notified with
+         * {@link ServiceConnection#onServiceDisconnected(ComponentName)}.
+         */
+        int WAITING_SERVICE_CONNECTED = 4;
+        /**
+         * {@link ServiceConnection#onServiceConnected(ComponentName, IBinder)} is already called
+         * back. The IME is ready to be used.
+         */
+        int SERVICE_CONNECTED = 5;
+        /**
+         * The binding is gone.  Either {@link Context#unbindService(ServiceConnection)} is
+         * explicitly called or the system decided to destroy the binding as notified with
+         * {@link ServiceConnection#onBindingDied(ComponentName)}.
+         */
+        int UNBIND_CALLED = 6;
+    }
+
+    /**
+     * Takes care of per-user state separation.
+     */
+    private static final class PerUserData {
+        final Object mLock = new Object();
+
+        /**
+         * User ID (not UID) that is associated with this data.
+         */
+        @UserIdInt
+        private final int mUserId;
+
+        /**
+         * {@link IMultiClientInputMethod} of the currently connected multi-client IME.  This
+         * must be non-{@code null} only while {@link #mState} is
+         * {@link PerUserState#SERVICE_CONNECTED}.
+         */
+        @Nullable
+        @GuardedBy("mLock")
+        IMultiClientInputMethod mCurrentInputMethod;
+
+        /**
+         * {@link InputMethodInfo} of the currently selected multi-client IME.  This must be
+         * non-{@code null} unless {@link #mState} is {@link PerUserState#SERVICE_NOT_QUERIED}.
+         */
+        @GuardedBy("mLock")
+        @Nullable
+        InputMethodInfo mCurrentInputMethodInfo;
+
+        /**
+         * Describes the current service state.
+         */
+        @GuardedBy("mLock")
+        @PerUserState
+        int mState;
+
+        /**
+         * A {@link SparseArray} that maps display ID to IME Window token that is already issued to
+         * the IME.
+         */
+        @GuardedBy("mLock")
+        final ArraySet<TokenInfo> mDisplayIdToImeWindowTokenMap = new ArraySet<>();
+
+        @GuardedBy("mLock")
+        private final ArrayMap<IBinder, InputMethodClientInfo> mClientMap = new ArrayMap<>();
+
+        @GuardedBy("mLock")
+        private SparseArray<InputMethodClientInfo> mClientIdToClientMap = new SparseArray<>();
+
+        private final OnWorkerThreadServiceConnection mOnWorkerThreadServiceConnection;
+
+        /**
+         * A {@link ServiceConnection} that is designed to run on a certain worker thread with
+         * which {@link OnWorkerThreadCallback} is associated.
+         *
+         * @see Context#bindServiceAsUser(Intent, ServiceConnection, int, Handler, UserHandle).
+         */
+        private static final class OnWorkerThreadServiceConnection implements ServiceConnection {
+            private final PerUserData mData;
+            private final OnWorkerThreadCallback mCallback;
+
+            OnWorkerThreadServiceConnection(PerUserData data, OnWorkerThreadCallback callback) {
+                mData = data;
+                mCallback = callback;
+            }
+
+            @WorkerThread
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                mCallback.onServiceConnected(mData,
+                        IMultiClientInputMethod.Stub.asInterface(service));
+            }
+
+            @WorkerThread
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+                mCallback.onServiceDisconnected(mData);
+            }
+
+            @WorkerThread
+            @Override
+            public void onBindingDied(ComponentName name) {
+                mCallback.onBindingDied(mData);
+            }
+
+            Handler getHandler() {
+                return mCallback.getHandler();
+            }
+        }
+
+        PerUserData(@UserIdInt int userId, @Nullable InputMethodInfo inputMethodInfo,
+                @PerUserState int initialState, OnWorkerThreadCallback callback) {
+            mUserId = userId;
+            mCurrentInputMethodInfo = inputMethodInfo;
+            mState = initialState;
+            mOnWorkerThreadServiceConnection =
+                    new OnWorkerThreadServiceConnection(this, callback);
+        }
+
+        @GuardedBy("mLock")
+        boolean bindServiceLocked(Context context, @UserIdInt int userId) {
+            final Intent intent =
+                    new Intent(MultiClientInputMethodServiceDelegate.SERVICE_INTERFACE)
+                            .setComponent(mCurrentInputMethodInfo.getComponent())
+                            .putExtra(Intent.EXTRA_CLIENT_LABEL,
+                                    com.android.internal.R.string.input_method_binding_label)
+                            .putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+                                    context, 0,
+                                    new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
+
+            // Note: Instead of re-dispatching callback from the main thread to the worker thread
+            // where OnWorkerThreadCallback is running, we pass the Handler object here so that
+            // the callbacks will be directly dispatched to the worker thread.
+            return context.bindServiceAsUser(intent, mOnWorkerThreadServiceConnection,
+                    IME_CONNECTION_UNIFIED_BIND_FLAGS,
+                    mOnWorkerThreadServiceConnection.getHandler(), UserHandle.of(userId));
+        }
+
+        @GuardedBy("mLock")
+        void unbindServiceLocked(Context context) {
+            context.unbindService(mOnWorkerThreadServiceConnection);
+        }
+
+        @GuardedBy("mLock")
+        @Nullable
+        InputMethodClientInfo getClientLocked(IInputMethodClient client) {
+            return mClientMap.get(client.asBinder());
+        }
+
+        @GuardedBy("mLock")
+        @Nullable
+        InputMethodClientInfo getClientFromIdLocked(int clientId) {
+            return mClientIdToClientMap.get(clientId);
+        }
+
+        @GuardedBy("mLock")
+        @Nullable
+        InputMethodClientInfo removeClientLocked(IInputMethodClient client) {
+            final InputMethodClientInfo info = mClientMap.remove(client.asBinder());
+            if (info != null) {
+                mClientIdToClientMap.remove(info.mClientId);
+            }
+            return info;
+        }
+
+        @GuardedBy("mLock")
+        void addClientLocked(int uid, int pid, IInputMethodClient client,
+                int selfReportedDisplayId) {
+            if (getClientLocked(client) != null) {
+                Slog.wtf(TAG, "The same client is added multiple times");
+                return;
+            }
+            final ClientDeathRecipient deathRecipient = new ClientDeathRecipient(this, client);
+            try {
+                client.asBinder().linkToDeath(deathRecipient, 0);
+            } catch (RemoteException e) {
+                throw new IllegalStateException(e);
+            }
+            final InputMethodClientInfo clientInfo =
+                    new InputMethodClientInfo(client, uid, pid, selfReportedDisplayId);
+            clientInfo.mState = InputMethodClientState.REGISTERED;
+            mClientMap.put(client.asBinder(), clientInfo);
+            mClientIdToClientMap.put(clientInfo.mClientId, clientInfo);
+            switch (mState) {
+                case PerUserState.SERVICE_CONNECTED:
+                    try {
+                        mCurrentInputMethod.addClient(
+                                clientInfo.mClientId, clientInfo.mPid, clientInfo.mUid,
+                                clientInfo.mSelfReportedDisplayId);
+                        clientInfo.mState = InputMethodClientState.WAITING_FOR_IME_SESSION;
+                    } catch (RemoteException e) {
+                        // TODO(yukawa): Need logging and expected behavior
+                    }
+                    break;
+            }
+        }
+
+        @GuardedBy("mLock")
+        void onInputMethodConnectedLocked() {
+            final int numClients = mClientMap.size();
+            for (int i = 0; i < numClients; ++i) {
+                final InputMethodClientInfo clientInfo = mClientMap.valueAt(i);
+                switch (clientInfo.mState) {
+                    case InputMethodClientState.REGISTERED:
+                        // OK
+                        break;
+                    default:
+                        Slog.e(TAG, "Unexpected state=" + clientInfo.mState);
+                        return;
+                }
+                try {
+                    mCurrentInputMethod.addClient(
+                            clientInfo.mClientId, clientInfo.mUid, clientInfo.mPid,
+                            clientInfo.mSelfReportedDisplayId);
+                    clientInfo.mState = InputMethodClientState.WAITING_FOR_IME_SESSION;
+                } catch (RemoteException e) {
+                }
+            }
+        }
+
+        @GuardedBy("mLock")
+        void onInputMethodDisconnectedLocked() {
+            final int numClients = mClientMap.size();
+            for (int i = 0; i < numClients; ++i) {
+                final InputMethodClientInfo clientInfo = mClientMap.valueAt(i);
+                switch (clientInfo.mState) {
+                    case InputMethodClientState.REGISTERED:
+                        // Disconnected before onInputMethodConnectedLocked().
+                        break;
+                    case InputMethodClientState.WAITING_FOR_IME_SESSION:
+                        // Disconnected between addClient() and acceptClient().
+                        clientInfo.mState = InputMethodClientState.REGISTERED;
+                        break;
+                    case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT:
+                        clientInfo.mState = InputMethodClientState.REGISTERED;
+                        clientInfo.mInputMethodSession = null;
+                        clientInfo.mMSInputMethodSession = null;
+                        if (clientInfo.mWriteChannel != null) {
+                            clientInfo.mWriteChannel.dispose();
+                            clientInfo.mWriteChannel = null;
+                        }
+                        break;
+                    case InputMethodClientState.ALREADY_SENT_BIND_RESULT:
+                        try {
+                            clientInfo.mClient.onUnbindMethod(clientInfo.mBindingSequence,
+                                    UnbindReason.DISCONNECT_IME);
+                        } catch (RemoteException e) {
+                        }
+                        clientInfo.mState = InputMethodClientState.REGISTERED;
+                        clientInfo.mInputMethodSession = null;
+                        clientInfo.mMSInputMethodSession = null;
+                        if (clientInfo.mWriteChannel != null) {
+                            clientInfo.mWriteChannel.dispose();
+                            clientInfo.mWriteChannel = null;
+                        }
+                        break;
+                }
+            }
+        }
+
+        private static final class ClientDeathRecipient implements IBinder.DeathRecipient {
+            private final PerUserData mPerUserData;
+            private final IInputMethodClient mClient;
+
+            ClientDeathRecipient(PerUserData perUserData, IInputMethodClient client) {
+                mPerUserData = perUserData;
+                mClient = client;
+            }
+
+            @BinderThread
+            @Override
+            public void binderDied() {
+                synchronized (mPerUserData.mLock) {
+                    mClient.asBinder().unlinkToDeath(this, 0);
+
+                    final InputMethodClientInfo clientInfo =
+                            mPerUserData.removeClientLocked(mClient);
+                    if (clientInfo == null) {
+                        return;
+                    }
+
+                    if (clientInfo.mWriteChannel != null) {
+                        clientInfo.mWriteChannel.dispose();
+                        clientInfo.mWriteChannel = null;
+                    }
+                    if (clientInfo.mInputMethodSession != null) {
+                        try {
+                            clientInfo.mInputMethodSession.finishSession();
+                        } catch (RemoteException e) {
+                        }
+                        clientInfo.mInputMethodSession = null;
+                    }
+                    clientInfo.mMSInputMethodSession = null;
+                    clientInfo.mState = InputMethodClientState.UNREGISTERED;
+                    switch (mPerUserData.mState) {
+                        case PerUserState.SERVICE_CONNECTED:
+                            try {
+                                mPerUserData.mCurrentInputMethod.removeClient(clientInfo.mClientId);
+                            } catch (RemoteException e) {
+                                // TODO(yukawa): Need logging and expected behavior
+                            }
+                            break;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Queries for multi-client IME specified with {@code componentName}.
+     *
+     * @param context {@link Context} to be used to query component.
+     * @param userId User ID for which the multi-client IME is queried.
+     * @param componentName {@link ComponentName} to be queried.
+     * @return {@link InputMethodInfo} when multi-client IME is found. Otherwise {@code null}.
+     */
+    @Nullable
+    private static InputMethodInfo queryInputMethod(Context context, @UserIdInt int userId,
+            @Nullable ComponentName componentName) {
+        if (componentName == null) {
+            return null;
+        }
+
+        // Use for queryIntentServicesAsUser
+        final PackageManager pm = context.getPackageManager();
+        final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
+                new Intent(MultiClientInputMethodServiceDelegate.SERVICE_INTERFACE)
+                        .setComponent(componentName),
+                PackageManager.GET_META_DATA, userId);
+
+        if (services.isEmpty()) {
+            Slog.e(TAG, "No IME found");
+            return null;
+        }
+
+        if (services.size() > 1) {
+            Slog.e(TAG, "Only one IME service is supported.");
+            return null;
+        }
+
+        final ResolveInfo ri = services.get(0);
+        ServiceInfo si = ri.serviceInfo;
+        final String imeId = InputMethodInfo.computeId(ri);
+        if (!android.Manifest.permission.BIND_INPUT_METHOD.equals(si.permission)) {
+            Slog.e(TAG, imeId + " must have required"
+                    + android.Manifest.permission.BIND_INPUT_METHOD);
+            return null;
+        }
+
+        if (!Build.IS_DEBUGGABLE && (si.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+            Slog.e(TAG, imeId + " must be pre-installed when Build.IS_DEBUGGABLE is false");
+            return null;
+        }
+
+        try {
+            return new InputMethodInfo(context, ri);
+        } catch (Exception e) {
+            Slog.wtf(TAG, "Unable to load input method " + imeId, e);
+        }
+        return null;
+    }
+
+    /**
+     * Manages the mapping rule from user ID to {@link InputMethodInfo}.
+     */
+    private static final class UserToInputMethodInfoMap {
+        @GuardedBy("mArray")
+        private final SparseArray<InputMethodInfo> mArray = new SparseArray<>();
+
+        @AnyThread
+        void put(@UserIdInt int userId, InputMethodInfo imi) {
+            synchronized (mArray) {
+                mArray.put(userId, imi);
+            }
+        }
+
+        @AnyThread
+        void remove(@UserIdInt int userId) {
+            synchronized (mArray) {
+                mArray.remove(userId);
+            }
+        }
+
+        @AnyThread
+        @Nullable
+        InputMethodInfo get(@UserIdInt int userId) {
+            synchronized (mArray) {
+                return mArray.get(userId);
+            }
+        }
+
+        @AnyThread
+        List<InputMethodInfo> getAsList(@UserIdInt int userId) {
+            final InputMethodInfo info = get(userId);
+            if (info == null) {
+                return Collections.emptyList();
+            }
+            return Collections.singletonList(info);
+        }
+    }
+
+    /**
+     * Takes care of IPCs exposed to the multi-client IME.
+     */
+    private static final class ImeCallbacks
+            extends IMultiClientInputMethodPrivilegedOperations.Stub {
+        private final PerUserData mPerUserData;
+        private final WindowManagerInternal mIWindowManagerInternal;
+
+        ImeCallbacks(PerUserData perUserData) {
+            mPerUserData = perUserData;
+            mIWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+        }
+
+        @BinderThread
+        @Override
+        public IBinder createInputMethodWindowToken(int displayId) {
+            synchronized (mPerUserData.mLock) {
+                // We assume the number of tokens would not be that large (up to 10 or so) hence
+                // linear search should be acceptable.
+                final int numTokens = mPerUserData.mDisplayIdToImeWindowTokenMap.size();
+                for (int i = 0; i < numTokens; ++i) {
+                    final TokenInfo tokenInfo =
+                            mPerUserData.mDisplayIdToImeWindowTokenMap.valueAt(i);
+                    // Currently we issue up to one window token per display.
+                    if (tokenInfo.mDisplayId == displayId) {
+                        return tokenInfo.mToken;
+                    }
+                }
+
+                final Binder token = new Binder();
+                Binder.withCleanCallingIdentity(
+                        PooledLambda.obtainRunnable(WindowManagerInternal::addWindowToken,
+                                mIWindowManagerInternal, token, TYPE_INPUT_METHOD, displayId));
+                mPerUserData.mDisplayIdToImeWindowTokenMap.add(new TokenInfo(token, displayId));
+                return token;
+            }
+        }
+
+        @BinderThread
+        @Override
+        public void deleteInputMethodWindowToken(IBinder token) {
+            synchronized (mPerUserData.mLock) {
+                // We assume the number of tokens would not be that large (up to 10 or so) hence
+                // linear search should be acceptable.
+                final int numTokens = mPerUserData.mDisplayIdToImeWindowTokenMap.size();
+                for (int i = 0; i < numTokens; ++i) {
+                    final TokenInfo tokenInfo =
+                            mPerUserData.mDisplayIdToImeWindowTokenMap.valueAt(i);
+                    if (tokenInfo.mToken == token) {
+                        mPerUserData.mDisplayIdToImeWindowTokenMap.remove(tokenInfo);
+                        break;
+                    }
+                }
+            }
+        }
+
+        @BinderThread
+        @Override
+        public void acceptClient(int clientId, IInputMethodSession inputMethodSession,
+                IMultiClientInputMethodSession multiSessionInputMethodSession,
+                InputChannel writeChannel) {
+            synchronized (mPerUserData.mLock) {
+                final InputMethodClientInfo clientInfo =
+                        mPerUserData.getClientFromIdLocked(clientId);
+                if (clientInfo == null) {
+                    Slog.e(TAG, "Unknown clientId=" + clientId);
+                    return;
+                }
+                switch (clientInfo.mState) {
+                    case InputMethodClientState.WAITING_FOR_IME_SESSION:
+                        try {
+                            clientInfo.mClient.setActive(true, false);
+                        } catch (RemoteException e) {
+                            // TODO(yukawa): Remove this client.
+                            return;
+                        }
+                        clientInfo.mState = InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT;
+                        clientInfo.mWriteChannel = writeChannel;
+                        clientInfo.mInputMethodSession = inputMethodSession;
+                        clientInfo.mMSInputMethodSession = multiSessionInputMethodSession;
+                        break;
+                    default:
+                        Slog.e(TAG, "Unexpected state=" + clientInfo.mState);
+                        break;
+                }
+            }
+        }
+
+        @BinderThread
+        @Override
+        public void reportImeWindowTarget(int clientId, int targetWindowHandle,
+                IBinder imeWindowToken) {
+            synchronized (mPerUserData.mLock) {
+                final InputMethodClientInfo clientInfo =
+                        mPerUserData.getClientFromIdLocked(clientId);
+                if (clientInfo == null) {
+                    Slog.e(TAG, "Unknown clientId=" + clientId);
+                    return;
+                }
+                for (WindowInfo windowInfo : clientInfo.mWindowMap.values()) {
+                    if (windowInfo.mWindowHandle == targetWindowHandle) {
+                        final IBinder targetWindowToken = windowInfo.mWindowToken;
+                        // TODO(yukawa): Report targetWindowToken and targetWindowToken to WMS.
+                        if (DEBUG) {
+                            Slog.v(TAG, "reportImeWindowTarget"
+                                    + " clientId=" + clientId
+                                    + " imeWindowToken=" + imeWindowToken
+                                    + " targetWindowToken=" + targetWindowToken);
+                        }
+                    }
+                }
+                // not found.
+            }
+        }
+
+        @BinderThread
+        @Override
+        public boolean isUidAllowedOnDisplay(int displayId, int uid) {
+            return mIWindowManagerInternal.isUidAllowedOnDisplay(displayId, uid);
+        }
+    }
+
+    /**
+     * Takes care of IPCs exposed to the IME client.
+     */
+    private static final class ApiCallbacks extends IInputMethodManager.Stub {
+        private final UserDataMap mUserDataMap;
+        private final UserToInputMethodInfoMap mInputMethodInfoMap;
+        private final AppOpsManager mAppOpsManager;
+        private final WindowManagerInternal mWindowManagerInternal;
+
+        ApiCallbacks(Context context, UserDataMap userDataMap,
+                UserToInputMethodInfoMap inputMethodInfoMap) {
+            mUserDataMap = userDataMap;
+            mInputMethodInfoMap = inputMethodInfoMap;
+            mAppOpsManager = context.getSystemService(AppOpsManager.class);
+            mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+        }
+
+        @AnyThread
+        private boolean checkFocus(int uid, int pid, int displayId) {
+            return mWindowManagerInternal.isInputMethodClientFocus(uid, pid, displayId);
+        }
+
+        @BinderThread
+        @Override
+        public void addClient(IInputMethodClient client, IInputContext inputContext,
+                int selfReportedDisplayId) {
+            final int callingUid = Binder.getCallingUid();
+            final int callingPid = Binder.getCallingPid();
+            final int userId = UserHandle.getUserId(callingUid);
+            final PerUserData data = mUserDataMap.get(userId);
+            if (data == null) {
+                Slog.e(TAG, "addClient() from unknown userId=" + userId
+                        + " uid=" + callingUid + " pid=" + callingPid);
+                return;
+            }
+            synchronized (data.mLock) {
+                data.addClientLocked(callingUid, callingPid, client, selfReportedDisplayId);
+            }
+        }
+
+        @BinderThread
+        @Override
+        public List<InputMethodInfo> getInputMethodList() {
+            return mInputMethodInfoMap.getAsList(UserHandle.getUserId(Binder.getCallingUid()));
+        }
+
+        @BinderThread
+        @Override
+        public List<InputMethodInfo> getVrInputMethodList() {
+            reportNotSupported();
+            return Collections.emptyList();
+        }
+
+        @BinderThread
+        @Override
+        public List<InputMethodInfo> getEnabledInputMethodList() {
+            return mInputMethodInfoMap.getAsList(UserHandle.getUserId(Binder.getCallingUid()));
+        }
+
+        @BinderThread
+        @Override
+        public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
+                boolean allowsImplicitlySelectedSubtypes) {
+            reportNotSupported();
+            return Collections.emptyList();
+        }
+
+        @BinderThread
+        @Override
+        public InputMethodSubtype getLastInputMethodSubtype() {
+            reportNotSupported();
+            return null;
+        }
+
+        @BinderThread
+        @Override
+        public List getShortcutInputMethodsAndSubtypes() {
+            reportNotSupported();
+            return null;
+        }
+
+        @BinderThread
+        @Override
+        public boolean showSoftInput(
+                IInputMethodClient client, int flags, ResultReceiver resultReceiver) {
+            final int callingUid = Binder.getCallingUid();
+            final int callingPid = Binder.getCallingPid();
+            final int userId = UserHandle.getUserId(callingUid);
+            final PerUserData data = mUserDataMap.get(userId);
+            if (data == null) {
+                Slog.e(TAG, "showSoftInput() from unknown userId=" + userId
+                        + " uid=" + callingUid + " pid=" + callingPid);
+                return false;
+            }
+            synchronized (data.mLock) {
+                final InputMethodClientInfo clientInfo = data.getClientLocked(client);
+                if (clientInfo == null) {
+                    Slog.e(TAG, "showSoftInput. client not found. ignoring.");
+                    return false;
+                }
+                if (clientInfo.mUid != callingUid) {
+                    Slog.e(TAG, "Expected calling UID=" + clientInfo.mUid
+                            + " actual=" + callingUid);
+                    return false;
+                }
+                switch (clientInfo.mState) {
+                    case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT:
+                    case InputMethodClientState.ALREADY_SENT_BIND_RESULT:
+                        try {
+                            clientInfo.mMSInputMethodSession.showSoftInput(flags, resultReceiver);
+                        } catch (RemoteException e) {
+                        }
+                        break;
+                    default:
+                        if (DEBUG) {
+                            Slog.e(TAG, "Ignoring showSoftInput(). clientState="
+                                    + clientInfo.mState);
+                        }
+                        break;
+                }
+                return true;
+            }
+        }
+
+        @BinderThread
+        @Override
+        public boolean hideSoftInput(
+                IInputMethodClient client, int flags, ResultReceiver resultReceiver) {
+            final int callingUid = Binder.getCallingUid();
+            final int callingPid = Binder.getCallingPid();
+            final int userId = UserHandle.getUserId(callingUid);
+            final PerUserData data = mUserDataMap.get(userId);
+            if (data == null) {
+                Slog.e(TAG, "hideSoftInput() from unknown userId=" + userId
+                        + " uid=" + callingUid + " pid=" + callingPid);
+                return false;
+            }
+            synchronized (data.mLock) {
+                final InputMethodClientInfo clientInfo = data.getClientLocked(client);
+                if (clientInfo == null) {
+                    return false;
+                }
+                if (clientInfo.mUid != callingUid) {
+                    Slog.e(TAG, "Expected calling UID=" + clientInfo.mUid
+                            + " actual=" + callingUid);
+                    return false;
+                }
+                switch (clientInfo.mState) {
+                    case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT:
+                    case InputMethodClientState.ALREADY_SENT_BIND_RESULT:
+                        try {
+                            clientInfo.mMSInputMethodSession.hideSoftInput(flags, resultReceiver);
+                        } catch (RemoteException e) {
+                        }
+                        break;
+                    default:
+                        if (DEBUG) {
+                            Slog.e(TAG, "Ignoring hideSoftInput(). clientState="
+                                    + clientInfo.mState);
+                        }
+                        break;
+                }
+                return true;
+            }
+        }
+
+        @BinderThread
+        @Override
+        public InputBindResult startInputOrWindowGainedFocus(
+                @StartInputReason int startInputReason,
+                @Nullable IInputMethodClient client,
+                @Nullable IBinder windowToken,
+                @StartInputFlags int startInputFlags,
+                @SoftInputModeFlags int softInputMode,
+                int windowFlags,
+                @Nullable EditorInfo editorInfo,
+                @Nullable IInputContext inputContext,
+                @MissingMethodFlags int missingMethods,
+                int unverifiedTargetSdkVersion) {
+            final int callingUid = Binder.getCallingUid();
+            final int callingPid = Binder.getCallingPid();
+            final int userId = UserHandle.getUserId(callingUid);
+
+            if (client == null) {
+                return InputBindResult.INVALID_CLIENT;
+            }
+
+            final boolean packageNameVerified =
+                    editorInfo != null && InputMethodUtils.checkIfPackageBelongsToUid(
+                            mAppOpsManager, callingUid, editorInfo.packageName);
+            if (editorInfo != null && !packageNameVerified) {
+                Slog.e(TAG, "Rejecting this client as it reported an invalid package name."
+                        + " uid=" + callingUid + " package=" + editorInfo.packageName);
+                return InputBindResult.INVALID_PACKAGE_NAME;
+            }
+
+            final PerUserData data = mUserDataMap.get(userId);
+            if (data == null) {
+                Slog.e(TAG, "startInputOrWindowGainedFocus() from unknown userId=" + userId
+                        + " uid=" + callingUid + " pid=" + callingPid);
+                return InputBindResult.INVALID_USER;
+            }
+
+            synchronized (data.mLock) {
+                final InputMethodClientInfo clientInfo = data.getClientLocked(client);
+                if (clientInfo == null) {
+                    return InputBindResult.INVALID_CLIENT;
+                }
+                if (clientInfo.mUid != callingUid) {
+                    Slog.e(TAG, "Expected calling UID=" + clientInfo.mUid
+                            + " actual=" + callingUid);
+                    return InputBindResult.INVALID_CLIENT;
+                }
+
+                switch (data.mState) {
+                    case PerUserState.USER_LOCKED:
+                    case PerUserState.SERVICE_NOT_QUERIED:
+                    case PerUserState.SERVICE_RECOGNIZED:
+                    case PerUserState.WAITING_SERVICE_CONNECTED:
+                    case PerUserState.UNBIND_CALLED:
+                        return InputBindResult.IME_NOT_CONNECTED;
+                    case PerUserState.SERVICE_CONNECTED:
+                        // OK
+                        break;
+                    default:
+                        Slog.wtf(TAG, "Unexpected state=" + data.mState);
+                        return InputBindResult.IME_NOT_CONNECTED;
+                }
+
+                WindowInfo windowInfo = null;
+                if (windowToken != null) {
+                    windowInfo = clientInfo.mWindowMap.get(windowToken);
+                    if (windowInfo == null) {
+                        windowInfo = new WindowInfo(windowToken, WindowHandleSource.getNext());
+                        clientInfo.mWindowMap.put(windowToken, windowInfo);
+                    }
+                }
+
+                if (!checkFocus(clientInfo.mUid, clientInfo.mPid,
+                        clientInfo.mSelfReportedDisplayId)) {
+                    return InputBindResult.NOT_IME_TARGET_WINDOW;
+                }
+
+                if (editorInfo == null) {
+                    // So-called dummy InputConnection scenario.  For app compatibility, we still
+                    // notify this to the IME.
+                    switch (clientInfo.mState) {
+                        case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT:
+                        case InputMethodClientState.ALREADY_SENT_BIND_RESULT:
+                            final int windowHandle = windowInfo != null
+                                    ? windowInfo.mWindowHandle
+                                    : MultiClientInputMethodServiceDelegate.INVALID_WINDOW_HANDLE;
+                            try {
+                                clientInfo.mMSInputMethodSession.startInputOrWindowGainedFocus(
+                                        inputContext, missingMethods, editorInfo, startInputFlags,
+                                        softInputMode, windowHandle);
+                            } catch (RemoteException e) {
+                            }
+                            break;
+                    }
+                    return InputBindResult.NULL_EDITOR_INFO;
+                }
+
+                switch (clientInfo.mState) {
+                    case InputMethodClientState.REGISTERED:
+                    case InputMethodClientState.WAITING_FOR_IME_SESSION:
+                        clientInfo.mBindingSequence++;
+                        if (clientInfo.mBindingSequence < 0) {
+                            clientInfo.mBindingSequence = 0;
+                        }
+                        return new InputBindResult(
+                                InputBindResult.ResultCode.SUCCESS_WAITING_IME_SESSION,
+                                null, null, data.mCurrentInputMethodInfo.getId(),
+                                clientInfo.mBindingSequence);
+                    case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT:
+                    case InputMethodClientState.ALREADY_SENT_BIND_RESULT:
+                        clientInfo.mBindingSequence++;
+                        if (clientInfo.mBindingSequence < 0) {
+                            clientInfo.mBindingSequence = 0;
+                        }
+                        // Successful start input.
+                        final int windowHandle = windowInfo != null
+                                ? windowInfo.mWindowHandle
+                                : MultiClientInputMethodServiceDelegate.INVALID_WINDOW_HANDLE;
+                        try {
+                            clientInfo.mMSInputMethodSession.startInputOrWindowGainedFocus(
+                                    inputContext, missingMethods, editorInfo, startInputFlags,
+                                    softInputMode, windowHandle);
+                        } catch (RemoteException e) {
+                        }
+                        clientInfo.mState = InputMethodClientState.ALREADY_SENT_BIND_RESULT;
+                        return new InputBindResult(
+                                InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION,
+                                clientInfo.mInputMethodSession,
+                                clientInfo.mWriteChannel.dup(),
+                                data.mCurrentInputMethodInfo.getId(),
+                                clientInfo.mBindingSequence);
+                    case InputMethodClientState.UNREGISTERED:
+                        Slog.e(TAG, "The client is already unregistered.");
+                        return InputBindResult.INVALID_CLIENT;
+                }
+            }
+            return null;
+        }
+
+        @BinderThread
+        @Override
+        public void showInputMethodPickerFromClient(
+                IInputMethodClient client, int auxiliarySubtypeMode) {
+            reportNotSupported();
+        }
+
+        @BinderThread
+        @Override
+        public void showInputMethodAndSubtypeEnablerFromClient(
+                IInputMethodClient client, String inputMethodId) {
+            reportNotSupported();
+        }
+
+        @BinderThread
+        @Override
+        public boolean isInputMethodPickerShownForTest() {
+            reportNotSupported();
+            return false;
+        }
+
+        @BinderThread
+        @Override
+        public void setInputMethod(IBinder token, String id) {
+            reportNotSupported();
+        }
+
+        @BinderThread
+        @Override
+        public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
+            reportNotSupported();
+        }
+
+        @BinderThread
+        @Override
+        public void registerSuggestionSpansForNotification(SuggestionSpan[] suggestionSpans) {
+            reportNotSupported();
+        }
+
+        @BinderThread
+        @Override
+        public boolean notifySuggestionPicked(
+                SuggestionSpan span, String originalString, int index) {
+            reportNotSupported();
+            return false;
+        }
+
+        @BinderThread
+        @Override
+        public InputMethodSubtype getCurrentInputMethodSubtype() {
+            reportNotSupported();
+            return null;
+        }
+
+        @BinderThread
+        @Override
+        public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
+            reportNotSupported();
+            return false;
+        }
+
+        @BinderThread
+        @Override
+        public boolean switchToPreviousInputMethod(IBinder token) {
+            reportNotSupported();
+            return false;
+        }
+
+        @BinderThread
+        @Override
+        public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
+            reportNotSupported();
+            return false;
+        }
+
+        @BinderThread
+        @Override
+        public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
+            reportNotSupported();
+        }
+
+        @BinderThread
+        @Override
+        public int getInputMethodWindowVisibleHeight() {
+            reportNotSupported();
+            return 0;
+        }
+
+        @BinderThread
+        @Override
+        public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
+                @Nullable FileDescriptor err, String[] args, @Nullable ShellCallback callback,
+                ResultReceiver resultReceiver) {
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/inputmethod/multi-client-ime.md b/services/core/java/com/android/server/inputmethod/multi-client-ime.md
new file mode 100644
index 0000000..3021d2f
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/multi-client-ime.md
@@ -0,0 +1,192 @@
+<!-- Copyright (C) 2018 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.
+-->
+
+# Multi Client Input Method Editors
+
+## History of Multi Client Input Method Editors (Multi Client IMEs)
+
+An advanced multi-display support is requested for certain Android form-factors so that user(s) can type text on each display at the same time without losing software keyboard focus in other displays (hereafter called "multi-client scenario"). This is not possible in Android IMEs built on top of `InputMethodService` class. The assumption that a single IME client can be focused at the same time was made before Android IME APIs were introduced in Android 1.5 and many public APIs in `InputMethodService` have already relied heavily on that assumption (hereafter called "single-client scenario"). Updating `InputMethodService` class to support multi-client scenario is, however, quite challenging because:
+
+ 1. doing so would introduce an unacceptable amount of complexity into `InputMethodService`, which is already hard to maintain,
+ 2. IME developers still need to update their implementation to be able to support parallel requests from multiple focused IME client, which may require non-trivial redesign in their side (e.g. input decoder, typing history database, ...), and
+ 3. actual use cases for multi IME clients are expected to be evolved rapidly hence the new protocol is not yet stable and not yet ready to be exposed as public APIs.
+
+Thus the first decision we made was that to support such special multi-display environments a new type of IME (hereafter called "multi-client IME") needs to be designed and implemented rather than reusing `InputMethodService` public class. On top of this decision, following decisions were also made:
+
+ * Multi-client IME V1 will be built on top of private APIs. This means:
+   * Multi-client IME must be pre-installed into the system. They cannot be distributed via application store since protocol compatibility is not guaranteed across devices and releases.
+   * The system should trust multi-client IME to some extent. System integrators are responsible for making sure that the pre-installed multi-client IME works as expected.
+ * Unlike `InputMethodService`, multiple multi-client IMEs cannot be enabled. The system pre-installs only one multi-client IME.
+ * Punt some special features of Android IMEs (e.g. fullscreen mode, InputMethodSubtype, ...) from V1 goal unless someone actually requests those features for multi-client IME scenario.
+ * Introduce `MultiClientInputMethodManagerService` (MCIMMS) for multi-client IME scenario and use it instead of `InputMethodManagerService` (IMMS) when a certain runtime flag is enabled at the device boot time. This means:
+   * basically no risk for single-client scenario,
+   * the feature can be easily deprecated, and
+   * it forces us to rewrite IME system server, which is expected to be a good chance to reconsider what Android IME protocol should look like.
+ * Most of form-factors such as Phones and TVs continue to use IMMS and support at most one focused IME client even under multi-display environment.
+
+
+## How to test
+
+On AOSP-based development devices (e.g. phones) where `android.os.Build.IS_DEBUGGABLE` returns `true` and you can have root access, you can enable multi-client IME feature by setting a valid component name that supports multi-client IME protocol to the system property `persist.debug.multi_client_ime`. Reboot is required for this to take effect.
+
+```shell
+# Build and install a sample multi-client IME
+make -j MultiClientInputMethod
+adb install -r $OUT/system/priv-app/MultiClientInputMethod/MultiClientInputMethod.apk
+
+# Enable multi-client IME for the side-loaded sample multi-client IME
+adb root
+adb shell setprop persist.debug.multi_client_ime com.example.android.multiclientinputmethod/.MultiClientInputMethod
+adb reboot
+```
+
+To disable multi-client IME on non-supported devices again, just clear `persist.debug.multi_client_ime` as follows. Reboot is still required for this to take effect.
+
+```shell
+# Disable multi-client IME again
+adb root
+adb shell "setprop persist.debug.multi_client_ime ''"
+adb reboot
+```
+
+## How to develop multi-client IMEs
+
+There is a sample multi-client IME in `development/samples/MultiClientInputMethod/`.
+
+## Versioning
+
+Neither forward nor backward compatibility is guaranteed in multi-client IME APIs. The system integrator is responsible for making sure that both the system and pre-installed multi-client IME are compatible with each other every time the system image is updated.
+
+## Implementation note
+
+### Unsupported features
+
+ * VR IME
+   * `VrManager#setVrInputMethod()` system API is not supported.
+ * InputMethodSubtype
+   * Following APIs are not supported
+     * `InputMethodManager#getEnabledInputMethodSubtypeList()`
+     * `InputMethodManager#getCurrentInputMethodSubtype()`
+     * `InputMethodManager#setCurrentInputMethodSubtype()`
+     * `InputMethodManager#getShortcutInputMethodsAndSubtypes()`
+     * `InputMethodManager#setAdditionalInputMethodSubtypes()`
+     * `InputMethodManager#getLastInputMethodSubtype()`
+     * `Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE`
+ * IME switching
+   * Following APIs are not supported
+     * `InputMethodManager#showInputMethodPicker()`
+     * `InputMethodManager#showInputMethodAndSubtypeEnabler()`
+     * `InputMethodManager#setInputMethod()`
+     * `InputMethodManager#setInputMethodAndSubtype()`
+     * `InputMethodManager#switchToLastInputMethod()`
+     * `InputMethodManager#switchToNextInputMethod()`
+     * `InputMethodManager#shouldOfferSwitchingToNextInputMethod()`
+     * `Settings.Secure#DEFAULT_INPUT_METHOD`
+     * `Settings.Secure#ENABLED_INPUT_METHODS`
+ * Direct-boot aware multi-client IME
+   * Device manufacturer can work around this by integrating in-app keyboard into the initial unlock screen.
+ * Full-screen mode
+   * Following API always returns `false`.
+     * `InputMethodManager#isFullscreenMode()`
+ * Custom inset
+   * For instance, floating IME cannot be implemented right now.
+ * Custom touchable region (`InputMethodService.Insets#touchableRegion`)
+ * Image Insertion API
+   * `InputConnection#commitContent()` API is silently ignored.
+ * `adb shell dumpsys` does not include any log from MCIMMS yet.
+
+### Security
+
+#### Root permission is required to enable MCIMMS on non-supported devices
+
+In order to override `persist.debug.multi_client_ime` device property, an explicit root permission is needed.
+
+#### Multi-client IME must be pre-installed
+
+Multi-client IME must be pre-installed since it is considered as part of the system component. This is verified by checking `ApplicationInfo.FLAG_SYSTEM` bit. This security check can be bypassed when `Build.IS_DEBUGGABLE` is `true` so that IME developers can easily side-load their APKs during development phase.
+
+```java
+public final class MultiClientInputMethodManagerService {
+    ...
+    @Nullable
+    private static InputMethodInfo queryInputMethod(Context context, @UserIdInt int userId,
+            @Nullable ComponentName componentName) {
+
+        ...
+
+        if (! && (si.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+            Slog.e(TAG, imeId + " must be pre-installed when Build.IS_DEBUGGABLE is false");
+            return null;
+        }
+```
+[services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java](MultiClientInputMethodManagerService.java)
+
+
+#### Integer handle vs IBinder token
+
+Sometimes MCIMMS needs to issue certain types of identifiers to the multi-client IME so that the IME can later specify to which entity or resource it intends to access. A good example is the IME client identifier. Multi-client IME definitely need to be able to specify which IME client to be interacted with for certain operations. The problem is that MCIMMS cannot simply pass `IInputMethodClient` to the multi-client IME as an ID because it would allow the IME to make IPC calls to the IME client. For this kind of situations, we usually use `Binder` object just as a non-spoofable token. For instance, IMMS creates another 'Binder' token then pass it to the IME, instead of directly passing 'IWindow' Binder token.
+
+```java
+public class InputMethodManagerService extends IInputMethodManager.Stub
+        implements ServiceConnection, Handler.Callback {
+    ...
+    @GuardedBy("mMethodMap")
+    private final WeakHashMap<IBinder, IBinder> mImeTargetWindowMap = new WeakHashMap<>();
+
+    ...
+
+    @GuardedBy("mMethodMap")
+    @NonNull
+    InputBindResult attachNewInputLocked(@StartInputReason int startInputReason, boolean initial) {
+        ...
+        final Binder startInputToken = new Binder();
+        final StartInputInfo info = new StartInputInfo(mCurToken, mCurId, startInputReason,
+                !initial, mCurFocusedWindow, mCurAttribute, mCurFocusedWindowSoftInputMode,
+                mCurSeq);
+        mImeTargetWindowMap.put(startInputToken, mCurFocusedWindow);
+        ...
+    }
+
+    ...
+
+    @BinderThread
+    private void reportStartInput(IBinder token, IBinder startInputToken) {
+        if (!calledWithValidToken(token)) {
+            return;
+        }
+
+        synchronized (mMethodMap) {
+            final IBinder targetWindow = mImeTargetWindowMap.get(startInputToken);
+            if (targetWindow != null && mLastImeTargetWindow != targetWindow) {
+                mWindowManagerInternal.updateInputMethodTargetWindow(token, targetWindow);
+            }
+            mLastImeTargetWindow = targetWindow;
+        }
+    }
+```
+[services/core/java/com/android/server/inputmethod/InputMethodManagerService.java](InputMethodManagerService.java)
+
+However, in MCIMMS, for certain cases we decided to use a simple integer token, which can be spoofable and can be messed up if integer overflow happens. This is because:
+
+ * It does not make much sense to worry about malicious multi-client IMEs, because it is guaranteed to be a pre-installed system component.
+ * Integer token is expected to be a more lightweight that `Binder` token.
+ * For that use case, integer overflow is unrealistic.
+ * Strict user separation is still enforced. Multi-client IMEs are still not allowed to interact with other users' resources by any means.
+
+Currently the following IDs are implemented as integer tokens:
+
+ * Client ID
+ * Window Handle
+   * Note that each IME client has its own Window Handle mapping table. Window Handle is valid only within the associated IME client.
diff --git a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java b/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
new file mode 100644
index 0000000..0ed56ff
--- /dev/null
+++ b/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 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.intelligence;
+
+import android.annotation.UserIdInt;
+
+/**
+ * Intelligence Manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class IntelligenceManagerInternal {
+
+    /**
+     * Checks whether the given {@code uid} owns the
+     * {@link android.service.intelligence.IntelligenceService} implementation associated with the
+     * given {@code userId}.
+     */
+    public abstract boolean isIntelligenceServiceForUser(int uid, @UserIdInt int userId);
+}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index dd993b8..b3f0629 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -1740,11 +1740,6 @@
     /**
      * The state of at least one job has changed. Here is where we could enforce various
      * policies on when we want to execute jobs.
-     * Right now the policy is such:
-     * If >1 of the ready jobs is idle mode we send all of them off
-     * if more than 2 network connectivity jobs are ready we send them all off.
-     * If more than 4 jobs total are ready we send them all off.
-     * TODO: It would be nice to consolidate these sort of high-level policies somewhere.
      */
     final class MaybeReadyJobQueueFunctor implements Consumer<JobStatus> {
         int chargingCount;
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 4ece538d..35fc29e 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -68,10 +68,10 @@
     public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
     public static final long NO_EARLIEST_RUNTIME = 0L;
 
-    static final int CONSTRAINT_CHARGING = JobInfo.CONSTRAINT_FLAG_CHARGING;
-    static final int CONSTRAINT_IDLE = JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE;
-    static final int CONSTRAINT_BATTERY_NOT_LOW = JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW;
-    static final int CONSTRAINT_STORAGE_NOT_LOW = JobInfo.CONSTRAINT_FLAG_STORAGE_NOT_LOW;
+    static final int CONSTRAINT_CHARGING = JobInfo.CONSTRAINT_FLAG_CHARGING; // 1 < 0
+    static final int CONSTRAINT_IDLE = JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE;  // 1 << 2
+    static final int CONSTRAINT_BATTERY_NOT_LOW = JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW; // 1 << 1
+    static final int CONSTRAINT_STORAGE_NOT_LOW = JobInfo.CONSTRAINT_FLAG_STORAGE_NOT_LOW; // 1 << 3
     static final int CONSTRAINT_TIMING_DELAY = 1<<31;
     static final int CONSTRAINT_DEADLINE = 1<<30;
     static final int CONSTRAINT_CONNECTIVITY = 1<<28;
@@ -975,8 +975,7 @@
     }
 
     /**
-     * @return Whether or not this job is ready to run, based on its requirements. This is true if
-     * the constraints are satisfied <strong>or</strong> the deadline on the job has expired.
+     * @return Whether or not this job is ready to run, based on its requirements.
      */
     public boolean isReady() {
         // Deadline constraint trumps other constraints (except for periodic jobs where deadline
@@ -1234,16 +1233,18 @@
         proto.end(token);
     }
 
-    // normalized bucket indices, not the AppStandby constants
-    private String bucketName(int bucket) {
-        switch (bucket) {
+    /**
+     * Returns a bucket name based on the normalized bucket indices, not the AppStandby constants.
+     */
+    String getBucketName() {
+        switch (standbyBucket) {
             case 0: return "ACTIVE";
             case 1: return "WORKING_SET";
             case 2: return "FREQUENT";
             case 3: return "RARE";
             case 4: return "NEVER";
             default:
-                return "Unknown: " + bucket;
+                return "Unknown: " + standbyBucket;
         }
     }
 
@@ -1385,6 +1386,17 @@
             if ((trackingControllers&TRACKING_TIME) != 0) pw.print(" TIME");
             pw.println();
         }
+
+        pw.print(prefix); pw.println("Implicit constraints:");
+        pw.print(prefix); pw.print("  readyNotDozing: ");
+        pw.println(mReadyNotDozing);
+        pw.print(prefix); pw.print("  readyNotRestrictedInBg: ");
+        pw.println(mReadyNotRestrictedInBg);
+        if (!job.isPeriodic() && hasDeadlineConstraint()) {
+            pw.print(prefix); pw.print("  readyDeadlineSatisfied: ");
+            pw.println(mReadyDeadlineSatisfied);
+        }
+
         if (changedAuthorities != null) {
             pw.print(prefix); pw.println("Changed authorities:");
             for (int i=0; i<changedAuthorities.size(); i++) {
@@ -1413,7 +1425,7 @@
             }
         }
         pw.print(prefix); pw.print("Standby bucket: ");
-        pw.println(bucketName(standbyBucket));
+        pw.println(getBucketName());
         if (standbyBucket > 0) {
             pw.print(prefix); pw.print("Base heartbeat: ");
             pw.println(baseHeartbeat);
@@ -1564,6 +1576,13 @@
                     JobStatusDumpProto.TRACKING_TIME);
         }
 
+        // Implicit constraints
+        final long icToken = proto.start(JobStatusDumpProto.IMPLICIT_CONSTRAINTS);
+        proto.write(JobStatusDumpProto.ImplicitConstraints.IS_NOT_DOZING, mReadyNotDozing);
+        proto.write(JobStatusDumpProto.ImplicitConstraints.IS_NOT_RESTRICTED_IN_BG,
+                mReadyNotRestrictedInBg);
+        proto.end(icToken);
+
         if (changedAuthorities != null) {
             for (int k = 0; k < changedAuthorities.size(); k++) {
                 proto.write(JobStatusDumpProto.CHANGED_AUTHORITIES, changedAuthorities.valueAt(k));
diff --git a/services/core/java/com/android/server/location/ActivityRecognitionProxy.java b/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
index f82b976..22fabb2 100644
--- a/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
+++ b/services/core/java/com/android/server/location/ActivityRecognitionProxy.java
@@ -16,59 +16,26 @@
 
 package com.android.server.location;
 
-import com.android.server.ServiceWatcher;
-
 import android.content.Context;
 import android.hardware.location.ActivityRecognitionHardware;
 import android.hardware.location.IActivityRecognitionHardwareClient;
 import android.hardware.location.IActivityRecognitionHardwareWatcher;
-import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.os.BackgroundThread;
+import com.android.server.ServiceWatcher;
+
 /**
  * Proxy class to bind GmsCore to the ActivityRecognitionHardware.
  *
  * @hide
  */
 public class ActivityRecognitionProxy {
+
     private static final String TAG = "ActivityRecognitionProxy";
 
-    private final ServiceWatcher mServiceWatcher;
-    private final boolean mIsSupported;
-    private final ActivityRecognitionHardware mInstance;
-
-    private ActivityRecognitionProxy(
-            Context context,
-            Handler handler,
-            boolean activityRecognitionHardwareIsSupported,
-            ActivityRecognitionHardware activityRecognitionHardware,
-            int overlaySwitchResId,
-            int defaultServicePackageNameResId,
-            int initialPackageNameResId) {
-        mIsSupported = activityRecognitionHardwareIsSupported;
-        mInstance = activityRecognitionHardware;
-
-        Runnable newServiceWork = new Runnable() {
-            @Override
-            public void run() {
-                bindProvider();
-            }
-        };
-
-        // prepare the connection to the provider
-        mServiceWatcher = new ServiceWatcher(
-                context,
-                TAG,
-                "com.android.location.service.ActivityRecognitionProvider",
-                overlaySwitchResId,
-                defaultServicePackageNameResId,
-                initialPackageNameResId,
-                newServiceWork,
-                handler);
-    }
-
     /**
      * Creates an instance of the proxy and binds it to the appropriate FusedProvider.
      *
@@ -76,7 +43,6 @@
      */
     public static ActivityRecognitionProxy createAndBind(
             Context context,
-            Handler handler,
             boolean activityRecognitionHardwareIsSupported,
             ActivityRecognitionHardware activityRecognitionHardware,
             int overlaySwitchResId,
@@ -84,74 +50,69 @@
             int initialPackageNameResId) {
         ActivityRecognitionProxy activityRecognitionProxy = new ActivityRecognitionProxy(
                 context,
-                handler,
                 activityRecognitionHardwareIsSupported,
                 activityRecognitionHardware,
                 overlaySwitchResId,
                 defaultServicePackageNameResId,
                 initialPackageNameResId);
 
-        // try to bind the provider
-        if (!activityRecognitionProxy.mServiceWatcher.start()) {
-            Log.e(TAG, "ServiceWatcher could not start.");
+        if (activityRecognitionProxy.mServiceWatcher.start()) {
+            return activityRecognitionProxy;
+        } else {
             return null;
         }
-        return activityRecognitionProxy;
     }
 
-    /**
-     * Helper function to bind the FusedLocationHardware to the appropriate FusedProvider instance.
-     */
-    private void bindProvider() {
-        if (!mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-            @Override
-            public void run(IBinder binder) {
-                String descriptor;
-                try {
-                    descriptor = binder.getInterfaceDescriptor();
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Unable to get interface descriptor.", e);
-                    return;
-                }
+    private final ServiceWatcher mServiceWatcher;
+    private final boolean mIsSupported;
+    private final ActivityRecognitionHardware mInstance;
 
-                if (IActivityRecognitionHardwareWatcher.class.getCanonicalName()
-                        .equals(descriptor)) {
-                    IActivityRecognitionHardwareWatcher watcher =
-                            IActivityRecognitionHardwareWatcher.Stub.asInterface(binder);
-                    if (watcher == null) {
-                        Log.e(TAG, "No watcher found on connection.");
-                        return;
-                    }
-                    if (mInstance == null) {
-                        // to keep backwards compatibility do not update the watcher when there is
-                        // no instance available, or it will cause an NPE
-                        Log.d(TAG, "AR HW instance not available, binding will be a no-op.");
-                        return;
-                    }
-                    try {
-                        watcher.onInstanceChanged(mInstance);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Error delivering hardware interface to watcher.", e);
-                    }
-                } else if (IActivityRecognitionHardwareClient.class.getCanonicalName()
-                            .equals(descriptor)) {
-                    IActivityRecognitionHardwareClient client =
-                            IActivityRecognitionHardwareClient.Stub.asInterface(binder);
-                    if (client == null) {
-                        Log.e(TAG, "No client found on connection.");
-                        return;
-                    }
-                    try {
-                        client.onAvailabilityChanged(mIsSupported, mInstance);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Error delivering hardware interface to client.", e);
-                    }
-                } else {
-                    Log.e(TAG, "Invalid descriptor found on connection: " + descriptor);
-                }
+    private ActivityRecognitionProxy(
+            Context context,
+            boolean activityRecognitionHardwareIsSupported,
+            ActivityRecognitionHardware activityRecognitionHardware,
+            int overlaySwitchResId,
+            int defaultServicePackageNameResId,
+            int initialPackageNameResId) {
+        mIsSupported = activityRecognitionHardwareIsSupported;
+        mInstance = activityRecognitionHardware;
+
+        mServiceWatcher = new ServiceWatcher(
+                context,
+                TAG,
+                "com.android.location.service.ActivityRecognitionProvider",
+                overlaySwitchResId,
+                defaultServicePackageNameResId,
+                initialPackageNameResId,
+                BackgroundThread.getHandler()) {
+            @Override
+            protected void onBind() {
+                runOnBinder(ActivityRecognitionProxy.this::initializeService);
             }
-        })) {
-            Log.e(TAG, "Null binder found on connection.");
+        };
+    }
+
+    private void initializeService(IBinder binder) {
+        try {
+            String descriptor = binder.getInterfaceDescriptor();
+
+            if (IActivityRecognitionHardwareWatcher.class.getCanonicalName().equals(
+                    descriptor)) {
+                IActivityRecognitionHardwareWatcher watcher =
+                        IActivityRecognitionHardwareWatcher.Stub.asInterface(binder);
+                if (mInstance != null) {
+                    watcher.onInstanceChanged(mInstance);
+                }
+            } else if (IActivityRecognitionHardwareClient.class.getCanonicalName()
+                    .equals(descriptor)) {
+                IActivityRecognitionHardwareClient client =
+                        IActivityRecognitionHardwareClient.Stub.asInterface(binder);
+                client.onAvailabilityChanged(mIsSupported, mInstance);
+            } else {
+                Log.e(TAG, "Invalid descriptor found on connection: " + descriptor);
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
         }
     }
 }
diff --git a/services/core/java/com/android/server/location/ContextHubClientBroker.java b/services/core/java/com/android/server/location/ContextHubClientBroker.java
index 6423470..6612d02 100644
--- a/services/core/java/com/android/server/location/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/ContextHubClientBroker.java
@@ -40,6 +40,8 @@
  * notification callbacks. This class implements the IContextHubClient object, and the implemented
  * APIs must be thread-safe.
  *
+ * TODO: Consider refactoring this class via inheritance
+ *
  * @hide
  */
 public class ContextHubClientBroker extends IContextHubClient.Stub
@@ -92,7 +94,7 @@
     /*
      * The PendingIntent registered with this client.
      */
-    private final PendingIntentRequest mPendingIntentRequest = new PendingIntentRequest();
+    private final PendingIntentRequest mPendingIntentRequest;
 
     /*
      * Helper class to manage registered PendingIntent requests from the client.
@@ -130,41 +132,31 @@
         public void clear() {
             mPendingIntent = null;
         }
-
-        public boolean register(PendingIntent pendingIntent, long nanoAppId) {
-            boolean success = false;
-            if (hasPendingIntent()) {
-                Log.e(TAG, "Failed to register PendingIntent: registered PendingIntent exists");
-            } else {
-                mNanoAppId = nanoAppId;
-                mPendingIntent = pendingIntent;
-                success = true;
-            }
-
-            return success;
-        }
-
-        public boolean unregister(PendingIntent pendingIntent) {
-            boolean success = false;
-            if (!hasPendingIntent() || !mPendingIntent.equals(pendingIntent)) {
-                Log.e(TAG, "Failed to unregister PendingIntent: PendingIntent is not registered");
-            } else {
-                mPendingIntent = null;
-                success = true;
-            }
-
-            return success;
-        }
     }
 
     /* package */ ContextHubClientBroker(
             Context context, IContexthub contextHubProxy, ContextHubClientManager clientManager,
-            ContextHubInfo contextHubInfo, short hostEndPointId) {
+            ContextHubInfo contextHubInfo, short hostEndPointId,
+            IContextHubClientCallback callback) {
         mContext = context;
         mContextHubProxy = contextHubProxy;
         mClientManager = clientManager;
         mAttachedContextHubInfo = contextHubInfo;
         mHostEndPointId = hostEndPointId;
+        mCallbackInterface = callback;
+        mPendingIntentRequest = new PendingIntentRequest();
+    }
+
+    /* package */ ContextHubClientBroker(
+            Context context, IContexthub contextHubProxy, ContextHubClientManager clientManager,
+            ContextHubInfo contextHubInfo, short hostEndPointId, PendingIntent pendingIntent,
+            long nanoAppId) {
+        mContext = context;
+        mContextHubProxy = contextHubProxy;
+        mClientManager = clientManager;
+        mAttachedContextHubInfo = contextHubInfo;
+        mHostEndPointId = hostEndPointId;
+        mPendingIntentRequest = new PendingIntentRequest(pendingIntent, nanoAppId);
     }
 
     /**
@@ -179,11 +171,7 @@
         ContextHubServiceUtil.checkPermissions(mContext);
 
         int result;
-        IContextHubClientCallback callback = null;
-        synchronized (this) {
-            callback = mCallbackInterface;
-        }
-        if (callback != null) {
+        if (isRegistered()) {
             ContextHubMsg messageToNanoApp =
                     ContextHubServiceUtil.createHidlContextHubMessage(mHostEndPointId, message);
 
@@ -204,60 +192,16 @@
     }
 
     /**
-     * @param pendingIntent the intent to register
-     * @param nanoAppId     the ID of the nanoapp to send events for
-     * @return true on success, false otherwise
-     */
-    @Override
-    public boolean registerIntent(PendingIntent pendingIntent, long nanoAppId) {
-        ContextHubServiceUtil.checkPermissions(mContext);
-
-        boolean success = false;
-        synchronized (this) {
-            if (mCallbackInterface == null) {
-                Log.e(TAG, "Failed to register PendingIntent: client connection is closed");
-            } else {
-                success = mPendingIntentRequest.register(pendingIntent, nanoAppId);
-            }
-        }
-
-        return success;
-    }
-
-    /**
-     * @param pendingIntent the intent to unregister
-     * @return true on success, false otherwise
-     */
-    @Override
-    public boolean unregisterIntent(PendingIntent pendingIntent) {
-        ContextHubServiceUtil.checkPermissions(mContext);
-
-        boolean success = false;
-        synchronized (this) {
-            success = mPendingIntentRequest.unregister(pendingIntent);
-            if (mCallbackInterface == null) {
-                close();
-            }
-        }
-
-        return success;
-    }
-
-    /**
      * Closes the connection for this client with the service.
+     *
+     * If the client has a PendingIntent registered, this method also unregisters it.
      */
     @Override
     public void close() {
         synchronized (this) {
-            if (mCallbackInterface != null) {
-                mCallbackInterface.asBinder().unlinkToDeath(this, 0 /* flags */);
-                mCallbackInterface = null;
-            }
-            if (!mPendingIntentRequest.hasPendingIntent() && mRegistered) {
-                mClientManager.unregisterClient(mHostEndPointId);
-                mRegistered = false;
-            }
+            mPendingIntentRequest.clear();
         }
+        onClientExit();
     }
 
     /**
@@ -265,38 +209,7 @@
      */
     @Override
     public void binderDied() {
-        close();
-    }
-
-    /**
-     * Sets the callback interface for this client, only if the callback is currently unregistered.
-     *
-     * Also attaches a death recipient to a ContextHubClientBroker object. If unsuccessful, the
-     * connection is closed.
-     *
-     * @param callback the callback interface
-     * @return true if the callback was successfully set, false otherwise
-     *
-     * @throws IllegalStateException if the client has already been registered to a callback
-     */
-    /* package */
-    synchronized boolean setCallback(IContextHubClientCallback callback) {
-        boolean success = false;
-        if (mCallbackInterface != null) {
-            throw new IllegalStateException("Client is already registered with a callback");
-        } else {
-            mCallbackInterface = callback;
-            try {
-                mCallbackInterface.asBinder().linkToDeath(this, 0 /* flags */);
-                success = true;
-            } catch (RemoteException e) {
-                // The client process has died, so we close the connection.
-                Log.e(TAG, "Failed to attach death recipient to client");
-                close();
-            }
-        }
-
-        return success;
+        onClientExit();
     }
 
     /**
@@ -371,15 +284,30 @@
     }
 
     /**
-     * @param intent the PendingIntent to compare to
+     * @param intent    the PendingIntent to compare to
+     * @param nanoAppId the ID of the nanoapp of the PendingIntent to compare to
      * @return true if the given PendingIntent is currently registered, false otherwise
      */
-    /* package */ boolean hasPendingIntent(PendingIntent intent) {
+    /* package */ boolean hasPendingIntent(PendingIntent intent, long nanoAppId) {
         PendingIntent pendingIntent = null;
+        long intentNanoAppId;
         synchronized (this) {
             pendingIntent = mPendingIntentRequest.getPendingIntent();
+            intentNanoAppId = mPendingIntentRequest.getNanoAppId();
         }
-        return (pendingIntent != null) && pendingIntent.equals(intent);
+        return (pendingIntent != null) && pendingIntent.equals(intent)
+                && intentNanoAppId == nanoAppId;
+    }
+
+    /**
+     * Attaches the death recipient to the callback interface object, if any.
+     *
+     * @throws RemoteException if the client process already died
+     */
+    /* package */ void attachDeathRecipient() throws RemoteException {
+        if (mCallbackInterface != null) {
+            mCallbackInterface.asBinder().linkToDeath(this, 0 /* flags */);
+        }
     }
 
     /**
@@ -442,11 +370,29 @@
                 // The PendingIntent is no longer valid
                 Log.w(TAG, "PendingIntent has been canceled, unregistering from client"
                         + " (host endpoint ID " + mHostEndPointId + ")");
-                mPendingIntentRequest.clear();
-                if (mCallbackInterface == null) {
-                    close();
-                }
+                close();
             }
         }
     }
+
+    /**
+     * @return true if the client is still registered with the service, false otherwise
+     */
+    private synchronized boolean isRegistered() {
+        return mRegistered;
+    }
+
+    /**
+     * Invoked when a client exits either explicitly or by binder death.
+     */
+    private synchronized void onClientExit() {
+        if (mCallbackInterface != null) {
+            mCallbackInterface.asBinder().unlinkToDeath(this, 0 /* flags */);
+            mCallbackInterface = null;
+        }
+        if (!mPendingIntentRequest.hasPendingIntent() && mRegistered) {
+            mClientManager.unregisterClient(mHostEndPointId);
+            mRegistered = false;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/location/ContextHubClientManager.java b/services/core/java/com/android/server/location/ContextHubClientManager.java
index 72879dd..7293440 100644
--- a/services/core/java/com/android/server/location/ContextHubClientManager.java
+++ b/services/core/java/com/android/server/location/ContextHubClientManager.java
@@ -69,7 +69,7 @@
     /*
      * The next host endpoint ID to start iterating for the next available host endpoint ID.
      */
-    private int mNextHostEndpointId = 0;
+    private int mNextHostEndPointId = 0;
 
     /* package */ ContextHubClientManager(
             Context context, IContexthub contextHubProxy) {
@@ -89,9 +89,22 @@
      */
     /* package */ IContextHubClient registerClient(
             IContextHubClientCallback clientCallback, ContextHubInfo contextHubInfo) {
-        ContextHubClientBroker broker = createNewClientBroker(contextHubInfo);
-        if (!broker.setCallback(clientCallback)) {
-            return null; // Client process has died, so we return null
+        ContextHubClientBroker broker;
+        synchronized (this) {
+            short hostEndPointId = getHostEndPointId();
+            broker = new ContextHubClientBroker(
+                    mContext, mContextHubProxy, this /* clientManager */, contextHubInfo,
+                    hostEndPointId, clientCallback);
+            mHostEndPointIdToClientMap.put(hostEndPointId, broker);
+        }
+
+        try {
+            broker.attachDeathRecipient();
+        } catch (RemoteException e) {
+            // The client process has died, so we close the connection and return null
+            Log.e(TAG, "Failed to attach death recipient to client");
+            broker.close();
+            return null;
         }
 
         Log.d(TAG, "Registered client with host endpoint ID " + broker.getHostEndPointId());
@@ -99,32 +112,36 @@
     }
 
     /**
-     * Binds a existing and registered client with a new callback interface, provided a previously
-     * registered PendingIntent.
+     * Registers a new client with the service.
      *
-     * @param pendingIntent  a previously registered PendingIntent for a registered client
-     * @param clientCallback the callback interface of the client to bind to
-     * @param contextHubId   the ID of the hub this client is attached to
+     * @param pendingIntent  the callback interface of the client to register
+     * @param contextHubInfo the object describing the hub this client is attached to
+     * @param nanoAppId      the ID of the nanoapp to receive Intent events for
      *
      * @return the client interface
      *
-     * @throws IllegalArgumentException if no matching client is found
-     * @throws IllegalStateException    if the client has already been registered to a callback
+     * @throws IllegalArgumentException the PendingIntent was already registered for a different
+     *                                  ContextHubClient
+     * @throws IllegalStateException    if there were too many registered clients at the service
      */
-    /* package */ IContextHubClient bindClient(
-            PendingIntent pendingIntent, IContextHubClientCallback clientCallback,
-            int contextHubId) {
-        ContextHubClientBroker broker = getClientBroker(pendingIntent, contextHubId);
-        if (broker == null) {
-            throw new IllegalArgumentException("Could not find client of Context Hub (ID = "
-                    + contextHubId + ") with PendingIntent");
+    /* package */ IContextHubClient registerClient(
+            ContextHubInfo contextHubInfo, PendingIntent pendingIntent, long nanoAppId) {
+        ContextHubClientBroker broker;
+        String registerString = "Regenerated";
+        synchronized (this) {
+            broker = getClientBroker(contextHubInfo.getId(), pendingIntent, nanoAppId);
+
+            if (broker == null) {
+                short hostEndPointId = getHostEndPointId();
+                broker = new ContextHubClientBroker(
+                        mContext, mContextHubProxy, this /* clientManager */, contextHubInfo,
+                        hostEndPointId, pendingIntent, nanoAppId);
+                mHostEndPointIdToClientMap.put(hostEndPointId, broker);
+                registerString = "Registered";
+            }
         }
 
-        if (!broker.setCallback(clientCallback)) {
-            return null; // Client process has died, so we return null
-        }
-
-        Log.d(TAG, "Re-registered client with host endpoint ID " + broker.getHostEndPointId());
+        Log.d(TAG, registerString + " client with host endpoint ID " + broker.getHostEndPointId());
         return IContextHubClient.Stub.asInterface(broker);
     }
 
@@ -204,36 +221,28 @@
     }
 
     /**
-     * Creates a new ContextHubClientBroker object for a client and registers it with the client
-     * manager.
+     * Returns an available host endpoint ID.
      *
-     * @param contextHubInfo the object describing the hub this client is attached to
-     *
-     * @return the ContextHubClientBroker object
+     * @returns an available host endpoint ID
      *
      * @throws IllegalStateException if max number of clients have already registered
      */
-    private synchronized ContextHubClientBroker createNewClientBroker(
-            ContextHubInfo contextHubInfo) {
+    private short getHostEndPointId() {
         if (mHostEndPointIdToClientMap.size() == MAX_CLIENT_ID + 1) {
             throw new IllegalStateException("Could not register client - max limit exceeded");
         }
 
-        ContextHubClientBroker broker = null;
-        int id = mNextHostEndpointId;
+        int id = mNextHostEndPointId;
         for (int i = 0; i <= MAX_CLIENT_ID; i++) {
             if (!mHostEndPointIdToClientMap.containsKey((short) id)) {
-                broker = new ContextHubClientBroker(
-                        mContext, mContextHubProxy, this, contextHubInfo, (short) id);
-                mHostEndPointIdToClientMap.put((short) id, broker);
-                mNextHostEndpointId = (id == MAX_CLIENT_ID) ? 0 : id + 1;
+                mNextHostEndPointId = (id == MAX_CLIENT_ID) ? 0 : id + 1;
                 break;
             }
 
             id = (id == MAX_CLIENT_ID) ? 0 : id + 1;
         }
 
-        return broker;
+        return (short) id;
     }
 
     /**
@@ -267,9 +276,10 @@
      * @param contextHubId  the ID of the Context Hub the client is attached to
      * @return the matching ContextHubClientBroker, null if not found
      */
-    private ContextHubClientBroker getClientBroker(PendingIntent pendingIntent, int contextHubId) {
+    private ContextHubClientBroker getClientBroker(
+            int contextHubId, PendingIntent pendingIntent, long nanoAppId) {
         for (ContextHubClientBroker broker : mHostEndPointIdToClientMap.values()) {
-            if (broker.hasPendingIntent(pendingIntent)
+            if (broker.hasPendingIntent(pendingIntent, nanoAppId)
                     && broker.getAttachedContextHubId() == contextHubId) {
                 return broker;
             }
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index 215e67c..52f1c6b 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -632,34 +632,26 @@
     }
 
     /**
-     * Recreates and binds a IContextHubClientCallback interface to an existing and registered
-     * client at the service for the specified Context Hub, provided a previously registered
-     * PendingIntent.
+     * Creates and registers a PendingIntent client at the service for the specified Context Hub.
      *
-     * @param pendingIntent  the PendingIntent previously registered for the client
-     * @param clientCallback the client interface to register with the service
-     * @param contextHubId   the ID of the hub this client is attached to
-     * @return the generated client interface, null if registration was unsuccessful
+     * @param contextHubId  the ID of the hub this client is attached to
+     * @param pendingIntent the PendingIntent associated with this client
+     * @param nanoAppId     the ID of the nanoapp PendingIntent events will be sent for
+     * @return the generated client interface
      *
-     * @throws IllegalArgumentException if contextHubId is not a valid ID
-     * @throws NullPointerException if clientCallback or pendingIntent is null
+     * @throws IllegalArgumentException if hubInfo does not represent a valid hub
+     * @throws IllegalStateException    if there were too many registered clients at the service
      */
     @Override
-    public IContextHubClient bindClient(
-            PendingIntent pendingIntent, IContextHubClientCallback clientCallback,
-            int contextHubId) throws RemoteException {
+    public IContextHubClient createPendingIntentClient(
+            int contextHubId, PendingIntent pendingIntent, long nanoAppId) throws RemoteException {
         checkPermissions();
         if (!isValidContextHubId(contextHubId)) {
             throw new IllegalArgumentException("Invalid context hub ID " + contextHubId);
         }
-        if (pendingIntent == null) {
-            throw new NullPointerException("Cannot create client with null pending intent");
-        }
-        if (clientCallback == null) {
-            throw new NullPointerException("Cannot create client with null callback");
-        }
 
-        return mClientManager.bindClient(pendingIntent, clientCallback, contextHubId);
+        ContextHubInfo contextHubInfo = mContextHubIdToInfoMap.get(contextHubId);
+        return mClientManager.registerClient(contextHubInfo, pendingIntent, nanoAppId);
     }
 
     /**
diff --git a/services/core/java/com/android/server/location/GeocoderProxy.java b/services/core/java/com/android/server/location/GeocoderProxy.java
index 9ad4aa1..f1de371 100644
--- a/services/core/java/com/android/server/location/GeocoderProxy.java
+++ b/services/core/java/com/android/server/location/GeocoderProxy.java
@@ -20,12 +20,12 @@
 import android.location.Address;
 import android.location.GeocoderParams;
 import android.location.IGeocodeProvider;
-import android.os.Handler;
-import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.os.BackgroundThread;
 import com.android.server.ServiceWatcher;
+
 import java.util.List;
 
 /**
@@ -36,14 +36,13 @@
 
     private static final String SERVICE_ACTION = "com.android.location.service.GeocodeProvider";
 
-    private final Context mContext;
     private final ServiceWatcher mServiceWatcher;
 
     public static GeocoderProxy createAndBind(Context context,
             int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId, Handler handler) {
+            int initialPackageNamesResId) {
         GeocoderProxy proxy = new GeocoderProxy(context, overlaySwitchResId,
-            defaultServicePackageNameResId, initialPackageNamesResId, handler);
+                defaultServicePackageNameResId, initialPackageNamesResId);
         if (proxy.bind()) {
             return proxy;
         } else {
@@ -53,34 +52,30 @@
 
     private GeocoderProxy(Context context,
             int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId, Handler handler) {
-        mContext = context;
-
-        mServiceWatcher = new ServiceWatcher(mContext, TAG, SERVICE_ACTION, overlaySwitchResId,
-            defaultServicePackageNameResId, initialPackageNamesResId, null, handler);
+            int initialPackageNamesResId) {
+        mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
+                defaultServicePackageNameResId, initialPackageNamesResId,
+                BackgroundThread.getHandler());
     }
 
-    private boolean bind () {
+    private boolean bind() {
         return mServiceWatcher.start();
     }
 
     public String getConnectedPackageName() {
-        return mServiceWatcher.getBestPackageName();
+        return mServiceWatcher.getCurrentPackageName();
     }
 
     public String getFromLocation(double latitude, double longitude, int maxResults,
             GeocoderParams params, List<Address> addrs) {
-        final String[] result = new String[] {"Service not Available"};
-        mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-            @Override
-            public void run(IBinder binder) {
-                IGeocodeProvider provider = IGeocodeProvider.Stub.asInterface(binder);
-                try {
-                    result[0] = provider.getFromLocation(
-                            latitude, longitude, maxResults, params, addrs);
-                } catch (RemoteException e) {
-                    Log.w(TAG, e);
-                }
+        final String[] result = new String[]{"Service not Available"};
+        mServiceWatcher.runOnBinder(binder -> {
+            IGeocodeProvider provider = IGeocodeProvider.Stub.asInterface(binder);
+            try {
+                result[0] = provider.getFromLocation(
+                        latitude, longitude, maxResults, params, addrs);
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
             }
         });
         return result[0];
@@ -90,18 +85,15 @@
             double lowerLeftLatitude, double lowerLeftLongitude,
             double upperRightLatitude, double upperRightLongitude, int maxResults,
             GeocoderParams params, List<Address> addrs) {
-        final String[] result = new String[] {"Service not Available"};
-        mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-            @Override
-            public void run(IBinder binder) {
-                IGeocodeProvider provider = IGeocodeProvider.Stub.asInterface(binder);
-                try {
-                    result[0] = provider.getFromLocationName(locationName, lowerLeftLatitude,
-                            lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
-                            maxResults, params, addrs);
-                } catch (RemoteException e) {
-                    Log.w(TAG, e);
-                }
+        final String[] result = new String[]{"Service not Available"};
+        mServiceWatcher.runOnBinder(binder -> {
+            IGeocodeProvider provider = IGeocodeProvider.Stub.asInterface(binder);
+            try {
+                result[0] = provider.getFromLocationName(locationName, lowerLeftLatitude,
+                        lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
+                        maxResults, params, addrs);
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
             }
         });
         return result[0];
diff --git a/services/core/java/com/android/server/location/GeofenceProxy.java b/services/core/java/com/android/server/location/GeofenceProxy.java
index eb47b2f..ca4f7fe 100644
--- a/services/core/java/com/android/server/location/GeofenceProxy.java
+++ b/services/core/java/com/android/server/location/GeofenceProxy.java
@@ -15,61 +15,60 @@
  */
 package com.android.server.location;
 
+import android.annotation.Nullable;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.hardware.location.GeofenceHardwareService;
 import android.hardware.location.IGeofenceHardware;
+import android.location.IFusedGeofenceHardware;
 import android.location.IGeofenceProvider;
 import android.location.IGpsGeofenceHardware;
-import android.location.IFusedGeofenceHardware;
-import android.content.Context;
-import android.os.Handler;
 import android.os.IBinder;
-import android.os.Message;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Log;
+
+import com.android.internal.os.BackgroundThread;
 import com.android.server.ServiceWatcher;
 
 /**
  * @hide
  */
 public final class GeofenceProxy {
+
     private static final String TAG = "GeofenceProxy";
-    private static final String SERVICE_ACTION =
-            "com.android.location.service.GeofenceProvider";
-    private final ServiceWatcher mServiceWatcher;
+    private static final String SERVICE_ACTION = "com.android.location.service.GeofenceProvider";
+
     private final Context mContext;
+    private final ServiceWatcher mServiceWatcher;
+
+    @Nullable
     private final IGpsGeofenceHardware mGpsGeofenceHardware;
+    @Nullable
     private final IFusedGeofenceHardware mFusedGeofenceHardware;
 
-    private final Object mLock = new Object();
+    private volatile IGeofenceHardware mGeofenceHardware;
 
-    // Access to mGeofenceHardware needs to be synchronized by mLock.
-    private IGeofenceHardware mGeofenceHardware;
-
-    private static final int GEOFENCE_PROVIDER_CONNECTED = 1;
-    private static final int GEOFENCE_HARDWARE_CONNECTED = 2;
-    private static final int GEOFENCE_HARDWARE_DISCONNECTED = 3;
-    private static final int GEOFENCE_GPS_HARDWARE_CONNECTED = 4;
-    private static final int GEOFENCE_GPS_HARDWARE_DISCONNECTED = 5;
-
-    private Runnable mRunnable = new Runnable() {
-        @Override
-        public void run() {
-            mHandler.sendEmptyMessage(GEOFENCE_PROVIDER_CONNECTED);
+    private final ServiceWatcher.BinderRunner mUpdateGeofenceHardware = (binder) -> {
+        IGeofenceProvider provider = IGeofenceProvider.Stub.asInterface(binder);
+        try {
+            provider.setGeofenceHardware(mGeofenceHardware);
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
         }
     };
 
     public static GeofenceProxy createAndBind(Context context,
             int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence,
-            IFusedGeofenceHardware fusedGeofenceHardware) {
+            int initialPackageNamesResId, @Nullable IGpsGeofenceHardware gpsGeofence,
+            @Nullable IFusedGeofenceHardware fusedGeofenceHardware) {
         GeofenceProxy proxy = new GeofenceProxy(context, overlaySwitchResId,
-            defaultServicePackageNameResId, initialPackageNamesResId, handler, gpsGeofence,
-            fusedGeofenceHardware);
-        if (proxy.bindGeofenceProvider()) {
+                defaultServicePackageNameResId, initialPackageNamesResId, gpsGeofence,
+                fusedGeofenceHardware);
+
+        if (proxy.bind()) {
             return proxy;
         } else {
             return null;
@@ -78,111 +77,56 @@
 
     private GeofenceProxy(Context context,
             int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId, Handler handler, IGpsGeofenceHardware gpsGeofence,
-            IFusedGeofenceHardware fusedGeofenceHardware) {
+            int initialPackageNamesResId, @Nullable IGpsGeofenceHardware gpsGeofence,
+            @Nullable IFusedGeofenceHardware fusedGeofenceHardware) {
         mContext = context;
         mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
-            defaultServicePackageNameResId, initialPackageNamesResId, mRunnable, handler);
+                defaultServicePackageNameResId, initialPackageNamesResId,
+                BackgroundThread.getHandler()) {
+            @Override
+            protected void onBind() {
+                runOnBinder(mUpdateGeofenceHardware);
+            }
+        };
+
         mGpsGeofenceHardware = gpsGeofence;
         mFusedGeofenceHardware = fusedGeofenceHardware;
-        bindHardwareGeofence();
+
+        mGeofenceHardware = null;
     }
 
-    private boolean bindGeofenceProvider() {
-        return mServiceWatcher.start();
+    private boolean bind() {
+        if (mServiceWatcher.start()) {
+            mContext.bindServiceAsUser(new Intent(mContext, GeofenceHardwareService.class),
+                    new GeofenceProxyServiceConnection(), Context.BIND_AUTO_CREATE,
+                    UserHandle.SYSTEM);
+            return true;
+        }
+
+        return false;
     }
 
-    private void bindHardwareGeofence() {
-        mContext.bindServiceAsUser(new Intent(mContext, GeofenceHardwareService.class),
-                mServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
-    }
+    private class GeofenceProxyServiceConnection implements ServiceConnection {
 
-    private ServiceConnection mServiceConnection = new ServiceConnection() {
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
-            synchronized (mLock) {
-                mGeofenceHardware = IGeofenceHardware.Stub.asInterface(service);
-                mHandler.sendEmptyMessage(GEOFENCE_HARDWARE_CONNECTED);
+            IGeofenceHardware geofenceHardware = IGeofenceHardware.Stub.asInterface(service);
+
+            try {
+                geofenceHardware.setGpsGeofenceHardware(mGpsGeofenceHardware);
+                geofenceHardware.setFusedGeofenceHardware(mFusedGeofenceHardware);
+
+                mGeofenceHardware = geofenceHardware;
+                mServiceWatcher.runOnBinder(mUpdateGeofenceHardware);
+            } catch (Exception e) {
+                Log.w(TAG, e);
             }
         }
 
         @Override
         public void onServiceDisconnected(ComponentName name) {
-            synchronized (mLock) {
-                mGeofenceHardware = null;
-                mHandler.sendEmptyMessage(GEOFENCE_HARDWARE_DISCONNECTED);
-            }
-        }
-    };
-
-    private void setGeofenceHardwareInProviderLocked() {
-        mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-            @Override
-            public void run(IBinder binder) {
-                final IGeofenceProvider provider = IGeofenceProvider.Stub.asInterface(binder);
-                try {
-                    provider.setGeofenceHardware(mGeofenceHardware);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Remote Exception: setGeofenceHardwareInProviderLocked: " + e);
-                }
-            }
-        });
-    }
-
-    private void setGpsGeofenceLocked() {
-        try {
-            if (mGpsGeofenceHardware != null) {
-                mGeofenceHardware.setGpsGeofenceHardware(mGpsGeofenceHardware);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error while connecting to GeofenceHardwareService");
+            mGeofenceHardware = null;
+            mServiceWatcher.runOnBinder(mUpdateGeofenceHardware);
         }
     }
-
-    private void setFusedGeofenceLocked() {
-        try {
-            mGeofenceHardware.setFusedGeofenceHardware(mFusedGeofenceHardware);
-        } catch(RemoteException e) {
-            Log.e(TAG, "Error while connecting to GeofenceHardwareService");
-        }
-    }
-
-    // This needs to be reworked, when more services get added,
-    // Might need a state machine or add a framework utility class,
-    private Handler mHandler = new Handler() {
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case GEOFENCE_PROVIDER_CONNECTED:
-                    synchronized (mLock) {
-                        if (mGeofenceHardware != null) {
-                            setGeofenceHardwareInProviderLocked();
-                        }
-                        // else: the geofence provider will be notified when the connection to
-                        // GeofenceHardwareService is established.
-                    }
-                    break;
-                case GEOFENCE_HARDWARE_CONNECTED:
-                    synchronized (mLock) {
-                        // Theoretically this won't happen because once the GeofenceHardwareService
-                        // is connected to, we won't lose connection to it because it's a system
-                        // service. But this check does make the code more robust.
-                        if (mGeofenceHardware != null) {
-                            setGpsGeofenceLocked();
-                            setFusedGeofenceLocked();
-                            setGeofenceHardwareInProviderLocked();
-                        }
-                    }
-                    break;
-                case GEOFENCE_HARDWARE_DISCONNECTED:
-                    synchronized (mLock) {
-                        if (mGeofenceHardware == null) {
-                            setGeofenceHardwareInProviderLocked();
-                        }
-                    }
-                    break;
-            }
-        }
-    };
 }
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 53d54ba..9e6e381 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -24,7 +24,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.database.Cursor;
 import android.hardware.location.GeofenceHardware;
 import android.hardware.location.GeofenceHardwareImpl;
 import android.location.Criteria;
@@ -42,12 +41,6 @@
 import android.location.LocationManager;
 import android.location.LocationProvider;
 import android.location.LocationRequest;
-import android.net.ConnectivityManager;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.net.NetworkRequest;
-import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.BatteryStats;
 import android.os.Binder;
@@ -67,7 +60,6 @@
 import android.os.WorkSource;
 import android.os.WorkSource.WorkChain;
 import android.provider.Settings;
-import android.provider.Telephony.Carriers;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
@@ -92,8 +84,6 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -135,14 +125,6 @@
     private static final int GPS_STATUS_ENGINE_ON = 3;
     private static final int GPS_STATUS_ENGINE_OFF = 4;
 
-    // these need to match AGnssStatusValue enum in IAGnssCallback.hal
-    /** AGPS status event values. */
-    private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
-    private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
-    private static final int GPS_AGPS_DATA_CONNECTED = 3;
-    private static final int GPS_AGPS_DATA_CONN_DONE = 4;
-    private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
-
     // these need to match GnssLocationFlags enum in types.hal
     private static final int LOCATION_INVALID = 0;
     private static final int LOCATION_HAS_LAT_LONG = 1;
@@ -188,17 +170,6 @@
     private static final int AGPS_TYPE_SUPL = 1;
     private static final int AGPS_TYPE_C2K = 2;
 
-    // these must match the ApnIpType enum in IAGnss.hal
-    private static final int APN_INVALID = 0;
-    private static final int APN_IPV4 = 1;
-    private static final int APN_IPV6 = 2;
-    private static final int APN_IPV4V6 = 3;
-
-    // for mAGpsDataConnectionState
-    private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
-    private static final int AGPS_DATA_CONNECTION_OPENING = 1;
-    private static final int AGPS_DATA_CONNECTION_OPEN = 2;
-
     // Handler messages
     private static final int CHECK_LOCATION = 1;
     private static final int ENABLE = 2;
@@ -254,9 +225,6 @@
     private static final long LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS = 1000;
     // Default update duration in milliseconds for REQUEST_LOCATION.
     private static final long LOCATION_UPDATE_DURATION_MILLIS = 10 * 1000;
-    // Default time limit in milliseconds for the ConnectivityManager to find a suitable
-    // network with SUPL connectivity or report an error.
-    private static final int SUPL_NETWORK_REQUEST_TIMEOUT_MILLIS = 10 * 1000;
 
     /** simpler wrapper for ProviderRequest + Worksource */
     private static class GpsRequest {
@@ -427,12 +395,7 @@
     // Handler for processing events
     private Handler mHandler;
 
-    /** It must be accessed only inside {@link #mHandler}. */
-    private int mAGpsDataConnectionState;
-    /** It must be accessed only inside {@link #mHandler}. */
-    private InetAddress mAGpsDataConnectionIpAddr;
-
-    private final ConnectivityManager mConnMgr;
+    private final GnssNetworkConnectivityHandler mNetworkConnectivityHandler;
     private final GpsNetInitiatedHandler mNIHandler;
 
     // Wakelocks
@@ -507,60 +470,6 @@
     public GnssNavigationMessageProvider getGnssNavigationMessageProvider() {
         return mGnssNavigationMessageProvider;
     }
-
-    /**
-     * Callback used to listen for data connectivity changes.
-     */
-    private final ConnectivityManager.NetworkCallback mNetworkConnectivityCallback =
-            new ConnectivityManager.NetworkCallback() {
-                @Override
-                public void onAvailable(Network network) {
-                    mNtpTimeHelper.onNetworkAvailable();
-                    if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
-                        if (mSupportsXtra) {
-                            // Download only if supported, (prevents an unneccesary on-boot
-                            // download)
-                            xtraDownloadRequest();
-                        }
-                    }
-                    // Always on, notify HAL so it can get data it needs
-                    sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
-                }
-
-                @Override
-                public void onLost(Network network) {
-                    sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
-                }
-            };
-
-    /**
-     * Callback used to listen for availability of a requested SUPL connection.
-     * It is kept as a separate instance from {@link #mNetworkConnectivityCallback} to be able to
-     * manage the registration/un-registration lifetimes separate.
-     */
-    private final ConnectivityManager.NetworkCallback mSuplConnectivityCallback =
-            new ConnectivityManager.NetworkCallback() {
-                @Override
-                public void onAvailable(Network network) {
-                    if (DEBUG) Log.d(TAG, "SUPL network connection available.");
-                    // Specific to a change to a SUPL enabled network becoming ready
-                    sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
-                }
-
-                @Override
-                public void onLost(Network network) {
-                    Log.i(TAG, "SUPL network connection lost.");
-                    releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
-                }
-
-                @Override
-                public void onUnavailable() {
-                    Log.i(TAG, "SUPL network connection request timed out.");
-                    // Could not setup the connection to the network in the specified time duration.
-                    releaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
-                }
-            };
-
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -793,7 +702,10 @@
         mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
         mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
 
-        mConnMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        mNetworkConnectivityHandler = new GnssNetworkConnectivityHandler(
+                context,
+                GnssLocationProvider.this::onNetworkAvailable,
+                looper);
 
         // App ops service to keep track of who is accessing the GPS
         mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -843,8 +755,8 @@
                 return isEnabled();
             }
         };
-        mGnssMetrics = new GnssMetrics(mBatteryStats);
 
+        mGnssMetrics = new GnssMetrics(mBatteryStats);
         mNtpTimeHelper = new NtpTimeHelper(mContext, looper, this);
         mGnssSatelliteBlacklistHelper = new GnssSatelliteBlacklistHelper(mContext,
                 looper, this);
@@ -866,7 +778,6 @@
         return PROPERTIES;
     }
 
-
     /**
      * Implements {@link InjectNtpTimeCallback#injectTime}
      */
@@ -875,124 +786,17 @@
         native_inject_time(time, timeReference, uncertainty);
     }
 
-    private void handleUpdateNetworkState(Network network) {
-        // retrieve NetworkInfo for this UID
-        NetworkInfo info = mConnMgr.getNetworkInfo(network);
-
-        boolean networkAvailable = false;
-        boolean isConnected = false;
-        int type = ConnectivityManager.TYPE_NONE;
-        boolean isRoaming = false;
-        String apnName = null;
-
-        if (info != null) {
-            networkAvailable = info.isAvailable() && TelephonyManager.getDefault().getDataEnabled();
-            isConnected = info.isConnected();
-            type = info.getType();
-            isRoaming = info.isRoaming();
-            apnName = info.getExtraInfo();
-        }
-
-        if (DEBUG) {
-            String message = String.format(
-                    "UpdateNetworkState, state=%s, connected=%s, info=%s, capabilities=%S",
-                    agpsDataConnStateAsString(),
-                    isConnected,
-                    info,
-                    mConnMgr.getNetworkCapabilities(network));
-            Log.d(TAG, message);
-        }
-
-        if (native_is_agps_ril_supported()) {
-            String defaultApn = getSelectedApn();
-            if (defaultApn == null) {
-                defaultApn = "dummy-apn";
+    /**
+     * Implements {@link GnssNetworkConnectivityHandler.GnssNetworkListener#onNetworkAvailable()}
+     */
+    private void onNetworkAvailable() {
+        mNtpTimeHelper.onNetworkAvailable();
+        if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
+            if (mSupportsXtra) {
+                // Download only if supported, (prevents an unneccesary on-boot
+                // download)
+                xtraDownloadRequest();
             }
-
-            native_update_network_state(
-                    isConnected,
-                    type,
-                    isRoaming,
-                    networkAvailable,
-                    apnName,
-                    defaultApn);
-        } else if (DEBUG) {
-            Log.d(TAG, "Skipped network state update because GPS HAL AGPS-RIL is not  supported");
-        }
-
-        if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
-            if (isConnected) {
-                if (apnName == null) {
-                    // assign a dummy value in the case of C2K as otherwise we will have a runtime
-                    // exception in the following call to native_agps_data_conn_open
-                    apnName = "dummy-apn";
-                }
-                int apnIpType = getApnIpType(apnName);
-                setRouting();
-                if (DEBUG) {
-                    String message = String.format(
-                            "native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
-                            apnName,
-                            apnIpType);
-                    Log.d(TAG, message);
-                }
-                native_agps_data_conn_open(apnName, apnIpType);
-                mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
-            } else {
-                handleReleaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
-            }
-        }
-    }
-
-    private void handleRequestSuplConnection(InetAddress address) {
-        if (DEBUG) {
-            String message = String.format(
-                    "requestSuplConnection, state=%s, address=%s",
-                    agpsDataConnStateAsString(),
-                    address);
-            Log.d(TAG, message);
-        }
-
-        if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
-            return;
-        }
-        mAGpsDataConnectionIpAddr = address;
-        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
-
-        NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
-        requestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
-        requestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
-        NetworkRequest request = requestBuilder.build();
-        mConnMgr.requestNetwork(
-                request,
-                mSuplConnectivityCallback,
-                SUPL_NETWORK_REQUEST_TIMEOUT_MILLIS);
-    }
-
-    private void handleReleaseSuplConnection(int agpsDataConnStatus) {
-        if (DEBUG) {
-            String message = String.format(
-                    "releaseSuplConnection, state=%s, status=%s",
-                    agpsDataConnStateAsString(),
-                    agpsDataConnStatusAsString(agpsDataConnStatus));
-            Log.d(TAG, message);
-        }
-
-        if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_CLOSED) {
-            return;
-        }
-        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
-
-        mConnMgr.unregisterNetworkCallback(mSuplConnectivityCallback);
-        switch (agpsDataConnStatus) {
-            case GPS_AGPS_DATA_CONN_FAILED:
-                native_agps_data_conn_failed();
-                break;
-            case GPS_RELEASE_AGPS_DATA_CONN:
-                native_agps_data_conn_closed();
-                break;
-            default:
-                Log.e(TAG, "Invalid status to release SUPL connection: " + agpsDataConnStatus);
         }
     }
 
@@ -1091,7 +895,7 @@
             // already downloading data
             return;
         }
-        if (!isDataNetworkConnected()) {
+        if (!mNetworkConnectivityHandler.isDataNetworkConnected()) {
             // try again when network is up
             mDownloadXtraDataPending = STATE_PENDING_NETWORK;
             return;
@@ -1822,41 +1626,7 @@
      * called from native code to update AGPS status
      */
     private void reportAGpsStatus(int type, int status, byte[] ipaddr) {
-        switch (status) {
-            case GPS_REQUEST_AGPS_DATA_CONN:
-                if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
-                Log.v(TAG, "Received SUPL IP addr[]: " + Arrays.toString(ipaddr));
-                InetAddress connectionIpAddress = null;
-                if (ipaddr != null) {
-                    try {
-                        connectionIpAddress = InetAddress.getByAddress(ipaddr);
-                        if (DEBUG) Log.d(TAG, "IP address converted to: " + connectionIpAddress);
-                    } catch (UnknownHostException e) {
-                        Log.e(TAG, "Bad IP Address: " + ipaddr, e);
-                    }
-                }
-                sendMessage(REQUEST_SUPL_CONNECTION, 0 /*arg*/, connectionIpAddress);
-                break;
-            case GPS_RELEASE_AGPS_DATA_CONN:
-                if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
-                releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
-                break;
-            case GPS_AGPS_DATA_CONNECTED:
-                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
-                break;
-            case GPS_AGPS_DATA_CONN_DONE:
-                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
-                break;
-            case GPS_AGPS_DATA_CONN_FAILED:
-                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
-                break;
-            default:
-                if (DEBUG) Log.d(TAG, "Received Unknown AGPS status: " + status);
-        }
-    }
-
-    private void releaseSuplConnection(int connStatus) {
-        sendMessage(RELEASE_SUPL_CONNECTION, connStatus, null /*obj*/);
+        mNetworkConnectivityHandler.onReportAGpsStatus(type, status, ipaddr);
     }
 
     /**
@@ -2305,8 +2075,8 @@
         // note that this assumes the message will not be removed from the queue before
         // it is handled (otherwise the wake lock would be leaked).
         mWakeLock.acquire();
-        if (Log.isLoggable(TAG, Log.INFO)) {
-            Log.i(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
+        if (DEBUG) {
+            Log.d(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
                     + ", " + obj + ")");
         }
         mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
@@ -2332,15 +2102,6 @@
                     GpsRequest gpsRequest = (GpsRequest) msg.obj;
                     handleSetRequest(gpsRequest.request, gpsRequest.source);
                     break;
-                case UPDATE_NETWORK_STATE:
-                    handleUpdateNetworkState((Network) msg.obj);
-                    break;
-                case REQUEST_SUPL_CONNECTION:
-                    handleRequestSuplConnection((InetAddress) msg.obj);
-                    break;
-                case RELEASE_SUPL_CONNECTION:
-                    handleReleaseSuplConnection(msg.arg1);
-                    break;
                 case INJECT_NTP_TIME:
                     mNtpTimeHelper.retrieveAndInjectNtpTime();
                     break;
@@ -2372,8 +2133,8 @@
             if (msg.arg2 == 1) {
                 // wakelock was taken for this message, release it
                 mWakeLock.release();
-                if (Log.isLoggable(TAG, Log.INFO)) {
-                    Log.i(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message)
+                if (DEBUG) {
+                    Log.d(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message)
                             + ", " + msg.arg1 + ", " + msg.obj + ")");
                 }
             }
@@ -2426,14 +2187,7 @@
             intentFilter.addAction(SIM_STATE_CHANGED);
             mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
 
-            // register for connectivity change events, this is equivalent to the deprecated way of
-            // registering for CONNECTIVITY_ACTION broadcasts
-            NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
-            networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
-            networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
-            networkRequestBuilder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
-            NetworkRequest networkRequest = networkRequestBuilder.build();
-            mConnMgr.registerNetworkCallback(networkRequest, mNetworkConnectivityCallback);
+            mNetworkConnectivityHandler.registerNetworkCallbacks();
 
             // listen for PASSIVE_PROVIDER updates
             LocationManager locManager =
@@ -2491,160 +2245,6 @@
         }
     }
 
-    private String getSelectedApn() {
-        Uri uri = Uri.parse("content://telephony/carriers/preferapn");
-        Cursor cursor = null;
-        try {
-            cursor = mContext.getContentResolver().query(
-                    uri,
-                    new String[]{"apn"},
-                    null /* selection */,
-                    null /* selectionArgs */,
-                    Carriers.DEFAULT_SORT_ORDER);
-            if (cursor != null && cursor.moveToFirst()) {
-                return cursor.getString(0);
-            } else {
-                Log.e(TAG, "No APN found to select.");
-            }
-        } catch (Exception e) {
-            Log.e(TAG, "Error encountered on selecting the APN.", e);
-        } finally {
-            if (cursor != null) {
-                cursor.close();
-            }
-        }
-
-        return null;
-    }
-
-    private int getApnIpType(String apn) {
-        ensureInHandlerThread();
-        if (apn == null) {
-            return APN_INVALID;
-        }
-        TelephonyManager phone = (TelephonyManager)
-                mContext.getSystemService(Context.TELEPHONY_SERVICE);
-        // Carrier configuration may override framework roaming state, we need to use the actual
-        // modem roaming state instead of the framework roaming state.
-        boolean isDataRoamingFromRegistration = phone.getServiceState().
-                getDataRoamingFromRegistration();
-        String projection = isDataRoamingFromRegistration ? Carriers.ROAMING_PROTOCOL :
-                Carriers.PROTOCOL;
-        String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
-        Cursor cursor = null;
-        try {
-            cursor = mContext.getContentResolver().query(
-                    Carriers.CONTENT_URI,
-                    new String[]{projection},
-                    selection,
-                    null,
-                    Carriers.DEFAULT_SORT_ORDER);
-
-            if (null != cursor && cursor.moveToFirst()) {
-                return translateToApnIpType(cursor.getString(0), apn);
-            } else {
-                Log.e(TAG, "No entry found in query for APN: " + apn);
-            }
-        } catch (Exception e) {
-            Log.e(TAG, "Error encountered on APN query for: " + apn, e);
-        } finally {
-            if (cursor != null) {
-                cursor.close();
-            }
-        }
-
-        return APN_INVALID;
-    }
-
-    private int translateToApnIpType(String ipProtocol, String apn) {
-        if ("IP".equals(ipProtocol)) {
-            return APN_IPV4;
-        }
-        if ("IPV6".equals(ipProtocol)) {
-            return APN_IPV6;
-        }
-        if ("IPV4V6".equals(ipProtocol)) {
-            return APN_IPV4V6;
-        }
-
-        // we hit the default case so the ipProtocol is not recognized
-        String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
-        Log.e(TAG, message);
-        return APN_INVALID;
-    }
-
-    private void setRouting() {
-        if (mAGpsDataConnectionIpAddr == null) {
-            return;
-        }
-
-        // TODO: replace the use of this deprecated API
-        boolean result = mConnMgr.requestRouteToHostAddress(
-                ConnectivityManager.TYPE_MOBILE_SUPL,
-                mAGpsDataConnectionIpAddr);
-
-        if (!result) {
-            Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr);
-        } else if (DEBUG) {
-            Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr);
-        }
-    }
-
-    /**
-     * @return {@code true} if there is a data network available for outgoing connections,
-     * {@code false} otherwise.
-     */
-    private boolean isDataNetworkConnected() {
-        NetworkInfo activeNetworkInfo = mConnMgr.getActiveNetworkInfo();
-        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
-    }
-
-    /**
-     * Ensures the calling function is running in the thread associated with {@link #mHandler}.
-     */
-    private void ensureInHandlerThread() {
-        if (mHandler != null && Looper.myLooper() == mHandler.getLooper()) {
-            return;
-        }
-        throw new RuntimeException("This method must run on the Handler thread.");
-    }
-
-    /**
-     * @return A string representing the current state stored in {@link #mAGpsDataConnectionState}.
-     */
-    private String agpsDataConnStateAsString() {
-        switch (mAGpsDataConnectionState) {
-            case AGPS_DATA_CONNECTION_CLOSED:
-                return "CLOSED";
-            case AGPS_DATA_CONNECTION_OPEN:
-                return "OPEN";
-            case AGPS_DATA_CONNECTION_OPENING:
-                return "OPENING";
-            default:
-                return "<Unknown>";
-        }
-    }
-
-    /**
-     * @return A string representing the given GPS_AGPS_DATA status.
-     */
-    private String agpsDataConnStatusAsString(int agpsDataConnStatus) {
-        switch (agpsDataConnStatus) {
-            case GPS_AGPS_DATA_CONNECTED:
-                return "CONNECTED";
-            case GPS_AGPS_DATA_CONN_DONE:
-                return "DONE";
-            case GPS_AGPS_DATA_CONN_FAILED:
-                return "FAILED";
-            case GPS_RELEASE_AGPS_DATA_CONN:
-                return "RELEASE";
-            case GPS_REQUEST_AGPS_DATA_CONN:
-                return "REQUEST";
-            default:
-                return "<Unknown>";
-        }
-    }
-
     /**
      * @return A string representing the given message ID.
      */
@@ -2654,12 +2254,6 @@
                 return "ENABLE";
             case SET_REQUEST:
                 return "SET_REQUEST";
-            case UPDATE_NETWORK_STATE:
-                return "UPDATE_NETWORK_STATE";
-            case REQUEST_SUPL_CONNECTION:
-                return "REQUEST_SUPL_CONNECTION";
-            case RELEASE_SUPL_CONNECTION:
-                return "RELEASE_SUPL_CONNECTION";
             case INJECT_NTP_TIME:
                 return "INJECT_NTP_TIME";
             case REQUEST_LOCATION:
@@ -2683,7 +2277,6 @@
         }
     }
 
-
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         StringBuilder s = new StringBuilder();
@@ -2723,8 +2316,6 @@
 
     private static native boolean native_is_supported();
 
-    private static native boolean native_is_agps_ril_supported();
-
     private static native boolean native_is_gnss_configuration_supported();
 
     private static native void native_init_once();
@@ -2770,12 +2361,6 @@
     private native String native_get_internal_state();
 
     // AGPS Support
-    private native void native_agps_data_conn_open(String apn, int apnIpType);
-
-    private native void native_agps_data_conn_closed();
-
-    private native void native_agps_data_conn_failed();
-
     private native void native_agps_ni_message(byte[] msg, int length);
 
     private native void native_set_agps_server(int type, String hostname, int port);
@@ -2783,15 +2368,12 @@
     // Network-initiated (NI) Support
     private native void native_send_ni_response(int notificationId, int userResponse);
 
-    // AGPS ril suport
+    // AGPS ril support
     private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
             int lac, int cid);
 
     private native void native_agps_set_id(int type, String setid);
 
-    private native void native_update_network_state(boolean connected, int type,
-            boolean roaming, boolean available, String extraInfo, String defaultAPN);
-
     // GNSS Configuration
     private static native boolean native_set_supl_version(int version);
 
diff --git a/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
new file mode 100644
index 0000000..b211948
--- /dev/null
+++ b/services/core/java/com/android/server/location/GnssNetworkConnectivityHandler.java
@@ -0,0 +1,631 @@
+/*
+ * Copyright (C) 2018 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.location;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkRequest;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.provider.Telephony.Carriers;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Handles network connection requests and network state change updates for AGPS data download.
+ */
+class GnssNetworkConnectivityHandler {
+    static final String TAG = "GnssNetworkConnectivityHandler";
+
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+    // for mAGpsDataConnectionState
+    private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
+    private static final int AGPS_DATA_CONNECTION_OPENING = 1;
+    private static final int AGPS_DATA_CONNECTION_OPEN = 2;
+
+    // these need to match AGnssStatusValue enum in IAGnssCallback.hal
+    /** AGPS status event values. */
+    private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
+    private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
+    private static final int GPS_AGPS_DATA_CONNECTED = 3;
+    private static final int GPS_AGPS_DATA_CONN_DONE = 4;
+    private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
+
+    // these must match the ApnIpType enum in IAGnss.hal
+    private static final int APN_INVALID = 0;
+    private static final int APN_IPV4 = 1;
+    private static final int APN_IPV6 = 2;
+    private static final int APN_IPV4V6 = 3;
+
+    // Default time limit in milliseconds for the ConnectivityManager to find a suitable
+    // network with SUPL connectivity or report an error.
+    private static final int SUPL_NETWORK_REQUEST_TIMEOUT_MILLIS = 10 * 1000;
+
+    private static final int HASH_MAP_INITIAL_CAPACITY_TO_TRACK_CONNECTED_NETWORKS = 5;
+
+    // keeps track of networks and their state as notified by the network request callbacks.
+    // Limit initial capacity to 5 as the number of connected networks will likely be small.
+    private ConcurrentHashMap<Network, NetworkAttributes> mAvailableNetworkAttributes =
+            new ConcurrentHashMap<>(HASH_MAP_INITIAL_CAPACITY_TO_TRACK_CONNECTED_NETWORKS);
+
+    private final ConnectivityManager mConnMgr;
+
+    private final Handler mHandler;
+    private final GnssNetworkListener mGnssNetworkListener;
+
+    private int mAGpsDataConnectionState;
+    private InetAddress mAGpsDataConnectionIpAddr;
+
+    private final Context mContext;
+
+    // Wakelocks
+    private static final String WAKELOCK_KEY = "GnssNetworkConnectivityHandler";
+    private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
+    private final PowerManager.WakeLock mWakeLock;
+
+    /**
+     * Network attributes needed when updating HAL about network connectivity status changes.
+     */
+    private static class NetworkAttributes {
+        NetworkCapabilities mCapabilities;
+        String mApn;
+        int mType = ConnectivityManager.TYPE_NONE;
+
+        /**
+         * Returns true if the capabilities that we pass on to HAL change between {@curCapabilities}
+         * and {@code newCapabilities}.
+         */
+        static boolean hasCapabilitiesChanged(NetworkCapabilities curCapabilities,
+                NetworkCapabilities newCapabilities) {
+            if (curCapabilities == null || newCapabilities == null) {
+                return true;
+            }
+
+            return curCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
+                    != newCapabilities.hasCapability(
+                    NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
+        }
+    }
+
+    /**
+     * Callback used to listen for data connectivity changes.
+     */
+    private ConnectivityManager.NetworkCallback mNetworkConnectivityCallback;
+
+    /**
+     * Callback used to listen for availability of a requested SUPL connection.
+     * It is kept as a separate instance from {@link #mNetworkConnectivityCallback} to be able to
+     * manage the registration/un-registration lifetimes separately.
+     */
+    private ConnectivityManager.NetworkCallback mSuplConnectivityCallback;
+
+    /**
+     * Interface to listen for network availability changes.
+     */
+    public interface GnssNetworkListener {
+        void onNetworkAvailable();
+    }
+
+    GnssNetworkConnectivityHandler(Context context,
+            GnssNetworkListener gnssNetworkListener,
+            Looper looper) {
+        mContext = context;
+        mGnssNetworkListener = gnssNetworkListener;
+
+        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+
+        mHandler = new Handler(looper);
+        mConnMgr = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+        mSuplConnectivityCallback = createSuplConnectivityCallback();
+    }
+
+    public void registerNetworkCallbacks() {
+        mAvailableNetworkAttributes.clear();
+        if (mNetworkConnectivityCallback != null) {
+            mConnMgr.unregisterNetworkCallback(mNetworkConnectivityCallback);
+        }
+
+        // register for connectivity change events.
+        NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
+        networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        networkRequestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+        networkRequestBuilder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
+        NetworkRequest networkRequest = networkRequestBuilder.build();
+        mNetworkConnectivityCallback = createNetworkConnectivityCallback();
+        mConnMgr.registerNetworkCallback(networkRequest, mNetworkConnectivityCallback);
+    }
+
+    /**
+     * @return {@code true} if there is a data network available for outgoing connections,
+     * {@code false} otherwise.
+     */
+    public boolean isDataNetworkConnected() {
+        NetworkInfo activeNetworkInfo = mConnMgr.getActiveNetworkInfo();
+        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
+    }
+
+    /**
+     * called from native code to update AGPS status
+     */
+    public void onReportAGpsStatus(int type, int status, byte[] ipaddr) {
+        switch (status) {
+            case GPS_REQUEST_AGPS_DATA_CONN:
+                if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
+                Log.v(TAG, "Received SUPL IP addr[]: " + Arrays.toString(ipaddr));
+                InetAddress connectionIpAddress = null;
+                if (ipaddr != null) {
+                    try {
+                        connectionIpAddress = InetAddress.getByAddress(ipaddr);
+                        if (DEBUG) Log.d(TAG, "IP address converted to: " + connectionIpAddress);
+                    } catch (UnknownHostException e) {
+                        Log.e(TAG, "Bad IP Address: " + ipaddr, e);
+                    }
+                }
+                requestSuplConnection(connectionIpAddress);
+                break;
+            case GPS_RELEASE_AGPS_DATA_CONN:
+                if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
+                releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
+                break;
+            case GPS_AGPS_DATA_CONNECTED:
+                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
+                break;
+            case GPS_AGPS_DATA_CONN_DONE:
+                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
+                break;
+            case GPS_AGPS_DATA_CONN_FAILED:
+                if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
+                break;
+            default:
+                if (DEBUG) Log.d(TAG, "Received Unknown AGPS status: " + status);
+        }
+    }
+
+    private ConnectivityManager.NetworkCallback createNetworkConnectivityCallback() {
+        return new ConnectivityManager.NetworkCallback() {
+            // Used to filter out network capabilities changes that we are not interested in.
+            // NOTE: Not using a ConcurrentHashMap and also not using locking around updates
+            //       and access to the map object because it is all done inside the same
+            //       handler thread invoking the callback methods.
+            private HashMap<Network, NetworkCapabilities>
+                    mAvailableNetworkCapabilities = new HashMap<>(
+                    HASH_MAP_INITIAL_CAPACITY_TO_TRACK_CONNECTED_NETWORKS);
+
+            @Override
+            public void onCapabilitiesChanged(Network network,
+                    NetworkCapabilities capabilities) {
+                // This callback is invoked for any change in the network capabilities including
+                // initial availability, and changes while still available. Only process if the
+                // capabilities that we pass on to HAL change.
+                if (!NetworkAttributes.hasCapabilitiesChanged(
+                        mAvailableNetworkCapabilities.get(network), capabilities)) {
+                    if (VERBOSE) {
+                        Log.v(TAG, "Relevant network capabilities unchanged. Capabilities: "
+                                + capabilities);
+                    }
+                    return;
+                }
+
+                mAvailableNetworkCapabilities.put(network, capabilities);
+                if (DEBUG) {
+                    Log.d(TAG, "Network connected/capabilities updated. Available networks count: "
+                            + mAvailableNetworkCapabilities.size());
+                }
+
+                mGnssNetworkListener.onNetworkAvailable();
+
+                // Always on, notify HAL so it can get data it needs
+                updateNetworkState(network, true, capabilities);
+            }
+
+            @Override
+            public void onLost(Network network) {
+                if (mAvailableNetworkCapabilities.remove(network) == null) {
+                    Log.w(TAG, "Incorrectly received network callback onLost() before"
+                            + " onCapabilitiesChanged() for network: " + network);
+                    return;
+                }
+
+                Log.i(TAG, "Network connection lost. Available networks count: "
+                        + mAvailableNetworkCapabilities.size());
+                updateNetworkState(network, false, null);
+            }
+        };
+    }
+
+    private ConnectivityManager.NetworkCallback createSuplConnectivityCallback() {
+        return new ConnectivityManager.NetworkCallback() {
+            @Override
+            public void onAvailable(Network network) {
+                if (DEBUG) Log.d(TAG, "SUPL network connection available.");
+                // Specific to a change to a SUPL enabled network becoming ready
+                suplConnectionAvailable(network);
+            }
+
+            @Override
+            public void onLost(Network network) {
+                Log.i(TAG, "SUPL network connection lost.");
+                releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
+            }
+
+            @Override
+            public void onUnavailable() {
+                Log.i(TAG, "SUPL network connection request timed out.");
+                // Could not setup the connection to the network in the specified time duration.
+                releaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
+            }
+        };
+    }
+
+    private void requestSuplConnection(InetAddress inetAddress) {
+        postEvent(() -> handleRequestSuplConnection(inetAddress));
+    }
+
+    private void suplConnectionAvailable(Network network) {
+        postEvent(() -> handleSuplConnectionAvailable(network));
+    }
+
+    private void releaseSuplConnection(int connStatus) {
+        postEvent(() -> handleReleaseSuplConnection(connStatus));
+    }
+
+    private void updateNetworkState(Network network, boolean isConnected,
+            NetworkCapabilities capabilities) {
+        postEvent(() -> handleUpdateNetworkState(network, isConnected, capabilities));
+    }
+
+    private void postEvent(Runnable event) {
+        // hold a wake lock until this message is delivered
+        // note that this assumes the message will not be removed from the queue before
+        // it is handled (otherwise the wake lock would be leaked).
+        mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
+        if (!mHandler.post(runEventAndReleaseWakeLock(event))) {
+            mWakeLock.release();
+        }
+    }
+
+    private Runnable runEventAndReleaseWakeLock(Runnable event) {
+        return () -> {
+            try {
+                event.run();
+            } finally {
+                mWakeLock.release();
+            }
+        };
+    }
+
+    private void handleUpdateNetworkState(Network network, boolean isConnected,
+            NetworkCapabilities capabilities) {
+        boolean networkAvailable = isConnected && TelephonyManager.getDefault().getDataEnabled();
+        NetworkAttributes networkAttributes = updateTrackedNetworksState(isConnected, network,
+                capabilities);
+        String apnName = networkAttributes.mApn;
+        int type = networkAttributes.mType;
+        // When isConnected is false, capabilities argument is null. So, use last received
+        // capabilities.
+        capabilities = networkAttributes.mCapabilities;
+        boolean isRoaming = !capabilities.hasTransport(
+                NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
+
+        Log.i(TAG, String.format(
+                "updateNetworkState, state=%s, connected=%s, network=%s, capabilities=%s"
+                        + ", availableNetworkCount: %d",
+                agpsDataConnStateAsString(),
+                isConnected,
+                network,
+                capabilities,
+                mAvailableNetworkAttributes.size()));
+
+        if (native_is_agps_ril_supported()) {
+            String defaultApn = getSelectedApn();
+            if (defaultApn == null) {
+                defaultApn = "dummy-apn";
+            }
+
+            native_update_network_state(
+                    isConnected,
+                    type,
+                    isRoaming,
+                    networkAvailable,
+                    apnName,
+                    defaultApn);
+        } else if (DEBUG) {
+            Log.d(TAG, "Skipped network state update because GPS HAL AGPS-RIL is not  supported");
+        }
+    }
+
+    private NetworkAttributes updateTrackedNetworksState(boolean isConnected, Network network,
+            NetworkCapabilities capabilities) {
+        if (!isConnected) {
+            // Connection lost event. So, remove it from tracked networks.
+            return mAvailableNetworkAttributes.remove(network);
+        }
+
+        NetworkAttributes networkAttributes = mAvailableNetworkAttributes.get(network);
+        if (networkAttributes != null) {
+            // Capabilities updated event for the connected network.
+            networkAttributes.mCapabilities = capabilities;
+            return networkAttributes;
+        }
+
+        // Initial capabilities event (equivalent to connection available event).
+        networkAttributes = new NetworkAttributes();
+        networkAttributes.mCapabilities = capabilities;
+
+        // TODO(b/119278134): The synchronous method ConnectivityManager.getNetworkInfo() must
+        // not be called inside the asynchronous ConnectivityManager.NetworkCallback methods.
+        NetworkInfo info = mConnMgr.getNetworkInfo(network);
+        if (info != null) {
+            networkAttributes.mApn = info.getExtraInfo();
+            networkAttributes.mType = info.getType();
+        }
+
+        // Start tracking this network for connection status updates.
+        mAvailableNetworkAttributes.put(network, networkAttributes);
+        return networkAttributes;
+    }
+
+    private void handleSuplConnectionAvailable(Network network) {
+        // TODO(b/119278134): The synchronous method ConnectivityManager.getNetworkInfo() must
+        // not be called inside the asynchronous ConnectivityManager.NetworkCallback methods.
+        NetworkInfo info = mConnMgr.getNetworkInfo(network);
+        String apnName = null;
+        if (info != null) {
+            apnName = info.getExtraInfo();
+        }
+
+        if (DEBUG) {
+            String message = String.format(
+                    "handleSuplConnectionAvailable: state=%s, suplNetwork=%s, info=%s",
+                    agpsDataConnStateAsString(),
+                    network,
+                    info);
+            Log.d(TAG, message);
+        }
+
+        if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
+            if (apnName == null) {
+                // assign a dummy value in the case of C2K as otherwise we will have a runtime
+                // exception in the following call to native_agps_data_conn_open
+                apnName = "dummy-apn";
+            }
+            int apnIpType = getApnIpType(apnName);
+            setRouting();
+            if (DEBUG) {
+                String message = String.format(
+                        "native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
+                        apnName,
+                        apnIpType);
+                Log.d(TAG, message);
+            }
+            native_agps_data_conn_open(apnName, apnIpType);
+            mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
+        }
+    }
+
+    private void handleRequestSuplConnection(InetAddress address) {
+        if (DEBUG) {
+            String message = String.format(
+                    "requestSuplConnection, state=%s, address=%s",
+                    agpsDataConnStateAsString(),
+                    address);
+            Log.d(TAG, message);
+        }
+
+        if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
+            return;
+        }
+        mAGpsDataConnectionIpAddr = address;
+        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
+
+        NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
+        requestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+        requestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
+        NetworkRequest request = requestBuilder.build();
+        mConnMgr.requestNetwork(
+                request,
+                mSuplConnectivityCallback,
+                SUPL_NETWORK_REQUEST_TIMEOUT_MILLIS);
+    }
+
+    private void handleReleaseSuplConnection(int agpsDataConnStatus) {
+        if (DEBUG) {
+            String message = String.format(
+                    "releaseSuplConnection, state=%s, status=%s",
+                    agpsDataConnStateAsString(),
+                    agpsDataConnStatusAsString(agpsDataConnStatus));
+            Log.d(TAG, message);
+        }
+
+        if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_CLOSED) {
+            return;
+        }
+        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
+
+        mConnMgr.unregisterNetworkCallback(mSuplConnectivityCallback);
+        switch (agpsDataConnStatus) {
+            case GPS_AGPS_DATA_CONN_FAILED:
+                native_agps_data_conn_failed();
+                break;
+            case GPS_RELEASE_AGPS_DATA_CONN:
+                native_agps_data_conn_closed();
+                break;
+            default:
+                Log.e(TAG, "Invalid status to release SUPL connection: " + agpsDataConnStatus);
+        }
+    }
+
+    private void setRouting() {
+        if (mAGpsDataConnectionIpAddr == null) {
+            return;
+        }
+
+        // TODO(25876485): replace the use of this deprecated API
+        boolean result = mConnMgr.requestRouteToHostAddress(
+                ConnectivityManager.TYPE_MOBILE_SUPL,
+                mAGpsDataConnectionIpAddr);
+
+        if (!result) {
+            Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr);
+        } else if (DEBUG) {
+            Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr);
+        }
+    }
+
+    /**
+     * Ensures the calling function is running in the thread associated with {@link #mHandler}.
+     */
+    private void ensureInHandlerThread() {
+        if (mHandler != null && Looper.myLooper() == mHandler.getLooper()) {
+            return;
+        }
+        throw new IllegalStateException("This method must run on the Handler thread.");
+    }
+
+    /**
+     * @return A string representing the current state stored in {@link #mAGpsDataConnectionState}.
+     */
+    private String agpsDataConnStateAsString() {
+        switch (mAGpsDataConnectionState) {
+            case AGPS_DATA_CONNECTION_CLOSED:
+                return "CLOSED";
+            case AGPS_DATA_CONNECTION_OPEN:
+                return "OPEN";
+            case AGPS_DATA_CONNECTION_OPENING:
+                return "OPENING";
+            default:
+                return "<Unknown>";
+        }
+    }
+
+    /**
+     * @return A string representing the given GPS_AGPS_DATA status.
+     */
+    private String agpsDataConnStatusAsString(int agpsDataConnStatus) {
+        switch (agpsDataConnStatus) {
+            case GPS_AGPS_DATA_CONNECTED:
+                return "CONNECTED";
+            case GPS_AGPS_DATA_CONN_DONE:
+                return "DONE";
+            case GPS_AGPS_DATA_CONN_FAILED:
+                return "FAILED";
+            case GPS_RELEASE_AGPS_DATA_CONN:
+                return "RELEASE";
+            case GPS_REQUEST_AGPS_DATA_CONN:
+                return "REQUEST";
+            default:
+                return "<Unknown>";
+        }
+    }
+
+    private int getApnIpType(String apn) {
+        ensureInHandlerThread();
+        if (apn == null) {
+            return APN_INVALID;
+        }
+        TelephonyManager phone = (TelephonyManager)
+                mContext.getSystemService(Context.TELEPHONY_SERVICE);
+        // Carrier configuration may override framework roaming state, we need to use the actual
+        // modem roaming state instead of the framework roaming state.
+        boolean isDataRoamingFromRegistration = phone.getServiceState()
+                .getDataRoamingFromRegistration();
+        String projection = isDataRoamingFromRegistration ? Carriers.ROAMING_PROTOCOL :
+                Carriers.PROTOCOL;
+        String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
+        try (Cursor cursor = mContext.getContentResolver().query(
+                Carriers.CONTENT_URI,
+                new String[]{projection},
+                selection,
+                null,
+                Carriers.DEFAULT_SORT_ORDER)) {
+            if (null != cursor && cursor.moveToFirst()) {
+                return translateToApnIpType(cursor.getString(0), apn);
+            } else {
+                Log.e(TAG, "No entry found in query for APN: " + apn);
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Error encountered on APN query for: " + apn, e);
+        }
+
+        return APN_INVALID;
+    }
+
+    private int translateToApnIpType(String ipProtocol, String apn) {
+        if ("IP".equals(ipProtocol)) {
+            return APN_IPV4;
+        }
+        if ("IPV6".equals(ipProtocol)) {
+            return APN_IPV6;
+        }
+        if ("IPV4V6".equals(ipProtocol)) {
+            return APN_IPV4V6;
+        }
+
+        // we hit the default case so the ipProtocol is not recognized
+        String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
+        Log.e(TAG, message);
+        return APN_INVALID;
+    }
+
+    private String getSelectedApn() {
+        Uri uri = Uri.parse("content://telephony/carriers/preferapn");
+        try (Cursor cursor = mContext.getContentResolver().query(
+                uri,
+                new String[]{"apn"},
+                null /* selection */,
+                null /* selectionArgs */,
+                Carriers.DEFAULT_SORT_ORDER)) {
+            if (cursor != null && cursor.moveToFirst()) {
+                return cursor.getString(0);
+            } else {
+                Log.e(TAG, "No APN found to select.");
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Error encountered on selecting the APN.", e);
+        }
+
+        return null;
+    }
+
+    // AGPS support
+    private native void native_agps_data_conn_open(String apn, int apnIpType);
+
+    private native void native_agps_data_conn_closed();
+
+    private native void native_agps_data_conn_failed();
+
+    // AGPS ril support
+    private static native boolean native_is_agps_ril_supported();
+
+    private native void native_update_network_state(boolean connected, int type,
+            boolean roaming, boolean available, String extraInfo, String defaultAPN);
+}
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index 16eae62..bb86b48 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -16,26 +16,28 @@
 
 package com.android.server.location;
 
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.PrintWriter;
-
+import android.annotation.Nullable;
 import android.content.Context;
 import android.location.LocationProvider;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.WorkSource;
 import android.util.Log;
 
-import com.android.internal.location.ProviderProperties;
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.location.ILocationProvider;
+import com.android.internal.location.ProviderProperties;
 import com.android.internal.location.ProviderRequest;
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.TransferPipe;
 import com.android.server.LocationManagerService;
 import com.android.server.ServiceWatcher;
 
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+
 /**
  * Proxy for ILocationProvider implementations.
  */
@@ -43,25 +45,36 @@
     private static final String TAG = "LocationProviderProxy";
     private static final boolean D = LocationManagerService.D;
 
-    private final Context mContext;
-    private final String mName;
     private final ServiceWatcher mServiceWatcher;
 
-    private Object mLock = new Object();
+    private final String mName;
 
-    // cached values set by the location manager, synchronized on mLock
-    private ProviderProperties mProperties;
-    private boolean mEnabled = false;
-    private ProviderRequest mRequest = null;
-    private WorkSource mWorksource = new WorkSource();
+    // used to ensure that updates to mRequest and mWorkSource are atomic
+    private final Object mRequestLock = new Object();
 
+
+    private volatile boolean mEnabled = false;
+    @Nullable
+    private volatile ProviderProperties mProperties;
+
+    @GuardedBy("mRequestLock")
+    @Nullable
+    private ProviderRequest mRequest;
+    @GuardedBy("mRequestLock")
+    private WorkSource mWorkSource;
+
+    /**
+     * Creates a new LocationProviderProxy and immediately begins binding to the best applicable
+     * service.
+     */
+    @Nullable
     public static LocationProviderProxy createAndBind(
             Context context, String name, String action,
             int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId, Handler handler) {
-        LocationProviderProxy proxy = new LocationProviderProxy(context, name, action,
-                overlaySwitchResId, defaultServicePackageNameResId, initialPackageNamesResId,
-                handler);
+            int initialPackageNamesResId) {
+        LocationProviderProxy proxy = new LocationProviderProxy(context, name,
+                action, overlaySwitchResId, defaultServicePackageNameResId,
+                initialPackageNamesResId);
         if (proxy.bind()) {
             return proxy;
         } else {
@@ -69,78 +82,66 @@
         }
     }
 
-    private LocationProviderProxy(Context context, String name, String action,
-            int overlaySwitchResId, int defaultServicePackageNameResId,
-            int initialPackageNamesResId, Handler handler) {
-        mContext = context;
-        mName = name;
-        mServiceWatcher = new ServiceWatcher(mContext, TAG + "-" + name, action, overlaySwitchResId,
+    private LocationProviderProxy(Context context, String name,
+            String action, int overlaySwitchResId, int defaultServicePackageNameResId,
+            int initialPackageNamesResId) {
+
+        mServiceWatcher = new ServiceWatcher(context, TAG, action, overlaySwitchResId,
                 defaultServicePackageNameResId, initialPackageNamesResId,
-                mNewServiceWork, handler);
+                BackgroundThread.getHandler()) {
+            @Override
+            protected void onBind() {
+                runOnBinder(LocationProviderProxy.this::initializeService);
+            }
+        };
+        mName = name;
+
+        mProperties = null;
+        mRequest = null;
+        mWorkSource = new WorkSource();
     }
 
-    private boolean bind () {
+    private boolean bind() {
         return mServiceWatcher.start();
     }
 
-    public String getConnectedPackageName() {
-        return mServiceWatcher.getBestPackageName();
+    private void initializeService(IBinder binder) {
+        ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+        if (D) Log.d(TAG, "applying state to connected service");
+
+        ProviderProperties[] properties = new ProviderProperties[1];
+        ProviderRequest request;
+        WorkSource source;
+        synchronized (mRequestLock) {
+            request = mRequest;
+            source = mWorkSource;
+        }
+
+        try {
+            // load properties from provider
+            properties[0] = service.getProperties();
+            if (properties[0] == null) {
+                Log.e(TAG, mServiceWatcher.getCurrentPackageName()
+                        + " has invalid location provider properties");
+            }
+
+            // apply current state to new service
+            if (mEnabled) {
+                service.enable();
+                if (request != null) {
+                    service.setRequest(request, source);
+                }
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, e);
+        }
+
+        mProperties = properties[0];
     }
 
-    /**
-     * Work to apply current state to a newly connected provider.
-     * Remember we can switch the service that implements a providers
-     * at run-time, so need to apply current state.
-     */
-    private Runnable mNewServiceWork = new Runnable() {
-        @Override
-        public void run() {
-            if (D) Log.d(TAG, "applying state to connected service");
-
-            boolean enabled;
-            final ProviderProperties[] properties = new ProviderProperties[1];
-            ProviderRequest request;
-            WorkSource source;
-            synchronized (mLock) {
-                enabled = mEnabled;
-                request = mRequest;
-                source = mWorksource;
-            }
-
-
-            mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-                @Override
-                public void run(IBinder binder) {
-                    ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
-                    try {
-                        // load properties from provider
-                        properties[0] = service.getProperties();
-                        if (properties[0] == null) {
-                            Log.e(TAG, mServiceWatcher.getBestPackageName() +
-                                    " has invalid location provider properties");
-                        }
-
-                        // apply current state to new service
-                        if (enabled) {
-                            service.enable();
-                            if (request != null) {
-                                service.setRequest(request, source);
-                            }
-                        }
-                    } catch (RemoteException e) {
-                        Log.w(TAG, e);
-                    } catch (Exception e) {
-                        // never let remote service crash system server
-                        Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
-                    }
-                }
-            });
-
-            synchronized (mLock) {
-                mProperties = properties[0];
-            }
-        }
-    };
+    public String getConnectedPackageName() {
+        return mServiceWatcher.getCurrentPackageName();
+    }
 
     @Override
     public String getName() {
@@ -149,78 +150,52 @@
 
     @Override
     public ProviderProperties getProperties() {
-        synchronized (mLock) {
-            return mProperties;
-        }
+        return mProperties;
     }
 
     @Override
     public void enable() {
-        synchronized (mLock) {
-            mEnabled = true;
-        }
-        mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-            @Override
-            public void run(IBinder binder) {
-                ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
-                try {
-                    service.enable();
-                } catch (RemoteException e) {
-                    Log.w(TAG, e);
-                } catch (Exception e) {
-                    // never let remote service crash system server
-                    Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
-                }
+        mEnabled = true;
+        mServiceWatcher.runOnBinder(binder -> {
+            ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+            try {
+                service.enable();
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
             }
         });
     }
 
     @Override
     public void disable() {
-        synchronized (mLock) {
-            mEnabled = false;
-        }
-        mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-            @Override
-            public void run(IBinder binder) {
-                ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
-                try {
-                    service.disable();
-                } catch (RemoteException e) {
-                    Log.w(TAG, e);
-                } catch (Exception e) {
-                    // never let remote service crash system server
-                    Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
-                }
+        mEnabled = false;
+        mServiceWatcher.runOnBinder(binder -> {
+            ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+            try {
+                service.disable();
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
             }
         });
     }
 
     @Override
     public boolean isEnabled() {
-        synchronized (mLock) {
-            return mEnabled;
-        }
+        return mEnabled;
     }
 
     @Override
     public void setRequest(ProviderRequest request, WorkSource source) {
-        synchronized (mLock) {
+        synchronized (mRequestLock) {
             mRequest = request;
-            mWorksource = source;
+            mWorkSource = source;
         }
-        mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-            @Override
-            public void run(IBinder binder) {
-                ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
-                try {
-                    service.setRequest(request, source);
-                } catch (RemoteException e) {
-                    Log.w(TAG, e);
-                } catch (Exception e) {
-                    // never let remote service crash system server
-                    Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
-                }
+        mServiceWatcher.runOnBinder(binder -> {
+            ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+            try {
+                service.setRequest(request, source);
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
             }
         });
     }
@@ -229,39 +204,28 @@
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.append("REMOTE SERVICE");
         pw.append(" name=").append(mName);
-        pw.append(" pkg=").append(mServiceWatcher.getBestPackageName());
-        pw.append(" version=").append("" + mServiceWatcher.getBestVersion());
+        pw.append(" pkg=").append(mServiceWatcher.getCurrentPackageName());
+        pw.append(" version=").append(Integer.toString(mServiceWatcher.getCurrentPackageVersion()));
         pw.append('\n');
-        if (!mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-            @Override
-            public void run(IBinder binder) {
-                ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
-                try {
-                    TransferPipe.dumpAsync(service.asBinder(), fd, args);
-                } catch (IOException | RemoteException e) {
-                    pw.println("Failed to dump location provider: " + e);
-                }
+        mServiceWatcher.runOnBinder(binder -> {
+            ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+            try {
+                TransferPipe.dumpAsync(service.asBinder(), fd, args);
+            } catch (IOException | RemoteException e) {
+                pw.println("Failed to dump location provider: " + e);
             }
-        })) {
-            pw.println("service down (null)");
-        }
+        });
     }
 
     @Override
     public int getStatus(Bundle extras) {
-        final int[] result = new int[] {LocationProvider.TEMPORARILY_UNAVAILABLE};
-        mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-            @Override
-            public void run(IBinder binder) {
-                ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
-                try {
-                    result[0] = service.getStatus(extras);
-                } catch (RemoteException e) {
-                    Log.w(TAG, e);
-                } catch (Exception e) {
-                    // never let remote service crash system server
-                    Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
-                }
+        int[] result = new int[]{LocationProvider.TEMPORARILY_UNAVAILABLE};
+        mServiceWatcher.runOnBinder(binder -> {
+            ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+            try {
+                result[0] = service.getStatus(extras);
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
             }
         });
         return result[0];
@@ -269,19 +233,13 @@
 
     @Override
     public long getStatusUpdateTime() {
-        final long[] result = new long[] {0L};
-        mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-            @Override
-            public void run(IBinder binder) {
-                ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
-                try {
-                    result[0] = service.getStatusUpdateTime();
-                } catch (RemoteException e) {
-                    Log.w(TAG, e);
-                } catch (Exception e) {
-                    // never let remote service crash system server
-                    Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
-                }
+        long[] result = new long[]{0L};
+        mServiceWatcher.runOnBinder(binder -> {
+            ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+            try {
+                result[0] = service.getStatusUpdateTime();
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
             }
         });
         return result[0];
@@ -289,21 +247,15 @@
 
     @Override
     public boolean sendExtraCommand(String command, Bundle extras) {
-        final boolean[] result = new boolean[] {false};
-        mServiceWatcher.runOnBinder(new ServiceWatcher.BinderRunner() {
-            @Override
-            public void run(IBinder binder) {
-                ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
-                try {
-                    result[0] = service.sendExtraCommand(command, extras);
-                } catch (RemoteException e) {
-                    Log.w(TAG, e);
-                } catch (Exception e) {
-                    // never let remote service crash system server
-                    Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e);
-                }
+        boolean[] result = new boolean[]{false};
+        mServiceWatcher.runOnBinder(binder -> {
+            ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+            try {
+                result[0] = service.sendExtraCommand(command, extras);
+            } catch (RemoteException e) {
+                Log.w(TAG, e);
             }
         });
         return result[0];
     }
- }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 924b075..6195ed9 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -870,6 +870,7 @@
                     }
                     if (expanded && userAction) {
                         r.recordExpanded();
+                        reportUserInteraction(r);
                     }
                     EventLogTags.writeNotificationExpansion(key,
                             userAction ? 1 : 0, expanded ? 1 : 0,
@@ -885,6 +886,9 @@
                 NotificationRecord r = mNotificationsByKey.get(key);
                 if (r != null) {
                     r.recordDirectReplied();
+                    mMetricsLogger.write(r.getLogMaker()
+                            .setCategory(MetricsEvent.NOTIFICATION_DIRECT_REPLY_ACTION)
+                            .setType(MetricsEvent.TYPE_ACTION));
                     reportUserInteraction(r);
                 }
             }
@@ -1160,6 +1164,7 @@
                     mConditionProviders.onUserSwitched(userId);
                     mListeners.onUserSwitched(userId);
                     mZenModeHelper.onUserSwitched(userId);
+                    mPreferencesHelper.onUserSwitched(userId);
                 }
                 // assistant is the only thing that cares about managed profiles specifically
                 mAssistants.onUserSwitched(userId);
@@ -1188,6 +1193,7 @@
                     mConditionProviders.onUserUnlocked(userId);
                     mListeners.onUserUnlocked(userId);
                     mZenModeHelper.onUserUnlocked(userId);
+                    mPreferencesHelper.onUserUnlocked(userId);
                 }
             }
         }
@@ -1982,7 +1988,7 @@
     }
 
     /**
-     * Report to usage stats that the notification was clicked.
+     * Report to usage stats that the user interacted with the notification.
      * @param r notification record
      */
     protected void reportUserInteraction(NotificationRecord r) {
@@ -2525,6 +2531,19 @@
         }
 
         @Override
+        public int getAppsBypassingDndCount(int userId) {
+            checkCallerIsSystem();
+            return mPreferencesHelper.getAppsBypassingDndCount(userId);
+        }
+
+        @Override
+        public ParceledListSlice<NotificationChannel> getNotificationChannelsBypassingDnd(
+                String pkg, int userId) {
+            checkCallerIsSystem();
+            return mPreferencesHelper.getNotificationChannelsBypassingDnd(pkg, userId);
+        }
+
+        @Override
         public boolean areChannelsBypassingDnd() {
             return mPreferencesHelper.areChannelsBypassingDnd();
         }
@@ -3610,7 +3629,7 @@
                         NotificationRecord r = mNotificationsByKey.get(adjustment.getKey());
                         if (r != null && mAssistants.isSameUser(token, r.getUserId())) {
                             applyAdjustment(r, adjustment);
-                            r.applyAdjustments();
+                            r.applyImportanceFromAdjustments();
                             if (r.getImportance() == IMPORTANCE_NONE) {
                                 cancelNotificationsFromListener(token, new String[]{r.getKey()});
                             } else {
@@ -4521,6 +4540,7 @@
                             mDuration)
                     .addTaggedData(MetricsEvent.NOTIFICATION_SNOOZED_CRITERIA,
                             mSnoozeCriterionId == null ? 0 : 1));
+            reportUserInteraction(r);
             boolean wasPosted = removeFromNotificationListsLocked(r);
             cancelNotificationLocked(r, false, REASON_SNOOZED, wasPosted, null);
             updateLightsLocked();
@@ -4756,6 +4776,10 @@
                     applyZenModeLocked(r);
                     mRankingHelper.sort(mNotificationList);
 
+                    if (!r.isHidden()) {
+                        buzzBeepBlinkLocked(r);
+                    }
+
                     if (notification.getSmallIcon() != null) {
                         StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
                         mListeners.notifyPostedLocked(r, old);
@@ -4788,9 +4812,6 @@
                                 + n.getPackageName());
                     }
 
-                    if (!r.isHidden()) {
-                        buzzBeepBlinkLocked(r);
-                    }
                     maybeRecordInterruptionLocked(r);
                 } finally {
                     int N = mEnqueuedNotifications.size();
@@ -5157,6 +5178,7 @@
                     .setSubtype((buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0)));
             EventLogTags.writeNotificationAlert(key, buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
         }
+        record.setAudiblyAlerted(buzz || beep);
     }
 
     @GuardedBy("mNotificationLock")
@@ -5527,7 +5549,7 @@
             ArrayList<ArrayList<SnoozeCriterion>> snoozeCriteriaBefore = new ArrayList<>(N);
             ArrayList<Integer> userSentimentBefore = new ArrayList<>(N);
             ArrayList<Integer> suppressVisuallyBefore = new ArrayList<>(N);
-            ArrayList<ArrayList<Notification.Action>> smartActionsBefore = new ArrayList<>(N);
+            ArrayList<ArrayList<Notification.Action>> systemSmartActionsBefore = new ArrayList<>(N);
             ArrayList<ArrayList<CharSequence>> smartRepliesBefore = new ArrayList<>(N);
             for (int i = 0; i < N; i++) {
                 final NotificationRecord r = mNotificationList.get(i);
@@ -5540,7 +5562,7 @@
                 snoozeCriteriaBefore.add(r.getSnoozeCriteria());
                 userSentimentBefore.add(r.getUserSentiment());
                 suppressVisuallyBefore.add(r.getSuppressedVisualEffects());
-                smartActionsBefore.add(r.getSmartActions());
+                systemSmartActionsBefore.add(r.getSystemGeneratedSmartActions());
                 smartRepliesBefore.add(r.getSmartReplies());
                 mRankingHelper.extractSignals(r);
             }
@@ -5557,7 +5579,8 @@
                         || !Objects.equals(userSentimentBefore.get(i), r.getUserSentiment())
                         || !Objects.equals(suppressVisuallyBefore.get(i),
                         r.getSuppressedVisualEffects())
-                        || !Objects.equals(smartActionsBefore.get(i), r.getSmartActions())
+                        || !Objects.equals(systemSmartActionsBefore.get(i),
+                                r.getSystemGeneratedSmartActions())
                         || !Objects.equals(smartRepliesBefore.get(i), r.getSmartReplies())) {
                     mHandler.scheduleSendRankingUpdate();
                     return;
@@ -6559,8 +6582,10 @@
         Bundle showBadge = new Bundle();
         Bundle userSentiment = new Bundle();
         Bundle hidden = new Bundle();
-        Bundle smartActions = new Bundle();
+        Bundle systemGeneratedSmartActions = new Bundle();
         Bundle smartReplies = new Bundle();
+        Bundle audiblyAlerted = new Bundle();
+        Bundle noisy = new Bundle();
         for (int i = 0; i < N; i++) {
             NotificationRecord record = mNotificationList.get(i);
             if (!isVisibleToListener(record.sbn, info)) {
@@ -6588,8 +6613,11 @@
             showBadge.putBoolean(key, record.canShowBadge());
             userSentiment.putInt(key, record.getUserSentiment());
             hidden.putBoolean(key, record.isHidden());
-            smartActions.putParcelableArrayList(key, record.getSmartActions());
+            systemGeneratedSmartActions.putParcelableArrayList(key,
+                    record.getSystemGeneratedSmartActions());
             smartReplies.putCharSequenceArrayList(key, record.getSmartReplies());
+            audiblyAlerted.putBoolean(key, record.getAudiblyAlerted());
+            noisy.putBoolean(key, record.getSound() != null || record.getVibration() != null);
         }
         final int M = keys.size();
         String[] keysAr = keys.toArray(new String[M]);
@@ -6601,7 +6629,7 @@
         return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
                 suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys,
                 channels, overridePeople, snoozeCriteria, showBadge, userSentiment, hidden,
-                smartActions, smartReplies);
+                systemGeneratedSmartActions, smartReplies, audiblyAlerted, noisy);
     }
 
     boolean hasCompanionDevice(ManagedServiceInfo info) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index e9f2718..1a9257c 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -163,13 +163,18 @@
     private Light mLight;
     private String mGroupLogTag;
     private String mChannelIdLogTag;
-    private ArrayList<Notification.Action> mSmartActions;
+    /**
+     * This list contains system generated smart actions from NAS, app-generated smart actions are
+     * stored in Notification.actions marked as SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION.
+     */
+    private ArrayList<Notification.Action> mSystemGeneratedSmartActions;
     private ArrayList<CharSequence> mSmartReplies;
 
     private final List<Adjustment> mAdjustments;
     private final NotificationStats mStats;
     private int mUserSentiment;
     private boolean mIsInterruptive;
+    private boolean mAudiblyAlerted;
     private boolean mTextChanged;
     private boolean mRecordedInterruption;
     private int mNumberOfSmartRepliesAdded;
@@ -652,10 +657,11 @@
                     }
                 }
                 if (signals.containsKey(Adjustment.KEY_SMART_ACTIONS)) {
-                    setSmartActions(signals.getParcelableArrayList(Adjustment.KEY_SMART_ACTIONS));
+                    setSystemGeneratedSmartActions(
+                            signals.getParcelableArrayList(Adjustment.KEY_SMART_ACTIONS));
                     MetricsLogger.action(getAdjustmentLogMaker()
                             .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_SMART_ACTIONS,
-                                    getSmartActions().size()));
+                                    getSystemGeneratedSmartActions().size()));
                 }
                 if (signals.containsKey(Adjustment.KEY_SMART_REPLIES)) {
                     setSmartReplies(signals.getCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES));
@@ -663,6 +669,18 @@
                             .addTaggedData(MetricsEvent.ADJUSTMENT_KEY_SMART_REPLIES,
                                     getSmartReplies().size()));
                 }
+            }
+            applyImportanceFromAdjustments();
+        }
+    }
+
+    /**
+     * Update importance from the adjustment.
+     */
+    public void applyImportanceFromAdjustments() {
+        synchronized (mAdjustments) {
+            for (Adjustment adjustment : mAdjustments) {
+                Bundle signals = adjustment.getSignals();
                 if (signals.containsKey(Adjustment.KEY_IMPORTANCE)) {
                     int importance = signals.getInt(Adjustment.KEY_IMPORTANCE);
                     importance = Math.max(IMPORTANCE_UNSPECIFIED, importance);
@@ -1023,6 +1041,10 @@
         }
     }
 
+    public void setAudiblyAlerted(boolean audiblyAlerted) {
+        mAudiblyAlerted = audiblyAlerted;
+    }
+
     public void setTextChanged(boolean textChanged) {
         mTextChanged = textChanged;
     }
@@ -1039,6 +1061,11 @@
         return mIsInterruptive;
     }
 
+    /** Returns true if the notification audibly alerted the user. */
+    public boolean getAudiblyAlerted() {
+        return mAudiblyAlerted;
+    }
+
     protected void setPeopleOverride(ArrayList<String> people) {
         mPeopleOverride = people;
     }
@@ -1110,12 +1137,13 @@
         mHasSeenSmartReplies = hasSeenSmartReplies;
     }
 
-    public void setSmartActions(ArrayList<Notification.Action> smartActions) {
-        mSmartActions = smartActions;
+    public void setSystemGeneratedSmartActions(
+            ArrayList<Notification.Action> systemGeneratedSmartActions) {
+        mSystemGeneratedSmartActions = systemGeneratedSmartActions;
     }
 
-    public ArrayList<Notification.Action> getSmartActions() {
-        return mSmartActions;
+    public ArrayList<Notification.Action> getSystemGeneratedSmartActions() {
+        return mSystemGeneratedSmartActions;
     }
 
     public void setSmartReplies(ArrayList<CharSequence> smartReplies) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 8fce5e3..fd65ebe 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -111,7 +111,6 @@
     // pkg => PackagePreferences
     private final ArrayMap<String, PackagePreferences> mRestoredWithoutUids = new ArrayMap<>();
 
-
     private final Context mContext;
     private final PackageManager mPm;
     private final RankingHandler mRankingHandler;
@@ -120,7 +119,6 @@
     private SparseBooleanArray mBadgingEnabled;
     private boolean mAreChannelsBypassingDnd;
 
-
     public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
             ZenModeHelper zenHelper) {
         mContext = context;
@@ -129,11 +127,7 @@
         mPm = pm;
 
         updateBadgingEnabled();
-
-        mAreChannelsBypassingDnd = (mZenModeHelper.getNotificationPolicy().state &
-                NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND) == 1;
-        updateChannelsBypassingDnd();
-
+        syncChannelsBypassingDnd(mContext.getUserId());
     }
 
     public void readXml(XmlPullParser parser, boolean forRestore)
@@ -525,6 +519,7 @@
                 // but the system can
                 if (group.isBlocked() != oldGroup.isBlocked()) {
                     group.lockFields(NotificationChannelGroup.USER_LOCKED_BLOCKED_STATE);
+                    updateChannelsBypassingDnd(mContext.getUserId());
                 }
                 if (group.canOverlayApps() != oldGroup.canOverlayApps()) {
                     group.lockFields(NotificationChannelGroup.USER_LOCKED_ALLOW_APP_OVERLAY);
@@ -571,6 +566,7 @@
 
             // Apps are allowed to downgrade channel importance if the user has not changed any
             // fields on this channel yet.
+            final int previousExistingImportance = existing.getImportance();
             if (existing.getUserLockedFields() == 0 &&
                     channel.getImportance() < existing.getImportance()) {
                 existing.setImportance(channel.getImportance());
@@ -582,8 +578,9 @@
                 boolean bypassDnd = channel.canBypassDnd();
                 existing.setBypassDnd(bypassDnd);
 
-                if (bypassDnd != mAreChannelsBypassingDnd) {
-                    updateChannelsBypassingDnd();
+                if (bypassDnd != mAreChannelsBypassingDnd
+                        || previousExistingImportance != existing.getImportance()) {
+                    updateChannelsBypassingDnd(mContext.getUserId());
                 }
             }
 
@@ -613,7 +610,7 @@
 
         r.channels.put(channel.getId(), channel);
         if (channel.canBypassDnd() != mAreChannelsBypassingDnd) {
-            updateChannelsBypassingDnd();
+            updateChannelsBypassingDnd(mContext.getUserId());
         }
         MetricsLogger.action(getChannelLog(channel, pkg).setType(
                 com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
@@ -663,8 +660,9 @@
             MetricsLogger.action(getChannelLog(updatedChannel, pkg));
         }
 
-        if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd) {
-            updateChannelsBypassingDnd();
+        if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd
+                || channel.getImportance() != updatedChannel.getImportance()) {
+            updateChannelsBypassingDnd(mContext.getUserId());
         }
         updateConfig();
     }
@@ -701,7 +699,7 @@
             MetricsLogger.action(lm);
 
             if (mAreChannelsBypassingDnd && channel.canBypassDnd()) {
-                updateChannelsBypassingDnd();
+                updateChannelsBypassingDnd(mContext.getUserId());
             }
         }
     }
@@ -859,6 +857,27 @@
     }
 
     /**
+     * Gets all notification channels associated with the given pkg and userId that can bypass dnd
+     */
+    public ParceledListSlice<NotificationChannel> getNotificationChannelsBypassingDnd(String pkg,
+            int userId) {
+        List<NotificationChannel> channels = new ArrayList<>();
+        synchronized (mPackagePreferences) {
+            final PackagePreferences r = mPackagePreferences.get(
+                    packagePreferencesKey(pkg, userId));
+            // notifications from this package aren't blocked
+            if (r != null && r.importance != IMPORTANCE_NONE) {
+                for (NotificationChannel channel : r.channels.values()) {
+                    if (channelIsLive(r, channel) && channel.canBypassDnd()) {
+                        channels.add(channel);
+                    }
+                }
+            }
+        }
+        return new ParceledListSlice<>(channels);
+    }
+
+    /**
      * True for pre-O apps that only have the default channel, or pre O apps that have no
      * channels yet. This method will create the default channel for pre-O apps that don't have it.
      * Should never be true for O+ targeting apps, but that's enforced on boot/when an app
@@ -922,18 +941,62 @@
         return count;
     }
 
-    public void updateChannelsBypassingDnd() {
+    /**
+     * Returns the number of apps that have at least one notification channel that can bypass DND
+     * for given particular user
+     */
+    public int getAppsBypassingDndCount(int userId) {
+        int count = 0;
         synchronized (mPackagePreferences) {
-            final int numPackagePreferencess = mPackagePreferences.size();
-            for (int PackagePreferencesIndex = 0; PackagePreferencesIndex < numPackagePreferencess;
-                    PackagePreferencesIndex++) {
-                final PackagePreferences r = mPackagePreferences.valueAt(PackagePreferencesIndex);
-                final int numChannels = r.channels.size();
+            final int numPackagePreferences = mPackagePreferences.size();
+            for (int i = 0; i < numPackagePreferences; i++) {
+                final PackagePreferences r = mPackagePreferences.valueAt(i);
+                // Package isn't associated with this userId or notifications from this package are
+                // blocked
+                if (userId != UserHandle.getUserId(r.uid) || r.importance == IMPORTANCE_NONE) {
+                    continue;
+                }
 
-                for (int channelIndex = 0; channelIndex < numChannels; channelIndex++) {
-                    NotificationChannel channel = r.channels.valueAt(channelIndex);
-                    if (!channel.isDeleted() && channel.canBypassDnd()) {
-                        // If any channel bypasses DND, synchronize state and return early.
+                for (NotificationChannel channel : r.channels.values()) {
+                    if (channelIsLive(r, channel) && channel.canBypassDnd()) {
+                        count++;
+                        break;
+                    }
+                }
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Syncs {@link #mAreChannelsBypassingDnd} with the user's notification policy before
+     * updating
+     * @param userId
+     */
+    private void syncChannelsBypassingDnd(int userId) {
+        mAreChannelsBypassingDnd = (mZenModeHelper.getNotificationPolicy().state
+                & NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND) == 1;
+        updateChannelsBypassingDnd(userId);
+    }
+
+    /**
+     * Updates the user's NotificationPolicy based on whether the given userId
+     * has channels bypassing DND
+     * @param userId
+     */
+    private void updateChannelsBypassingDnd(int userId) {
+        synchronized (mPackagePreferences) {
+            final int numPackagePreferences = mPackagePreferences.size();
+            for (int i = 0; i < numPackagePreferences; i++) {
+                final PackagePreferences r = mPackagePreferences.valueAt(i);
+                // Package isn't associated with this userId or notifications from this package are
+                // blocked
+                if (userId != UserHandle.getUserId(r.uid) || r.importance == IMPORTANCE_NONE) {
+                    continue;
+                }
+
+                for (NotificationChannel channel : r.channels.values()) {
+                    if (channelIsLive(r, channel) && channel.canBypassDnd()) {
                         if (!mAreChannelsBypassingDnd) {
                             mAreChannelsBypassingDnd = true;
                             updateZenPolicy(true);
@@ -943,7 +1006,6 @@
                 }
             }
         }
-
         // If no channels bypass DND, update the zen policy once to disable DND bypass.
         if (mAreChannelsBypassingDnd) {
             mAreChannelsBypassingDnd = false;
@@ -951,6 +1013,22 @@
         }
     }
 
+    private boolean channelIsLive(PackagePreferences pkgPref, NotificationChannel channel) {
+        // Channel is in a group that's blocked
+        if (!TextUtils.isEmpty(channel.getGroup())) {
+            if (pkgPref.groups.get(channel.getGroup()).isBlocked()) {
+                return false;
+            }
+        }
+
+        // Channel is deleted or is blocked
+        if (channel.isDeleted() || channel.getImportance() == IMPORTANCE_NONE) {
+            return false;
+        }
+
+        return true;
+    }
+
     public void updateZenPolicy(boolean areChannelsBypassingDnd) {
         NotificationManager.Policy policy = mZenModeHelper.getNotificationPolicy();
         mZenModeHelper.setNotificationPolicy(new NotificationManager.Policy(
@@ -1329,6 +1407,20 @@
         return packageChannels;
     }
 
+    /**
+     * Called when user switches
+     */
+    public void onUserSwitched(int userId) {
+        syncChannelsBypassingDnd(userId);
+    }
+
+    /**
+     * Called when user is unlocked
+     */
+    public void onUserUnlocked(int userId) {
+        syncChannelsBypassingDnd(userId);
+    }
+
     public void onUserRemoved(int userId) {
         synchronized (mPackagePreferences) {
             int N = mPackagePreferences.size();
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index 807c343..731e6bc 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -16,36 +16,46 @@
 
 package com.android.server.om;
 
+import static android.content.Context.IDMAP_SERVICE;
+import static android.text.format.DateUtils.SECOND_IN_MILLIS;
+
 import static com.android.server.om.OverlayManagerService.DEBUG;
 import static com.android.server.om.OverlayManagerService.TAG;
 
 import android.annotation.NonNull;
 import android.content.om.OverlayInfo;
 import android.content.pm.PackageInfo;
+import android.os.IBinder;
+import android.os.IIdmap2;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.util.Slog;
 
-import com.android.server.pm.Installer.InstallerException;
+import com.android.internal.os.BackgroundThread;
 import com.android.server.pm.Installer;
 
-import java.io.DataInputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
 
 /**
  * Handle the creation and deletion of idmap files.
  *
  * The actual work is performed by the idmap binary, launched through Installer
- * and installd.
+ * and installd (or idmap2).
  *
  * Note: this class is subclassed in the OMS unit tests, and hence not marked as final.
  */
 class IdmapManager {
+    private static final boolean FEATURE_FLAG_IDMAP2 = false;
+
     private final Installer mInstaller;
+    private IIdmap2 mIdmap2Service;
 
     IdmapManager(final Installer installer) {
         mInstaller = installer;
+        if (FEATURE_FLAG_IDMAP2) {
+            connectToIdmap2d();
+        }
     }
 
     boolean createIdmap(@NonNull final PackageInfo targetPackage,
@@ -59,8 +69,12 @@
         final String targetPath = targetPackage.applicationInfo.getBaseCodePath();
         final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath();
         try {
-            mInstaller.idmap(targetPath, overlayPath, sharedGid);
-        } catch (InstallerException e) {
+            if (FEATURE_FLAG_IDMAP2) {
+                mIdmap2Service.createIdmap(targetPath, overlayPath, userId);
+            } else {
+                mInstaller.idmap(targetPath, overlayPath, sharedGid);
+            }
+        } catch (Exception e) {
             Slog.w(TAG, "failed to generate idmap for " + targetPath + " and "
                     + overlayPath + ": " + e.getMessage());
             return false;
@@ -69,13 +83,16 @@
     }
 
     boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) {
-        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
         if (DEBUG) {
             Slog.d(TAG, "remove idmap for " + oi.baseCodePath);
         }
         try {
-            mInstaller.removeIdmap(oi.baseCodePath);
-        } catch (InstallerException e) {
+            if (FEATURE_FLAG_IDMAP2) {
+                mIdmap2Service.removeIdmap(oi.baseCodePath, userId);
+            } else {
+                mInstaller.removeIdmap(oi.baseCodePath);
+            }
+        } catch (Exception e) {
             Slog.w(TAG, "failed to remove idmap for " + oi.baseCodePath + ": " + e.getMessage());
             return false;
         }
@@ -83,19 +100,58 @@
     }
 
     boolean idmapExists(@NonNull final OverlayInfo oi) {
-        // unused OverlayInfo.userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
-        return new File(getIdmapPath(oi.baseCodePath)).isFile();
+        return new File(getIdmapPath(oi.baseCodePath, oi.userId)).isFile();
     }
 
     boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
-        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
-        return new File(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath())).isFile();
+        return new File(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath(), userId))
+            .isFile();
     }
 
-    private String getIdmapPath(@NonNull final String baseCodePath) {
-        final StringBuilder sb = new StringBuilder("/data/resource-cache/");
-        sb.append(baseCodePath.substring(1).replace('/', '@'));
-        sb.append("@idmap");
-        return sb.toString();
+    private @NonNull String getIdmapPath(@NonNull final String overlayPackagePath,
+            final int userId) {
+        if (FEATURE_FLAG_IDMAP2) {
+            try {
+                return mIdmap2Service.getIdmapPath(overlayPackagePath, userId);
+            } catch (Exception e) {
+                Slog.w(TAG, "failed to get idmap path for " + overlayPackagePath + ": "
+                        + e.getMessage());
+                return "";
+            }
+        } else {
+            final StringBuilder sb = new StringBuilder("/data/resource-cache/");
+            sb.append(overlayPackagePath.substring(1).replace('/', '@'));
+            sb.append("@idmap");
+            return sb.toString();
+        }
+    }
+
+    private void connectToIdmap2d() {
+        IBinder binder = ServiceManager.getService(IDMAP_SERVICE);
+        if (binder != null) {
+            try {
+                binder.linkToDeath(new IBinder.DeathRecipient() {
+                    @Override
+                    public void binderDied() {
+                        Slog.w(TAG, "service '" + IDMAP_SERVICE + "' died; reconnecting...");
+                        connectToIdmap2d();
+                    }
+
+                }, 0);
+            } catch (RemoteException e) {
+                binder = null;
+            }
+        }
+        if (binder != null) {
+            mIdmap2Service = IIdmap2.Stub.asInterface(binder);
+            if (DEBUG) {
+                Slog.d(TAG, "service '" + IDMAP_SERVICE + "' connected");
+            }
+        } else {
+            Slog.w(TAG, "service '" + IDMAP_SERVICE + "' not found; trying again...");
+            BackgroundThread.getHandler().postDelayed(() -> {
+                connectToIdmap2d();
+            }, SECOND_IN_MILLIS);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index 36bf83d..572d368 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -179,19 +179,13 @@
 
     List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName,
             final int userId) {
-        // Static RROs targeting "android" are loaded from AssetManager, and so they should be
-        // ignored in OverlayManagerService.
         return selectWhereTarget(targetPackageName, userId)
-                .filter((i) -> !(i.isStatic() && "android".equals(i.getTargetPackageName())))
                 .map(SettingsItem::getOverlayInfo)
                 .collect(Collectors.toList());
     }
 
     ArrayMap<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
-        // Static RROs targeting "android" are loaded from AssetManager, and so they should be
-        // ignored in OverlayManagerService.
         return selectWhereUser(userId)
-                .filter((i) -> !(i.isStatic() && "android".equals(i.getTargetPackageName())))
                 .map(SettingsItem::getOverlayInfo)
                 .collect(Collectors.groupingBy(info -> info.targetPackageName, ArrayMap::new,
                         Collectors.toList()));
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 404f152..b490381 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -77,7 +77,6 @@
  */
 public class LauncherAppsService extends SystemService {
 
-    private static final boolean SHOW_HIDDEN_APP_ENABLED = false;
     private final LauncherAppsImpl mLauncherAppsImpl;
 
     public LauncherAppsService(Context context) {
@@ -310,22 +309,28 @@
                             .addCategory(Intent.CATEGORY_LAUNCHER)
                             .setPackage(packageName),
                     user);
-            if (!SHOW_HIDDEN_APP_ENABLED) {
+            if (Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, 0) == 0) {
                 return launcherActivities;
             }
 
             final int callingUid = injectBinderCallingUid();
             final ArrayList<ResolveInfo> result = new ArrayList<>(launcherActivities.getList());
+            final PackageManagerInternal pmInt =
+                    LocalServices.getService(PackageManagerInternal.class);
             if (packageName != null) {
-                // If target package has launcher activities, then return those launcher
-                // activities. Otherwise, return hidden activity that forwards user to app
-                // details page.
+                // If this hidden app should not be shown, return the original list.
+                // Otherwise, inject hidden activity that forwards user to app details page.
                 if (result.size() > 0) {
                     return launcherActivities;
                 }
-                ResolveInfo info = getHiddenAppActivityInfo(packageName, callingUid, user);
-                if (info != null) {
-                    result.add(info);
+                ApplicationInfo appInfo = pmInt.getApplicationInfo(packageName, /*flags*/ 0,
+                        callingUid, user.getIdentifier());
+                if (shouldShowHiddenApp(appInfo)) {
+                    ResolveInfo info = getHiddenAppActivityInfo(packageName, callingUid, user);
+                    if (info != null) {
+                        result.add(info);
+                    }
                 }
                 return new ParceledListSlice<>(result);
             }
@@ -336,8 +341,6 @@
                 for (ResolveInfo info : result) {
                     visiblePackages.add(info.activityInfo.packageName);
                 }
-                final PackageManagerInternal pmInt =
-                        LocalServices.getService(PackageManagerInternal.class);
                 List<ApplicationInfo> installedPackages = pmInt.getInstalledApplications(0,
                         user.getIdentifier(), callingUid);
                 for (ApplicationInfo applicationInfo : installedPackages) {
@@ -359,7 +362,7 @@
         }
 
         private static boolean shouldShowHiddenApp(ApplicationInfo appInfo) {
-            if (appInfo.isSystemApp() || appInfo.isUpdatedSystemApp()) {
+            if (appInfo == null || appInfo.isSystemApp() || appInfo.isUpdatedSystemApp()) {
                 return false;
             }
             return true;
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 95c70d5..95d2154 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -49,7 +49,7 @@
 
 import dalvik.system.DexFile;
 
-import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_NONE;
+import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DISABLED;
 
 import static com.android.server.pm.Installer.DEXOPT_BOOTCOMPLETE;
 import static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE;
@@ -548,7 +548,7 @@
         // Some apps are executed with restrictions on hidden API usage. If this app is one
         // of them, pass a flag to dexopt to enable the same restrictions during compilation.
         // TODO we should pass the actual flag value to dexopt, rather than assuming blacklist
-        int hiddenApiFlag = info.getHiddenApiEnforcementPolicy() == HIDDEN_API_ENFORCEMENT_NONE
+        int hiddenApiFlag = info.getHiddenApiEnforcementPolicy() == HIDDEN_API_ENFORCEMENT_DISABLED
                 ? 0
                 : DEXOPT_ENABLE_HIDDEN_API_CHECKS;
         // Avoid generating CompactDex for modes that are latency critical.
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 0b32d1a..1a5b86c 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -58,7 +58,6 @@
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SELinux;
-import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.StorageManager;
@@ -108,7 +107,9 @@
 import java.util.Objects;
 import java.util.Random;
 
-public class PackageInstallerService extends IPackageInstaller.Stub {
+/** The service responsible for installing packages. */
+public class PackageInstallerService extends IPackageInstaller.Stub implements
+        PackageSessionProvider {
     private static final String TAG = "PackageInstaller";
     private static final boolean LOGD = false;
 
@@ -297,6 +298,7 @@
             in.setInput(fis, StandardCharsets.UTF_8.name());
 
             int type;
+            PackageInstallerSession currentSession = null;
             while ((type = in.next()) != END_DOCUMENT) {
                 if (type == START_TAG) {
                     final String tag = in.getName();
@@ -304,8 +306,10 @@
                         final PackageInstallerSession session;
                         try {
                             session = PackageInstallerSession.readFromXml(in, mInternalCallback,
-                                    mContext, mPm, mInstallThread.getLooper(), mSessionsDir);
+                                    mContext, mPm, mInstallThread.getLooper(), mSessionsDir, this);
+                            currentSession = session;
                         } catch (Exception e) {
+                            currentSession = null;
                             Slog.e(TAG, "Could not read session", e);
                             continue;
                         }
@@ -330,6 +334,10 @@
                             addHistoricalSessionLocked(session);
                         }
                         mAllocatedSessions.put(session.sessionId, true);
+                    } else if (currentSession != null
+                            && PackageInstallerSession.TAG_CHILD_SESSION.equals(tag)) {
+                        currentSession.addChildSessionIdInternal(
+                                PackageInstallerSession.readChildSessionIdFromXml(in));
                     }
                 }
             }
@@ -437,70 +445,72 @@
             }
         }
 
-        // Only system components can circumvent runtime permissions when installing.
-        if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
-                && mContext.checkCallingOrSelfPermission(Manifest.permission
-                .INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) {
-            throw new SecurityException("You need the "
-                    + "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission "
-                    + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
-        }
-
-        if ((params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0
-                || (params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
-            throw new IllegalArgumentException(
-                    "New installs into ASEC containers no longer supported");
-        }
-
-        // Defensively resize giant app icons
-        if (params.appIcon != null) {
-            final ActivityManager am = (ActivityManager) mContext.getSystemService(
-                    Context.ACTIVITY_SERVICE);
-            final int iconSize = am.getLauncherLargeIconSize();
-            if ((params.appIcon.getWidth() > iconSize * 2)
-                    || (params.appIcon.getHeight() > iconSize * 2)) {
-                params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize,
-                        true);
-            }
-        }
-
-        switch (params.mode) {
-            case SessionParams.MODE_FULL_INSTALL:
-            case SessionParams.MODE_INHERIT_EXISTING:
-                break;
-            default:
-                throw new IllegalArgumentException("Invalid install mode: " + params.mode);
-        }
-
-        // If caller requested explicit location, sanity check it, otherwise
-        // resolve the best internal or adopted location.
-        if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
-            if (!PackageHelper.fitsOnInternal(mContext, params)) {
-                throw new IOException("No suitable internal storage available");
+        if (!params.isMultiPackage) {
+            // Only system components can circumvent runtime permissions when installing.
+            if ((params.installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
+                    && mContext.checkCallingOrSelfPermission(Manifest.permission
+                    .INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) {
+                throw new SecurityException("You need the "
+                        + "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission "
+                        + "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
             }
 
-        } else if ((params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
-            if (!PackageHelper.fitsOnExternal(mContext, params)) {
-                throw new IOException("No suitable external storage available");
+            if ((params.installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0
+                    || (params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+                throw new IllegalArgumentException(
+                        "New installs into ASEC containers no longer supported");
             }
 
-        } else if ((params.installFlags & PackageManager.INSTALL_FORCE_VOLUME_UUID) != 0) {
-            // For now, installs to adopted media are treated as internal from
-            // an install flag point-of-view.
-            params.setInstallFlagsInternal();
+            // Defensively resize giant app icons
+            if (params.appIcon != null) {
+                final ActivityManager am = (ActivityManager) mContext.getSystemService(
+                        Context.ACTIVITY_SERVICE);
+                final int iconSize = am.getLauncherLargeIconSize();
+                if ((params.appIcon.getWidth() > iconSize * 2)
+                        || (params.appIcon.getHeight() > iconSize * 2)) {
+                    params.appIcon = Bitmap.createScaledBitmap(params.appIcon, iconSize, iconSize,
+                            true);
+                }
+            }
 
-        } else {
-            // For now, installs to adopted media are treated as internal from
-            // an install flag point-of-view.
-            params.setInstallFlagsInternal();
+            switch (params.mode) {
+                case SessionParams.MODE_FULL_INSTALL:
+                case SessionParams.MODE_INHERIT_EXISTING:
+                    break;
+                default:
+                    throw new IllegalArgumentException("Invalid install mode: " + params.mode);
+            }
 
-            // Resolve best location for install, based on combination of
-            // requested install flags, delta size, and manifest settings.
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                params.volumeUuid = PackageHelper.resolveInstallVolume(mContext, params);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
+            // If caller requested explicit location, sanity check it, otherwise
+            // resolve the best internal or adopted location.
+            if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+                if (!PackageHelper.fitsOnInternal(mContext, params)) {
+                    throw new IOException("No suitable internal storage available");
+                }
+
+            } else if ((params.installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
+                if (!PackageHelper.fitsOnExternal(mContext, params)) {
+                    throw new IOException("No suitable external storage available");
+                }
+
+            } else if ((params.installFlags & PackageManager.INSTALL_FORCE_VOLUME_UUID) != 0) {
+                // For now, installs to adopted media are treated as internal from
+                // an install flag point-of-view.
+                params.setInstallFlagsInternal();
+
+            } else {
+                // For now, installs to adopted media are treated as internal from
+                // an install flag point-of-view.
+                params.setInstallFlagsInternal();
+
+                // Resolve best location for install, based on combination of
+                // requested install flags, delta size, and manifest settings.
+                final long ident = Binder.clearCallingIdentity();
+                try {
+                    params.volumeUuid = PackageHelper.resolveInstallVolume(mContext, params);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
             }
         }
 
@@ -526,17 +536,19 @@
         // We're staging to exactly one location
         File stageDir = null;
         String stageCid = null;
-        if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
-            final boolean isInstant =
-                    (params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
-            stageDir = buildStageDir(params.volumeUuid, sessionId, isInstant);
-        } else {
-            stageCid = buildExternalStageCid(sessionId);
+        if (!params.isMultiPackage) {
+            if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+                final boolean isInstant =
+                        (params.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
+                stageDir = buildStageDir(params.volumeUuid, sessionId, isInstant);
+            } else {
+                stageCid = buildExternalStageCid(sessionId);
+            }
         }
-
-        session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
-                mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
-                params, createdMillis, stageDir, stageCid, false, false);
+        session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
+                mInstallThread.getLooper(), sessionId, userId, installerPackageName,
+                callingUid, params, createdMillis, stageDir, stageCid, false, false, null,
+                SessionInfo.INVALID_ID);
 
         synchronized (mSessions) {
             mSessions.put(sessionId, session);
@@ -646,8 +658,8 @@
         }
 
         try {
-            Os.mkdir(stageDir.getAbsolutePath(), 0755);
-            Os.chmod(stageDir.getAbsolutePath(), 0755);
+            Os.mkdir(stageDir.getAbsolutePath(), 0775);
+            Os.chmod(stageDir.getAbsolutePath(), 0775);
         } catch (ErrnoException e) {
             // This purposefully throws if directory already exists
             throw new IOException("Failed to prepare session dir: " + stageDir, e);
@@ -679,7 +691,7 @@
         synchronized (mSessions) {
             for (int i = 0; i < mSessions.size(); i++) {
                 final PackageInstallerSession session = mSessions.valueAt(i);
-                if (session.userId == userId) {
+                if (session.userId == userId && !session.hasParentSessionId()) {
                     result.add(session.generateInfo(false));
                 }
             }
@@ -700,7 +712,7 @@
 
                 SessionInfo info = session.generateInfo(false);
                 if (Objects.equals(info.getInstallerPackageName(), installerPackageName)
-                        && session.userId == userId) {
+                        && session.userId == userId && !session.hasParentSessionId()) {
                     result.add(info);
                 }
             }
@@ -782,6 +794,13 @@
         mCallbacks.unregister(callback);
     }
 
+    @Override
+    public PackageInstallerSession getSession(int sessionId) {
+        synchronized (mSessions) {
+            return mSessions.get(sessionId);
+        }
+    }
+
     private static int getSessionCount(SparseArray<PackageInstallerSession> sessions,
             int installerUid) {
         int count = 0;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 51225a7..ea190a7 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -43,9 +43,12 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.apex.IApexService;
 import android.app.admin.DeviceAdminInfo;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.Context;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.ApplicationInfo;
@@ -68,6 +71,7 @@
 import android.os.FileBridge;
 import android.os.FileUtils;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
@@ -75,6 +79,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.RevocableFileDescriptor;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
@@ -88,6 +93,7 @@
 import android.util.ExceptionUtils;
 import android.util.MathUtils;
 import android.util.Slog;
+import android.util.SparseIntArray;
 import android.util.apk.ApkSignatureVerifier;
 
 import com.android.internal.annotations.GuardedBy;
@@ -128,6 +134,7 @@
 
     /** XML constants used for persisting a session */
     static final String TAG_SESSION = "session";
+    static final String TAG_CHILD_SESSION = "childSession";
     private static final String TAG_GRANTED_RUNTIME_PERMISSION = "granted-runtime-permission";
     private static final String ATTR_SESSION_ID = "sessionId";
     private static final String ATTR_USER_ID = "userId";
@@ -138,6 +145,8 @@
     private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
     private static final String ATTR_PREPARED = "prepared";
     private static final String ATTR_SEALED = "sealed";
+    private static final String ATTR_MULTI_PACKAGE = "multiPackage";
+    private static final String ATTR_PARENT_SESSION_ID = "parentSessionId";
     private static final String ATTR_MODE = "mode";
     private static final String ATTR_INSTALL_FLAGS = "installFlags";
     private static final String ATTR_INSTALL_LOCATION = "installLocation";
@@ -155,6 +164,7 @@
     private static final String ATTR_INSTALL_REASON = "installRason";
 
     private static final String PROPERTY_NAME_INHERIT_NATIVE = "pi.inherit_native_on_dont_kill";
+    private static final int[] EMPTY_CHILD_SESSION_ARRAY = {};
 
     // TODO: enforce INSTALL_ALLOW_TEST
     // TODO: enforce INSTALL_ALLOW_DOWNGRADE
@@ -163,6 +173,7 @@
     private final Context mContext;
     private final PackageManagerService mPm;
     private final Handler mHandler;
+    private final PackageSessionProvider mSessionProvider;
 
     final int sessionId;
     final int userId;
@@ -234,6 +245,10 @@
     private long mVersionCode;
     @GuardedBy("mLock")
     private PackageParser.SigningDetails mSigningDetails;
+    @GuardedBy("mLock")
+    private SparseIntArray mChildSessionIds = new SparseIntArray();
+    @GuardedBy("mLock")
+    private int mParentSessionId;
 
     /**
      * Path to the validated base APK for this session, which may point at an
@@ -370,12 +385,16 @@
     }
 
     public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
-            Context context, PackageManagerService pm, Looper looper, int sessionId, int userId,
+            Context context, PackageManagerService pm,
+            PackageSessionProvider sessionProvider, Looper looper,
+            int sessionId, int userId,
             String installerPackageName, int installerUid, SessionParams params, long createdMillis,
-            File stageDir, String stageCid, boolean prepared, boolean sealed) {
+            File stageDir, String stageCid, boolean prepared, boolean sealed,
+            @Nullable int[] childSessionIds, int parentSessionId) {
         mCallback = callback;
         mContext = context;
         mPm = pm;
+        mSessionProvider = sessionProvider;
         mHandler = new Handler(looper, mHandlerCallback);
 
         this.sessionId = sessionId;
@@ -387,8 +406,14 @@
         this.createdMillis = createdMillis;
         this.stageDir = stageDir;
         this.stageCid = stageCid;
+        if (childSessionIds != null) {
+            for (int childSessionId : childSessionIds) {
+                mChildSessionIds.put(childSessionId, 0);
+            }
+        }
+        this.mParentSessionId = parentSessionId;
 
-        if ((stageDir == null) == (stageCid == null)) {
+        if (!params.isMultiPackage && (stageDir == null) == (stageCid == null)) {
             throw new IllegalArgumentException(
                     "Exactly one of stageDir or stageCid stage must be set");
         }
@@ -437,6 +462,12 @@
             info.referrerUri = params.referrerUri;
             info.grantedRuntimePermissions = params.grantedRuntimePermissions;
             info.installFlags = params.installFlags;
+            info.isMultiPackage = params.isMultiPackage;
+            info.parentSessionId = mParentSessionId;
+            info.childSessionIds = mChildSessionIds.copyKeys();
+            if (info.childSessionIds == null) {
+                info.childSessionIds = EMPTY_CHILD_SESSION_ARRAY;
+            }
         }
         return info;
     }
@@ -760,6 +791,92 @@
 
     @Override
     public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
+        if (!markAsCommitted(statusReceiver, forTransfer  /* enforce */)) {
+            return;
+        }
+        if (isMultiPackage()) {
+
+            final SparseIntArray remainingSessions = mChildSessionIds.clone();
+            final ChildStatusIntentReceiver localIntentReceiver =
+                    new ChildStatusIntentReceiver(remainingSessions, statusReceiver);
+            for (int childSessionId : getChildSessionIds()) {
+                mSessionProvider.getSession(childSessionId)
+                        .markAsCommitted(localIntentReceiver.getIntentSender(), forTransfer);
+            }
+        }
+        mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
+    }
+
+    private class ChildStatusIntentReceiver {
+        private final SparseIntArray mChildSessionsRemaining;
+        private final IntentSender mStatusReceiver;
+        private final IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
+            @Override
+            public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
+                    IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
+                statusUpdate(intent);
+            }
+        };
+
+        private ChildStatusIntentReceiver(SparseIntArray remainingSessions,
+                IntentSender statusReceiver) {
+            this.mChildSessionsRemaining = remainingSessions;
+            this.mStatusReceiver = statusReceiver;
+        }
+
+        public IntentSender getIntentSender() {
+            return new IntentSender((IIntentSender) mLocalSender);
+        }
+
+        public void statusUpdate(Intent intent) {
+            mHandler.post(() -> {
+                if (mChildSessionsRemaining.size() == 0) {
+                    return;
+                }
+                final int sessionId = intent.getIntExtra(
+                        PackageInstaller.EXTRA_SESSION_ID, 0);
+                final int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
+                        PackageInstaller.STATUS_FAILURE);
+                final int sessionIndex = mChildSessionsRemaining.indexOfKey(sessionId);
+                if (PackageInstaller.STATUS_SUCCESS == status) {
+                    mChildSessionsRemaining.removeAt(sessionIndex);
+                    if (mChildSessionsRemaining.size() == 0) {
+                        try {
+                            intent.putExtra(PackageInstaller.EXTRA_SESSION_ID,
+                                    PackageInstallerSession.this.sessionId);
+                            mStatusReceiver.sendIntent(mContext, 0, intent, null, null);
+                        } catch (IntentSender.SendIntentException ignore) {
+                        }
+                    }
+                } else if (PackageInstaller.STATUS_PENDING_USER_ACTION == status) {
+                    try {
+                        mStatusReceiver.sendIntent(mContext, 0, intent, null, null);
+                    } catch (IntentSender.SendIntentException ignore) {
+                    }
+                } else {
+                    intent.putExtra(PackageInstaller.EXTRA_SESSION_ID,
+                            PackageInstallerSession.this.sessionId);
+                    mChildSessionsRemaining.clear(); // we're done. Don't send any more.
+                    try {
+                        mStatusReceiver.sendIntent(mContext, 0, intent, null, null);
+                    } catch (IntentSender.SendIntentException ignore) {
+                    }
+                }
+            });
+        }
+    }
+
+
+    /**
+     * Do everything but actually commit the session. If this was not already called, the session
+     * will be sealed and marked as committed. The caller of this method is responsible for
+     * subsequently submitting this session for processing.
+     *
+     * This method may be called multiple times to update the status receiver validate caller
+     * permissions.
+     */
+    public boolean markAsCommitted(
+            @NonNull IntentSender statusReceiver, boolean forTransfer) {
         Preconditions.checkNotNull(statusReceiver);
 
         final boolean wasSealed;
@@ -784,6 +901,12 @@
                 }
             }
 
+            // After validations and updating the observer, we can skip re-sealing, etc. because we
+            // have already marked ourselves as committed.
+            if (mCommitted) {
+                return true;
+            }
+
             wasSealed = mSealed;
             if (!mSealed) {
                 try {
@@ -794,7 +917,7 @@
                     // Do now throw an exception here to stay compatible with O and older
                     destroyInternal();
                     dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);
-                    return;
+                    return false;
                 }
             }
 
@@ -807,7 +930,6 @@
             mActiveCount.incrementAndGet();
 
             mCommitted = true;
-            mHandler.obtainMessage(MSG_COMMIT).sendToTarget();
         }
 
         if (!wasSealed) {
@@ -816,6 +938,7 @@
             // the session lock, since otherwise it's a lock inversion.
             mCallback.onSessionSealedBlocking(this);
         }
+        return true;
     }
 
     /**
@@ -831,29 +954,37 @@
         assertNoWriteFileTransfersOpenLocked();
         assertPreparedAndNotDestroyedLocked("sealing of session");
 
-        final PackageInfo pkgInfo = mPm.getPackageInfo(
-                params.appPackageName, PackageManager.GET_SIGNATURES
-                        | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
-
-        resolveStageDirLocked();
-
         mSealed = true;
 
-        // Verify that stage looks sane with respect to existing application.
-        // This currently only ensures packageName, versionCode, and certificate
-        // consistency.
-        try {
-            validateInstallLocked(pkgInfo);
-        } catch (PackageManagerException e) {
-            throw e;
-        } catch (Throwable e) {
-            // Convert all exceptions into package manager exceptions as only those are handled
-            // in the code above
-            throw new PackageManagerException(e);
-        }
-
         // Read transfers from the original owner stay open, but as the session's data
         // cannot be modified anymore, there is no leak of information.
+        if (!params.isMultiPackage) {
+            final PackageInfo pkgInfo = mPm.getPackageInfo(
+                    params.appPackageName, PackageManager.GET_SIGNATURES
+                            | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
+
+            resolveStageDirLocked();
+
+            // Verify that stage looks sane with respect to existing application.
+            // This currently only ensures packageName, versionCode, and certificate
+            // consistency.
+            try {
+                if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+                    validateApexInstallLocked(pkgInfo);
+                } else {
+                    // Verify that stage looks sane with respect to existing application.
+                    // This currently only ensures packageName, versionCode, and certificate
+                    // consistency.
+                    validateApkInstallLocked(pkgInfo);
+                }
+            } catch (PackageManagerException e) {
+                throw e;
+            } catch (Throwable e) {
+                // Convert all exceptions into package manager exceptions as only those are handled
+                // in the code above
+                throw new PackageManagerException(e);
+            }
+        }
     }
 
     @Override
@@ -911,10 +1042,83 @@
     @GuardedBy("mLock")
     private void commitLocked()
             throws PackageManagerException {
-        if (mRelinquished) {
-            Slog.d(TAG, "Ignoring commit after previous commit relinquished control");
+        final PackageManagerService.ActiveInstallSession committingSession =
+                makeSessionActiveLocked();
+        if (committingSession == null) {
             return;
         }
+        if (isMultiPackage()) {
+            final int[] childSessionIds = getChildSessionIds();
+            List<PackageManagerService.ActiveInstallSession> childSessions =
+                    new ArrayList<>(childSessionIds.length);
+            boolean success = true;
+            PackageManagerException failure = null;
+            for (int childSessionId : getChildSessionIds()) {
+                final PackageInstallerSession session = mSessionProvider.getSession(childSessionId);
+                try {
+                    final PackageManagerService.ActiveInstallSession activeSession =
+                            session.makeSessionActiveLocked();
+                    if (activeSession != null) {
+                        if ((activeSession.getSessionParams().installFlags
+                                & PackageManager.INSTALL_APEX) != 0) {
+                            // TODO(b/118865310): Add exception to this case for staged installs
+                            throw new PackageManagerException(
+                                    PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
+                                    "Atomic install is not supported for APEX packages.");
+                        }
+                        childSessions.add(activeSession);
+                    }
+                } catch (PackageManagerException e) {
+                    failure = e;
+                    success = false;
+                }
+            }
+            if (!success) {
+                try {
+                    mRemoteObserver.onPackageInstalled(
+                            null, failure.error, failure.getLocalizedMessage(), null);
+                } catch (RemoteException ignored) {
+                }
+                return;
+            }
+            mPm.installStage(childSessions);
+        } else {
+            if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+                commitApexLocked();
+            } else {
+                mPm.installStage(committingSession);
+            }
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void commitApexLocked() throws PackageManagerException {
+        try {
+            IApexService apex = IApexService.Stub.asInterface(
+                    ServiceManager.getService("apexservice"));
+            apex.stagePackage(mResolvedBaseFile.toString());
+        } catch (Throwable e) {
+            // Convert all exceptions into package manager exceptions as only those are handled
+            // in the code above
+            throw new PackageManagerException(e);
+        } finally {
+            destroyInternal();
+            dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "APEX installed", null);
+        }
+    }
+
+    /**
+     * Stages this session for install and returns a
+     * {@link PackageManagerService.ActiveInstallSession} representing this new staged state or null
+     * in case permissions need to be requested before install can proceed.
+     */
+    @GuardedBy("mLock")
+    private PackageManagerService.ActiveInstallSession makeSessionActiveLocked()
+            throws PackageManagerException {
+        if (mRelinquished) {
+            throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+                    "Session relinquished");
+        }
         if (mDestroyed) {
             throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
         }
@@ -922,99 +1126,109 @@
             throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
         }
 
-        Preconditions.checkNotNull(mPackageName);
-        Preconditions.checkNotNull(mSigningDetails);
-        Preconditions.checkNotNull(mResolvedBaseFile);
+        final IPackageInstallObserver2 localObserver;
+        if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+            localObserver = null;
+        } else {
+            if (!params.isMultiPackage) {
+                Preconditions.checkNotNull(mPackageName);
+                Preconditions.checkNotNull(mSigningDetails);
+                Preconditions.checkNotNull(mResolvedBaseFile);
 
-        if (needToAskForPermissionsLocked()) {
-            // User needs to confirm installation; give installer an intent they can use to involve
-            // user.
-            final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_INSTALL);
-            intent.setPackage(mPm.getPackageInstallerPackageName());
-            intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
-            try {
-                mRemoteObserver.onUserActionRequired(intent);
-            } catch (RemoteException ignored) {
-            }
+                if (needToAskForPermissionsLocked()) {
+                    // User needs to confirm installation;
+                    // give installer an intent they can use to involve
+                    // user.
+                    final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_INSTALL);
+                    intent.setPackage(mPm.getPackageInstallerPackageName());
+                    intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
+                    try {
+                        mRemoteObserver.onUserActionRequired(intent);
+                    } catch (RemoteException ignored) {
+                    }
 
-            // Commit was keeping session marked as active until now; release
-            // that extra refcount so session appears idle.
-            closeInternal(false);
-            return;
-        }
-
-        // Inherit any packages and native libraries from existing install that
-        // haven't been overridden.
-        if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
-            try {
-                final List<File> fromFiles = mResolvedInheritedFiles;
-                final File toDir = resolveStageDirLocked();
-
-                if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
-                if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
-                    throw new IllegalStateException("mInheritedFilesBase == null");
+                    // Commit was keeping session marked as active until now; release
+                    // that extra refcount so session appears idle.
+                    closeInternal(false);
+                    return null;
                 }
 
-                if (isLinkPossible(fromFiles, toDir)) {
-                    if (!mResolvedInstructionSets.isEmpty()) {
-                        final File oatDir = new File(toDir, "oat");
-                        createOatDirs(mResolvedInstructionSets, oatDir);
-                    }
-                    // pre-create lib dirs for linking if necessary
-                    if (!mResolvedNativeLibPaths.isEmpty()) {
-                        for (String libPath : mResolvedNativeLibPaths) {
-                            // "/lib/arm64" -> ["lib", "arm64"]
-                            final int splitIndex = libPath.lastIndexOf('/');
-                            if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
-                                Slog.e(TAG, "Skipping native library creation for linking due to "
-                                        + "invalid path: " + libPath);
-                                continue;
-                            }
-                            final String libDirPath = libPath.substring(1, splitIndex);
-                            final File libDir = new File(toDir, libDirPath);
-                            if (!libDir.exists()) {
-                                NativeLibraryHelper.createNativeLibrarySubdir(libDir);
-                            }
-                            final String archDirPath = libPath.substring(splitIndex + 1);
-                            NativeLibraryHelper.createNativeLibrarySubdir(
-                                    new File(libDir, archDirPath));
+                // Inherit any packages and native libraries from existing install that
+                // haven't been overridden.
+                if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
+                    try {
+                        final List<File> fromFiles = mResolvedInheritedFiles;
+                        final File toDir = resolveStageDirLocked();
+
+                        if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
+                        if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
+                            throw new IllegalStateException("mInheritedFilesBase == null");
                         }
+
+                        if (isLinkPossible(fromFiles, toDir)) {
+                            if (!mResolvedInstructionSets.isEmpty()) {
+                                final File oatDir = new File(toDir, "oat");
+                                createOatDirs(mResolvedInstructionSets, oatDir);
+                            }
+                            // pre-create lib dirs for linking if necessary
+                            if (!mResolvedNativeLibPaths.isEmpty()) {
+                                for (String libPath : mResolvedNativeLibPaths) {
+                                    // "/lib/arm64" -> ["lib", "arm64"]
+                                    final int splitIndex = libPath.lastIndexOf('/');
+                                    if (splitIndex < 0 || splitIndex >= libPath.length() - 1) {
+                                        Slog.e(TAG,
+                                                "Skipping native library creation for linking due"
+                                                        + " to invalid path: " + libPath);
+                                        continue;
+                                    }
+                                    final String libDirPath = libPath.substring(1, splitIndex);
+                                    final File libDir = new File(toDir, libDirPath);
+                                    if (!libDir.exists()) {
+                                        NativeLibraryHelper.createNativeLibrarySubdir(libDir);
+                                    }
+                                    final String archDirPath = libPath.substring(splitIndex + 1);
+                                    NativeLibraryHelper.createNativeLibrarySubdir(
+                                            new File(libDir, archDirPath));
+                                }
+                            }
+                            linkFiles(fromFiles, toDir, mInheritedFilesBase);
+                        } else {
+                            // TODO: this should delegate to DCS so the system process
+                            // avoids holding open FDs into containers.
+                            copyFiles(fromFiles, toDir);
+                        }
+                    } catch (IOException e) {
+                        throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
+                                "Failed to inherit existing install", e);
                     }
-                    linkFiles(fromFiles, toDir, mInheritedFilesBase);
-                } else {
-                    // TODO: this should delegate to DCS so the system process
-                    // avoids holding open FDs into containers.
-                    copyFiles(fromFiles, toDir);
                 }
-            } catch (IOException e) {
-                throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
-                        "Failed to inherit existing install", e);
+
+                // TODO: surface more granular state from dexopt
+                mInternalProgress = 0.5f;
+                computeProgressLocked(true);
+
+                // Unpack native libraries
+                extractNativeLibraries(mResolvedStageDir, params.abiOverride,
+                        mayInheritNativeLibs());
             }
+
+            // We've reached point of no return; call into PMS to install the stage.
+            // Regardless of success or failure we always destroy session.
+            localObserver = new IPackageInstallObserver2.Stub() {
+                @Override
+                public void onUserActionRequired(Intent intent) {
+                    throw new IllegalStateException();
+                }
+
+                @Override
+                public void onPackageInstalled(String basePackageName, int returnCode, String msg,
+                        Bundle extras) {
+                    destroyInternal();
+                    dispatchSessionFinished(returnCode, msg, extras);
+                }
+            };
         }
 
-        // TODO: surface more granular state from dexopt
-        mInternalProgress = 0.5f;
-        computeProgressLocked(true);
-
-        // Unpack native libraries
-        extractNativeLibraries(mResolvedStageDir, params.abiOverride, mayInheritNativeLibs());
-
-        // We've reached point of no return; call into PMS to install the stage.
-        // Regardless of success or failure we always destroy session.
-        final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
-            @Override
-            public void onUserActionRequired(Intent intent) {
-                throw new IllegalStateException();
-            }
-
-            @Override
-            public void onPackageInstalled(String basePackageName, int returnCode, String msg,
-                    Bundle extras) {
-                destroyInternal();
-                dispatchSessionFinished(returnCode, msg, extras);
-            }
-        };
-
         final UserHandle user;
         if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
             user = UserHandle.ALL;
@@ -1023,8 +1237,9 @@
         }
 
         mRelinquished = true;
-        mPm.installStage(mPackageName, stageDir, localObserver, params,
-                mInstallerPackageName, mInstallerUid, user, mSigningDetails);
+        return new PackageManagerService.ActiveInstallSession(mPackageName, stageDir,
+                localObserver, params, mInstallerPackageName, mInstallerUid, user,
+                mSigningDetails);
     }
 
     private static void maybeRenameFile(File from, File to) throws PackageManagerException {
@@ -1047,6 +1262,57 @@
                 (params.installFlags & PackageManager.DONT_KILL_APP) != 0;
     }
 
+    @GuardedBy("mLock")
+    private void validateApexInstallLocked(@Nullable PackageInfo pkgInfo)
+            throws PackageManagerException {
+        mResolvedStagedFiles.clear();
+        mResolvedInheritedFiles.clear();
+
+        try {
+            resolveStageDirLocked();
+        } catch (IOException e) {
+            throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+                "Failed to resolve stage location", e);
+        }
+
+        final File[] addedFiles = mResolvedStageDir.listFiles(sAddedFilter);
+        if (ArrayUtils.isEmpty(addedFiles)) {
+            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
+        }
+
+        if (addedFiles.length > 1) {
+            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+                "Only one APEX file at a time might be installed");
+        }
+        File addedFile = addedFiles[0];
+        final ApkLite apk;
+        try {
+            apk = PackageParser.parseApkLite(
+                addedFile, PackageParser.PARSE_COLLECT_CERTIFICATES);
+        } catch (PackageParserException e) {
+            throw PackageManagerException.from(e);
+        }
+
+        mPackageName = apk.packageName;
+        mVersionCode = apk.getLongVersionCode();
+        mSigningDetails = apk.signingDetails;
+        mResolvedBaseFile = addedFile;
+
+        assertApkConsistentLocked(String.valueOf(addedFile), apk);
+
+        if (mSigningDetails == PackageParser.SigningDetails.UNKNOWN) {
+            try {
+                // STOPSHIP: For APEX we should also implement proper APK Signature verification.
+                mSigningDetails = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts(
+                    pkgInfo.applicationInfo.sourceDir,
+                    PackageParser.SigningDetails.SignatureSchemeVersion.JAR);
+            } catch (PackageParserException e) {
+                throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+                    "Couldn't obtain signatures from base APK");
+            }
+        }
+    }
+
     /**
      * Validate install by confirming that all application packages are have
      * consistent package name, version code, and signing certificates.
@@ -1060,7 +1326,7 @@
      * {@link PackageManagerService}.
      */
     @GuardedBy("mLock")
-    private void validateInstallLocked(@Nullable PackageInfo pkgInfo)
+    private void validateApkInstallLocked(@Nullable PackageInfo pkgInfo)
             throws PackageManagerException {
         ApkLite baseApk = null;
         mPackageName = null;
@@ -1475,6 +1741,14 @@
         }
     }
 
+    /**
+     * Adds a child session ID without any safety / sanity checks. This should only be used to
+     * build a session from XML or similar.
+     */
+    void addChildSessionIdInternal(int sessionId) {
+        mChildSessionIds.put(sessionId, 0);
+    }
+
     public void open() throws IOException {
         if (mActiveCount.getAndIncrement() == 0) {
             mCallback.onSessionActiveChanged(this, true);
@@ -1486,6 +1760,8 @@
             if (!mPrepared) {
                 if (stageDir != null) {
                     prepareStageDir(stageDir);
+                } else if (params.isMultiPackage) {
+                    // it's all ok
                 } else {
                     throw new IllegalArgumentException("stageDir must be set");
                 }
@@ -1534,6 +1810,81 @@
         dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
     }
 
+    @Override
+    public boolean isMultiPackage() {
+        return params.isMultiPackage;
+    }
+
+    @Override
+    public int[] getChildSessionIds() {
+        final int[] childSessionIds = mChildSessionIds.copyKeys();
+        if (childSessionIds != null) {
+            return childSessionIds;
+        }
+        return EMPTY_CHILD_SESSION_ARRAY;
+    }
+
+    @Override
+    public void addChildSessionId(int sessionId) {
+        final PackageInstallerSession session = mSessionProvider.getSession(sessionId);
+        if (session == null) {
+            throw new RemoteException("Unable to add child.",
+                    new PackageManagerException("Child session " + sessionId + " does not exist"),
+                    false, true).rethrowAsRuntimeException();
+        }
+        synchronized (mLock) {
+            final int indexOfSession = mChildSessionIds.indexOfKey(sessionId);
+            if (indexOfSession >= 0) {
+                return;
+            }
+            session.setParentSessionId(this.sessionId);
+            addChildSessionIdInternal(sessionId);
+        }
+    }
+
+    @Override
+    public void removeChildSessionId(int sessionId) {
+        final PackageInstallerSession session = mSessionProvider.getSession(sessionId);
+        synchronized (mLock) {
+            final int indexOfSession = mChildSessionIds.indexOfKey(sessionId);
+            if (session != null) {
+                session.setParentSessionId(SessionInfo.INVALID_ID);
+            }
+            if (indexOfSession < 0) {
+                // not added in the first place; no-op
+                return;
+            }
+            mChildSessionIds.removeAt(indexOfSession);
+        }
+    }
+
+    /**
+     * Sets the parent session ID if not already set.
+     * If {@link SessionInfo#INVALID_ID} is passed, it will be unset.
+     */
+    void setParentSessionId(int parentSessionId) {
+        synchronized (mLock) {
+            if (parentSessionId != SessionInfo.INVALID_ID
+                    && mParentSessionId != SessionInfo.INVALID_ID) {
+                throw new RemoteException("Unable to set parent session.",
+                        new PackageManagerException(
+                                "The parent of " + sessionId + " is" + " already set to "
+                                        + mParentSessionId), false,
+                        true).rethrowAsRuntimeException();
+            }
+            this.mParentSessionId = parentSessionId;
+        }
+    }
+
+    boolean hasParentSessionId() {
+        return mParentSessionId != SessionInfo.INVALID_ID;
+    }
+
+    @Override
+    public int getParentSessionId() {
+        return mParentSessionId;
+    }
+
     private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
         final IPackageInstallObserver2 observer;
         final String packageName;
@@ -1623,6 +1974,7 @@
         pw.printPair("mBridges", mBridges.size());
         pw.printPair("mFinalStatus", mFinalStatus);
         pw.printPair("mFinalMessage", mFinalMessage);
+        pw.printPair("params.isMultiPackage", params.isMultiPackage);
         pw.println();
 
         pw.decreaseIndent();
@@ -1673,6 +2025,10 @@
             writeBooleanAttribute(out, ATTR_PREPARED, isPrepared());
             writeBooleanAttribute(out, ATTR_SEALED, isSealed());
 
+            writeBooleanAttribute(out, ATTR_MULTI_PACKAGE, params.isMultiPackage);
+            // TODO(patb,109941548): avoid writing to xml and instead infer / validate this after
+            //                       we've read all sessions.
+            writeIntAttribute(out, ATTR_PARENT_SESSION_ID, mParentSessionId);
             writeIntAttribute(out, ATTR_MODE, params.mode);
             writeIntAttribute(out, ATTR_INSTALL_FLAGS, params.installFlags);
             writeIntAttribute(out, ATTR_INSTALL_LOCATION, params.installLocation);
@@ -1707,6 +2063,12 @@
 
                 params.appIconLastModified = appIconFile.lastModified();
             }
+            final int[] childSessionIds = getChildSessionIds();
+            for (int childSessionId : childSessionIds) {
+                out.startTag(null, TAG_CHILD_SESSION);
+                writeIntAttribute(out, ATTR_SESSION_ID, childSessionId);
+                out.endTag(null, TAG_CHILD_SESSION);
+            }
         }
 
         out.endTag(null, TAG_SESSION);
@@ -1751,11 +2113,15 @@
      * @param installerThread Thread to be used for callbacks of this session
      * @param sessionsDir The directory the sessions are stored in
      *
+     * @param sessionProvider
      * @return The newly created session
      */
+    // TODO(patb,109941548): modify readFromXml to consume to the next tag session tag so we
+    //                       can have a complete session for the constructor
     public static PackageInstallerSession readFromXml(@NonNull XmlPullParser in,
             @NonNull PackageInstallerService.InternalCallback callback, @NonNull Context context,
-            @NonNull PackageManagerService pm, Looper installerThread, @NonNull File sessionsDir)
+            @NonNull PackageManagerService pm, Looper installerThread, @NonNull File sessionsDir,
+            @NonNull PackageSessionProvider sessionProvider)
             throws IOException, XmlPullParserException {
         final int sessionId = readIntAttribute(in, ATTR_SESSION_ID);
         final int userId = readIntAttribute(in, ATTR_USER_ID);
@@ -1768,9 +2134,12 @@
         final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID);
         final boolean prepared = readBooleanAttribute(in, ATTR_PREPARED, true);
         final boolean sealed = readBooleanAttribute(in, ATTR_SEALED);
+        final int parentSessionId = readIntAttribute(in, ATTR_PARENT_SESSION_ID,
+                SessionInfo.INVALID_ID);
 
         final SessionParams params = new SessionParams(
                 SessionParams.MODE_INVALID);
+        params.isMultiPackage = readBooleanAttribute(in, ATTR_MULTI_PACKAGE, false);
         params.mode = readIntAttribute(in, ATTR_MODE);
         params.installFlags = readIntAttribute(in, ATTR_INSTALL_FLAGS);
         params.installLocation = readIntAttribute(in, ATTR_INSTALL_LOCATION);
@@ -1793,9 +2162,16 @@
             params.appIcon = BitmapFactory.decodeFile(appIconFile.getAbsolutePath());
             params.appIconLastModified = appIconFile.lastModified();
         }
-
-        return new PackageInstallerSession(callback, context, pm,
+        return new PackageInstallerSession(callback, context, pm, sessionProvider,
                 installerThread, sessionId, userId, installerPackageName, installerUid,
-                params, createdMillis, stageDir, stageCid, prepared, sealed);
+                params, createdMillis, stageDir, stageCid, prepared, sealed,
+                EMPTY_CHILD_SESSION_ARRAY, parentSessionId);
+    }
+
+    /**
+     * Reads the session ID from a child session tag stored in the provided {@link XmlPullParser}
+     */
+    static int readChildSessionIdFromXml(@NonNull XmlPullParser in) {
+        return readIntAttribute(in, ATTR_SESSION_ID, SessionInfo.INVALID_ID);
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9210d46..e4e8010 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -60,6 +60,7 @@
 import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
 import static android.content.pm.PackageManager.INSTALL_INTERNAL;
+import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
@@ -85,6 +86,11 @@
 import static android.content.pm.PackageManager.PERMISSION_DENIED;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.pm.PackageParser.isApkFile;
+import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_BASE;
+import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_MANAGER;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK;
+import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
 import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
@@ -234,7 +240,6 @@
 import android.os.storage.StorageManagerInternal;
 import android.os.storage.VolumeInfo;
 import android.os.storage.VolumeRecord;
-import android.permission.PermissionManager;
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
 import android.security.KeyStore;
@@ -366,6 +371,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiConsumer;
 import java.util.function.Predicate;
 
 /**
@@ -2090,6 +2096,28 @@
         }
     }
 
+    @GuardedBy("mPackages")
+    private void setupBuiltinSharedLibraryDependenciesLocked() {
+        // Builtin libraries don't have versions.
+        long version = SharedLibraryInfo.VERSION_UNDEFINED;
+
+        SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(ANDROID_HIDL_MANAGER, version);
+        if (libraryInfo != null) {
+            libraryInfo.addDependency(getSharedLibraryInfoLPr(ANDROID_HIDL_BASE, version));
+        }
+
+        libraryInfo = getSharedLibraryInfoLPr(ANDROID_TEST_RUNNER, version);
+        if (libraryInfo != null) {
+            libraryInfo.addDependency(getSharedLibraryInfoLPr(ANDROID_TEST_MOCK, version));
+            libraryInfo.addDependency(getSharedLibraryInfoLPr(ANDROID_TEST_BASE, version));
+        }
+
+        libraryInfo = getSharedLibraryInfoLPr(ANDROID_TEST_MOCK, version);
+        if (libraryInfo != null) {
+            libraryInfo.addDependency(getSharedLibraryInfoLPr(ANDROID_TEST_BASE, version));
+        }
+    }
+
     public PackageManagerService(Context context, Installer installer,
             boolean factoryTest, boolean onlyCore) {
         LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
@@ -2205,6 +2233,9 @@
                 addSharedLibraryLPw(path, null, name, SharedLibraryInfo.VERSION_UNDEFINED,
                         SharedLibraryInfo.TYPE_BUILTIN, PLATFORM_PACKAGE_NAME, 0);
             }
+            // Builtin libraries cannot encode their dependency where they are
+            // defined, so fix that now.
+            setupBuiltinSharedLibraryDependenciesLocked();
 
             SELinuxMMAC.readInstallPolicy();
 
@@ -2899,60 +2930,6 @@
 
             checkDefaultBrowser();
 
-            // If a granted permission is split, all new permissions should be granted too
-            if (mIsUpgrade) {
-                final int callingUid = getCallingUid();
-
-                final List<PermissionManager.SplitPermissionInfo> splitPermissions =
-                        mContext.getSystemService(PermissionManager.class).getSplitPermissions();
-                final int numSplitPerms = splitPermissions.size();
-                for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
-                    final PermissionManager.SplitPermissionInfo splitPerm =
-                            splitPermissions.get(splitPermNum);
-                    final String rootPerm = splitPerm.getSplitPermission();
-
-                    if (preUpgradeSdkVersion >= splitPerm.getTargetSdk()) {
-                        continue;
-                    }
-
-                    final int numPackages = mPackages.size();
-                    for (int packageNum = 0; packageNum < numPackages; packageNum++) {
-                        final PackageParser.Package pkg = mPackages.valueAt(packageNum);
-
-                        if (pkg.applicationInfo.targetSdkVersion >= splitPerm.getTargetSdk()
-                                || !pkg.requestedPermissions.contains(rootPerm)) {
-                            continue;
-                        }
-
-                        final int userId = UserHandle.getUserId(pkg.applicationInfo.uid);
-                        final String pkgName = pkg.packageName;
-
-                        if (checkPermission(rootPerm, pkgName, userId) == PERMISSION_DENIED) {
-                            continue;
-                        }
-
-                        final List<String> newPerms = splitPerm.getNewPermissions();
-
-                        final int numNewPerms = newPerms.size();
-                        for (int newPermNum = 0; newPermNum < numNewPerms; newPermNum++) {
-                            final String newPerm = newPerms.get(newPermNum);
-                            if (checkPermission(newPerm, pkgName, userId) == PERMISSION_GRANTED) {
-                                continue;
-                            }
-
-                            if (DEBUG_PERMISSIONS) {
-                                Slog.v(TAG, "Granting " + newPerm + " to " + pkgName
-                                        + " as the root permission " + rootPerm
-                                        + " is already granted");
-                            }
-
-                            mPermissionManager.grantRuntimePermission(newPerm, pkgName, true,
-                                    callingUid, userId, null);
-                        }
-                    }
-                }
-            }
-
             // clear only after permissions and other defaults have been updated
             mExistingSystemPackages.clear();
             mPromoteSystemApps = false;
@@ -3226,9 +3203,8 @@
         }
 
         // The base directory for the package parser cache lives under /data/system/.
-        final File cacheBaseDir = FileUtils.createDir(Environment.getDataSystemDirectory(),
-                "package_cache");
-        if (cacheBaseDir == null) {
+        final File cacheBaseDir = Environment.getPackageCacheDirectory();
+        if (!FileUtils.createDir(cacheBaseDir)) {
             return null;
         }
 
@@ -4867,7 +4843,10 @@
                     SharedLibraryInfo resLibInfo = new SharedLibraryInfo(libInfo.getPath(),
                             libInfo.getPackageName(), libInfo.getName(), libInfo.getLongVersion(),
                             libInfo.getType(), libInfo.getDeclaringPackage(),
-                            getPackagesUsingSharedLibraryLPr(libInfo, flags, userId));
+                            getPackagesUsingSharedLibraryLPr(libInfo, flags, userId),
+                            (libInfo.getDependencies() == null
+                                    ? null
+                                    : new ArrayList(libInfo.getDependencies())));
 
                     if (result == null) {
                         result = new ArrayList<>();
@@ -9329,7 +9308,7 @@
         }
     }
 
-    private SharedLibraryInfo getSharedLibraryInfoLPr(String name, long version) {
+    private @Nullable SharedLibraryInfo getSharedLibraryInfoLPr(String name, long version) {
         LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
         if (versionedLib == null) {
             return null;
@@ -9598,16 +9577,44 @@
     }
 
     @GuardedBy("mPackages")
-    private void addSharedLibraryLPr(Set<String> usesLibraryFiles,
-            SharedLibraryInfo file,
-            PackageParser.Package changingLib) {
+    private void applyDefiningSharedLibraryUpdateLocked(
+            PackageParser.Package pkg, SharedLibraryInfo libInfo,
+            BiConsumer<SharedLibraryInfo, SharedLibraryInfo> action) {
+        // Note that libraries defined by this package may be null if:
+        // - Package manager was unable to create the shared library. The package still
+        //   gets installed, but the shared library does not get created.
+        // Or:
+        // - Package manager is in a state where package isn't scanned yet. This will
+        //   get called again after scanning to fix the dependencies.
+        if (pkg.isLibrary()) {
+            if (pkg.staticSharedLibName != null) {
+                SharedLibraryInfo definedLibrary = getSharedLibraryInfoLPr(
+                        pkg.staticSharedLibName, pkg.staticSharedLibVersion);
+                if (definedLibrary != null) {
+                    action.accept(definedLibrary, libInfo);
+                }
+            } else {
+                for (String libraryName : pkg.libraryNames) {
+                    SharedLibraryInfo definedLibrary = getSharedLibraryInfoLPr(
+                            libraryName, SharedLibraryInfo.VERSION_UNDEFINED);
+                    if (definedLibrary != null) {
+                        action.accept(definedLibrary, libInfo);
+                    }
+                }
+            }
+        }
+    }
 
-        if (file.getPath() != null) {
-            usesLibraryFiles.add(file.getPath());
+    @GuardedBy("mPackages")
+    private void addSharedLibraryLPr(PackageParser.Package pkg, Set<String> usesLibraryFiles,
+            SharedLibraryInfo libInfo, PackageParser.Package changingLib) {
+
+        if (libInfo.getPath() != null) {
+            usesLibraryFiles.add(libInfo.getPath());
             return;
         }
-        PackageParser.Package p = mPackages.get(file.getPackageName());
-        if (changingLib != null && changingLib.packageName.equals(file.getPackageName())) {
+        PackageParser.Package p = mPackages.get(libInfo.getPackageName());
+        if (changingLib != null && changingLib.packageName.equals(libInfo.getPackageName())) {
             // If we are doing this while in the middle of updating a library apk,
             // then we need to make sure to use that new apk for determining the
             // dependencies here.  (We haven't yet finished committing the new apk
@@ -9618,6 +9625,10 @@
         }
         if (p != null) {
             usesLibraryFiles.addAll(p.getAllCodePaths());
+            // If the package provides libraries, add the dependency to them.
+            applyDefiningSharedLibraryUpdateLocked(pkg, libInfo, (definingLibrary, dependency) -> {
+                definingLibrary.addDependency(dependency);
+            });
             if (p.usesLibraryFiles != null) {
                 Collections.addAll(usesLibraryFiles, p.usesLibraryFiles);
             }
@@ -9630,6 +9641,12 @@
         if (pkg == null) {
             return;
         }
+
+        // If the package provides libraries, clear their old dependencies.
+        // This method will set them up again.
+        applyDefiningSharedLibraryUpdateLocked(pkg, null, (definingLibrary, dependency) -> {
+            definingLibrary.clearDependencies();
+        });
         // The collection used here must maintain the order of addition (so
         // that libraries are searched in the correct order) and must have no
         // duplicates.
@@ -9656,7 +9673,7 @@
             // usesLibraryFiles while eliminating duplicates.
             Set<String> usesLibraryFiles = new LinkedHashSet<>();
             for (SharedLibraryInfo libInfo : usesLibraryInfos) {
-                addSharedLibraryLPr(usesLibraryFiles, libInfo, changingLib);
+                addSharedLibraryLPr(pkg, usesLibraryFiles, libInfo, changingLib);
             }
             pkg.usesLibraryFiles = usesLibraryFiles.toArray(new String[usesLibraryFiles.size()]);
         } else {
@@ -11201,7 +11218,7 @@
         }
         SharedLibraryInfo libraryInfo = new SharedLibraryInfo(path, apk, name,
                 version, type, new VersionedPackage(declaringPackageName, declaringVersionCode),
-                null);
+                null, null);
         versionedLib.put(version, libraryInfo);
         return true;
     }
@@ -12067,8 +12084,7 @@
     void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
         mComponentResolver.removeAllComponents(pkg, chatty);
 
-        final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
-        mPermissionManager.removeAllPermissions(pkg, allPackageNames, mPermissionCallback, chatty);
+        mPermissionManager.removeAllPermissions(pkg, chatty);
 
         final int instrumentationSize = pkg.instrumentation.size();
         StringBuilder r = null;
@@ -12296,28 +12312,15 @@
         return installReason;
     }
 
-    void installStage(String packageName, File stagedDir,
-            IPackageInstallObserver2 observer, PackageInstaller.SessionParams sessionParams,
-            String installerPackageName, int installerUid, UserHandle user,
-            PackageParser.SigningDetails signingDetails) {
+    void installStage(ActiveInstallSession activeInstallSession) {
         if (DEBUG_INSTANT) {
-            if ((sessionParams.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
-                Slog.d(TAG, "Ephemeral install of " + packageName);
+            if ((activeInstallSession.getSessionParams().installFlags
+                    & PackageManager.INSTALL_INSTANT_APP) != 0) {
+                Slog.d(TAG, "Ephemeral install of " + activeInstallSession.getPackageName());
             }
         }
-        final VerificationInfo verificationInfo = new VerificationInfo(
-                sessionParams.originatingUri, sessionParams.referrerUri,
-                sessionParams.originatingUid, installerUid);
-
-        final OriginInfo origin = OriginInfo.fromStagedFile(stagedDir);
-
         final Message msg = mHandler.obtainMessage(INIT_COPY);
-        final int installReason = fixUpInstallReason(installerPackageName, installerUid,
-                sessionParams.installReason);
-        final InstallParams params = new InstallParams(origin, null, observer,
-                sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
-                verificationInfo, user, sessionParams.abiOverride,
-                sessionParams.grantedRuntimePermissions, signingDetails, installReason);
+        final InstallParams params = new InstallParams(activeInstallSession);
         params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
         msg.obj = params;
 
@@ -12329,6 +12332,22 @@
         mHandler.sendMessage(msg);
     }
 
+    void installStage(List<ActiveInstallSession> children)
+            throws PackageManagerException {
+        final Message msg = mHandler.obtainMessage(INIT_COPY);
+        final MultiPackageInstallParams params =
+                new MultiPackageInstallParams(UserHandle.ALL, children);
+        params.setTraceMethod("installStageMultiPackage")
+                .setTraceCookie(System.identityHashCode(params));
+        msg.obj = params;
+
+        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStageMultiPackage",
+                System.identityHashCode(msg.obj));
+        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
+                System.identityHashCode(msg.obj));
+        mHandler.sendMessage(msg);
+    }
+
     private void sendPackageAddedForUser(String packageName, PackageSetting pkgSetting,
             int userId) {
         final boolean isSystem = isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
@@ -12918,6 +12937,25 @@
         }
     }
 
+    @Override
+    public boolean canSuspendPackageForUser(String packageName, int userId) {
+        mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS,
+                "canSuspendPackageForUser");
+        final int callingUid = Binder.getCallingUid();
+        if (UserHandle.getUserId(callingUid) != userId) {
+            throw new SecurityException("Calling uid " + callingUid
+                    + " cannot query canSuspendPackageForUser for user " + userId);
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            synchronized (mPackages) {
+                return canSuspendPackageForUserLocked(packageName, userId);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     @GuardedBy("mPackages")
     private boolean canSuspendPackageForUserLocked(String packageName, int userId) {
         if (isPackageDeviceAdmin(packageName, userId)) {
@@ -12981,7 +13019,7 @@
         }
 
         if (PLATFORM_PACKAGE_NAME.equals(packageName)) {
-            Slog.w(TAG, "Cannot suspend package: " + packageName);
+            Slog.w(TAG, "Cannot suspend the platform package: " + packageName);
             return false;
         }
 
@@ -13506,88 +13544,113 @@
     }
 
     private void processPendingInstall(final InstallArgs args, final int currentStatus) {
-        // Queue up an async operation since the package installation may take a little while.
-        mHandler.post(new Runnable() {
-            public void run() {
-                mHandler.removeCallbacks(this);
-                 // Result object to be returned
-                PackageInstalledInfo res = new PackageInstalledInfo();
-                res.setReturnCode(currentStatus);
-                res.uid = -1;
-                res.pkg = null;
-                res.removedInfo = null;
-                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
-                    args.doPreInstall(res.returnCode);
-                    synchronized (mInstallLock) {
-                        installPackageTracedLI(args, res);
-                    }
-                    args.doPostInstall(res.returnCode, res.uid);
+        if (args.mMultiPackageInstallParams != null) {
+            args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus);
+        } else {
+            PackageInstalledInfo res = createPackageInstalledInfo(currentStatus);
+            processInstallRequestsAsync(
+                    res.returnCode == PackageManager.INSTALL_SUCCEEDED,
+                    Collections.singletonList(new InstallRequest(args, res)));
+        }
+    }
+
+    // Queue up an async operation since the package installation may take a little while.
+    private void processInstallRequestsAsync(boolean success,
+            List<InstallRequest> installRequests) {
+        mHandler.post(() -> {
+            if (success) {
+                for (InstallRequest request : installRequests) {
+                    request.args.doPreInstall(request.installResult.returnCode);
                 }
-
-                // A restore should be performed at this point if (a) the install
-                // succeeded, (b) the operation is not an update, and (c) the new
-                // package has not opted out of backup participation.
-                final boolean update = res.removedInfo != null
-                        && res.removedInfo.removedPackage != null;
-                final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags;
-                boolean doRestore = !update
-                        && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);
-
-                // Set up the post-install work request bookkeeping.  This will be used
-                // and cleaned up by the post-install event handling regardless of whether
-                // there's a restore pass performed.  Token values are >= 1.
-                int token;
-                if (mNextInstallToken < 0) mNextInstallToken = 1;
-                token = mNextInstallToken++;
-
-                PostInstallData data = new PostInstallData(args, res);
-                mRunningInstalls.put(token, data);
-                if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
-
-                if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
-                    // Pass responsibility to the Backup Manager.  It will perform a
-                    // restore if appropriate, then pass responsibility back to the
-                    // Package Manager to run the post-install observer callbacks
-                    // and broadcasts.
-                    IBackupManager bm = IBackupManager.Stub.asInterface(
-                            ServiceManager.getService(Context.BACKUP_SERVICE));
-                    if (bm != null) {
-                        if (DEBUG_INSTALL) Log.v(TAG, "token " + token
-                                + " to BM for possible restore");
-                        Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
-                        try {
-                            // TODO: http://b/22388012
-                            if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
-                                bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
-                            } else {
-                                doRestore = false;
-                            }
-                        } catch (RemoteException e) {
-                            // can't happen; the backup manager is local
-                        } catch (Exception e) {
-                            Slog.e(TAG, "Exception trying to enqueue restore", e);
-                            doRestore = false;
-                        }
-                    } else {
-                        Slog.e(TAG, "Backup Manager not found!");
-                        doRestore = false;
-                    }
+                synchronized (mInstallLock) {
+                    installPackagesTracedLI(installRequests);
                 }
-
-                if (!doRestore) {
-                    // No restore possible, or the Backup Manager was mysteriously not
-                    // available -- just fire the post-install work request directly.
-                    if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
-
-                    Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
-
-                    Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
-                    mHandler.sendMessage(msg);
+                for (InstallRequest request : installRequests) {
+                    request.args.doPostInstall(
+                            request.installResult.returnCode, request.installResult.uid);
                 }
             }
+            for (InstallRequest request : installRequests) {
+                resolvePackageInstalledInfo(request.args,
+                        request.installResult);
+            }
         });
     }
 
+    private PackageInstalledInfo createPackageInstalledInfo(
+            int currentStatus) {
+        PackageInstalledInfo res = new PackageInstalledInfo();
+        res.setReturnCode(currentStatus);
+        res.uid = -1;
+        res.pkg = null;
+        res.removedInfo = null;
+        return res;
+    }
+
+    private void resolvePackageInstalledInfo(InstallArgs args, PackageInstalledInfo res) {
+        // A restore should be performed at this point if (a) the install
+        // succeeded, (b) the operation is not an update, and (c) the new
+        // package has not opted out of backup participation.
+        final boolean update = res.removedInfo != null
+                && res.removedInfo.removedPackage != null;
+        final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags;
+        boolean doRestore = !update
+                && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);
+
+        // Set up the post-install work request bookkeeping.  This will be used
+        // and cleaned up by the post-install event handling regardless of whether
+        // there's a restore pass performed.  Token values are >= 1.
+        int token;
+        if (mNextInstallToken < 0) mNextInstallToken = 1;
+        token = mNextInstallToken++;
+
+        PostInstallData data = new PostInstallData(args, res);
+        mRunningInstalls.put(token, data);
+        if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token);
+
+        if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) {
+            // Pass responsibility to the Backup Manager.  It will perform a
+            // restore if appropriate, then pass responsibility back to the
+            // Package Manager to run the post-install observer callbacks
+            // and broadcasts.
+            IBackupManager bm = IBackupManager.Stub.asInterface(
+                    ServiceManager.getService(Context.BACKUP_SERVICE));
+            if (bm != null) {
+                if (DEBUG_INSTALL) {
+                    Log.v(TAG, "token " + token + " to BM for possible restore");
+                }
+                Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "restore", token);
+                try {
+                    // TODO: http://b/22388012
+                    if (bm.isBackupServiceActive(UserHandle.USER_SYSTEM)) {
+                        bm.restoreAtInstall(res.pkg.applicationInfo.packageName, token);
+                    } else {
+                        doRestore = false;
+                    }
+                } catch (RemoteException e) {
+                    // can't happen; the backup manager is local
+                } catch (Exception e) {
+                    Slog.e(TAG, "Exception trying to enqueue restore", e);
+                    doRestore = false;
+                }
+            } else {
+                Slog.e(TAG, "Backup Manager not found!");
+                doRestore = false;
+            }
+        }
+
+        if (!doRestore) {
+            // No restore possible, or the Backup Manager was mysteriously not
+            // available -- just fire the post-install work request directly.
+            if (DEBUG_INSTALL) Log.v(TAG, "No restore - queue post-install for " + token);
+
+            Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "postInstall", token);
+
+            Message msg = mHandler.obtainMessage(POST_INSTALL, token, 0);
+            mHandler.sendMessage(msg);
+        }
+    }
+
     /**
      * Callback from PackageSettings whenever an app is first transitioned out of the
      * 'stopped' state.  Normally we just issue the broadcast, but we can't do that if
@@ -13775,7 +13838,83 @@
         }
     }
 
+    /**
+     * Container for a multi-package install which refers to all install sessions and args being
+     * committed together.
+     */
+    class MultiPackageInstallParams extends HandlerParams {
+
+        private int mRet = INSTALL_SUCCEEDED;
+        @NonNull
+        private final ArrayList<InstallParams> mChildParams;
+        @NonNull
+        private final Map<InstallArgs, Integer> mVerifiedState;
+
+        MultiPackageInstallParams(
+                @NonNull UserHandle user,
+                @NonNull List<ActiveInstallSession> activeInstallSessions)
+                throws PackageManagerException {
+            super(user);
+            if (activeInstallSessions.size() == 0) {
+                throw new PackageManagerException("No child sessions found!");
+            }
+            mChildParams = new ArrayList<>(activeInstallSessions.size());
+            for (int i = 0; i < activeInstallSessions.size(); i++) {
+                final InstallParams childParams = new InstallParams(activeInstallSessions.get(i));
+                childParams.mParentInstallParams = this;
+                this.mChildParams.add(childParams);
+            }
+            this.mVerifiedState = new ArrayMap<>(mChildParams.size());
+        }
+
+        @Override
+        void handleStartCopy() {
+            for (InstallParams params : mChildParams) {
+                params.handleStartCopy();
+                if (params.mRet != INSTALL_SUCCEEDED) {
+                    mRet = params.mRet;
+                    break;
+                }
+            }
+        }
+
+        @Override
+        void handleReturnCode() {
+            for (InstallParams params : mChildParams) {
+                params.handleReturnCode();
+                if (params.mRet != INSTALL_SUCCEEDED) {
+                    mRet = params.mRet;
+                    break;
+                }
+            }
+        }
+
+        void tryProcessInstallRequest(InstallArgs args, int currentStatus) {
+            mVerifiedState.put(args, currentStatus);
+            boolean success = true;
+            if (mVerifiedState.size() != mChildParams.size()) {
+                return;
+            }
+            for (Integer status : mVerifiedState.values()) {
+                if (status == PackageManager.INSTALL_UNKNOWN) {
+                    return;
+                } else if (status != PackageManager.INSTALL_SUCCEEDED) {
+                    success = false;
+                    break;
+                }
+            }
+            final List<InstallRequest> installRequests = new ArrayList<>(mVerifiedState.size());
+            for (Map.Entry<InstallArgs, Integer> entry : mVerifiedState.entrySet()) {
+                installRequests.add(new InstallRequest(entry.getKey(),
+                        createPackageInstalledInfo(entry.getValue())));
+            }
+            processInstallRequestsAsync(success, installRequests);
+        }
+    }
+
     class InstallParams extends HandlerParams {
+        // TODO: see if we can collapse this into ActiveInstallSession
+
         final OriginInfo origin;
         final MoveInfo move;
         final IPackageInstallObserver2 observer;
@@ -13783,17 +13922,20 @@
         final String installerPackageName;
         final String volumeUuid;
         private InstallArgs mArgs;
-        private int mRet;
+        int mRet;
         final String packageAbiOverride;
         final String[] grantedRuntimePermissions;
         final VerificationInfo verificationInfo;
         final PackageParser.SigningDetails signingDetails;
         final int installReason;
+        @Nullable
+        MultiPackageInstallParams mParentInstallParams;
 
         InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
                 int installFlags, String installerPackageName, String volumeUuid,
                 VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
-                String[] grantedPermissions, PackageParser.SigningDetails signingDetails, int installReason) {
+                String[] grantedPermissions, PackageParser.SigningDetails signingDetails,
+                int installReason) {
             super(user);
             this.origin = origin;
             this.move = move;
@@ -13808,6 +13950,34 @@
             this.installReason = installReason;
         }
 
+        InstallParams(ActiveInstallSession activeInstallSession) {
+            super(activeInstallSession.getUser());
+            if (DEBUG_INSTANT) {
+                if ((activeInstallSession.getSessionParams().installFlags
+                        & PackageManager.INSTALL_INSTANT_APP) != 0) {
+                    Slog.d(TAG, "Ephemeral install of " + activeInstallSession.getPackageName());
+                }
+            }
+            verificationInfo = new VerificationInfo(
+                    activeInstallSession.getSessionParams().originatingUri,
+                    activeInstallSession.getSessionParams().referrerUri,
+                    activeInstallSession.getSessionParams().originatingUid,
+                    activeInstallSession.getInstallerUid());
+            origin = OriginInfo.fromStagedFile(activeInstallSession.getStagedDir());
+            move = null;
+            installReason = fixUpInstallReason(activeInstallSession.getInstallerPackageName(),
+                    activeInstallSession.getInstallerUid(),
+                    activeInstallSession.getSessionParams().installReason);
+            observer = activeInstallSession.getObserver();
+            installFlags = activeInstallSession.getSessionParams().installFlags;
+            installerPackageName = activeInstallSession.getInstallerPackageName();
+            volumeUuid = activeInstallSession.getSessionParams().volumeUuid;
+            packageAbiOverride = activeInstallSession.getSessionParams().abiOverride;
+            grantedRuntimePermissions =
+                    activeInstallSession.getSessionParams().grantedRuntimePermissions;
+            signingDetails = activeInstallSession.getSigningDetails();
+        }
+
         @Override
         public String toString() {
             return "InstallParams{" + Integer.toHexString(System.identityHashCode(this))
@@ -14229,6 +14399,7 @@
         final int traceCookie;
         final PackageParser.SigningDetails signingDetails;
         final int installReason;
+        @Nullable final MultiPackageInstallParams mMultiPackageInstallParams;
 
         // The list of instruction sets supported by this app. This is currently
         // only used during the rmdex() phase to clean up resources. We can get rid of this
@@ -14239,8 +14410,9 @@
                 int installFlags, String installerPackageName, String volumeUuid,
                 UserHandle user, String[] instructionSets,
                 String abiOverride, String[] installGrantPermissions,
-                String traceMethod, int traceCookie, PackageParser.SigningDetails signingDetails,
-                int installReason) {
+                String traceMethod, int traceCookie, SigningDetails signingDetails,
+                int installReason,
+                MultiPackageInstallParams multiPackageInstallParams) {
             this.origin = origin;
             this.move = move;
             this.installFlags = installFlags;
@@ -14255,6 +14427,7 @@
             this.traceCookie = traceCookie;
             this.signingDetails = signingDetails;
             this.installReason = installReason;
+            this.mMultiPackageInstallParams = multiPackageInstallParams;
         }
 
         abstract int copyApk();
@@ -14350,7 +14523,7 @@
                     params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
                     params.grantedRuntimePermissions,
                     params.traceMethod, params.traceCookie, params.signingDetails,
-                    params.installReason);
+                    params.installReason, params.mParentInstallParams);
             if (isFwdLocked()) {
                 throw new IllegalArgumentException("Forward locking only supported in ASEC");
             }
@@ -14360,7 +14533,7 @@
         FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
             super(OriginInfo.fromNothing(), null, null, 0, null, null, null, instructionSets,
                     null, null, null, 0, PackageParser.SigningDetails.UNKNOWN,
-                    PackageManager.INSTALL_REASON_UNKNOWN);
+                    PackageManager.INSTALL_REASON_UNKNOWN, null /* parent */);
             this.codeFile = (codePath != null) ? new File(codePath) : null;
             this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
         }
@@ -14552,7 +14725,7 @@
                     params.getUser(), null /* instruction sets */, params.packageAbiOverride,
                     params.grantedRuntimePermissions,
                     params.traceMethod, params.traceCookie, params.signingDetails,
-                    params.installReason);
+                    params.installReason, params.mParentInstallParams);
         }
 
         int copyApk() {
@@ -14957,10 +15130,10 @@
     }
 
     @GuardedBy({"mInstallLock", "mPackages"})
-    private void installPackageTracedLI(InstallArgs args, PackageInstalledInfo installResult) {
+    private void installPackagesTracedLI(List<InstallRequest> requests) {
         try {
-            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackage");
-            installPackagesLI(Collections.singletonList(new InstallRequest(args, installResult)));
+            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackages");
+            installPackagesLI(requests);
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
@@ -15153,14 +15326,8 @@
                             pkgList.add(oldPackage.applicationInfo.packageName);
                             sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
                         }
-
-                        clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE
-                                | StorageManager.FLAG_STORAGE_CE
-                                | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                     }
 
-
-
                     // Update the in-memory copy of the previous code paths.
                     PackageSetting ps1 = mSettings.mPackages.get(
                             reconciledPkg.prepareResult.existingPackage.packageName);
@@ -15306,7 +15473,7 @@
                             request.installResult.setError(
                                     PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE,
                                     "Duplicate package " + result.pkgSetting.pkg.packageName
-                                            + " in atomic install request.");
+                                            + " in multi-package install request.");
                             return;
                         }
                     }
@@ -15364,7 +15531,8 @@
 
     /**
      * On successful install, executes remaining steps after commit completes and the package lock
-     * is released.
+     * is released. These are typically more expensive or require calls to installd, which often
+     * locks on {@link #mPackages}.
      */
     private void executePostCommitSteps(CommitRequest commitRequest) {
         for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
@@ -16093,7 +16261,6 @@
         try {
             final PackageParser.Package existingPackage;
             String renamedPackage = null;
-            boolean clearCodeCache = false;
             boolean sysPkg = false;
             String targetVolumeUuid = volumeUuid;
             int targetScanFlags = scanFlags;
@@ -16199,17 +16366,6 @@
                                         + oldPackage.mSharedUserId);
                     }
 
-                    // check if the new package supports all of the abis which the old package
-                    // supports
-                    boolean oldPkgSupportMultiArch =
-                            oldPackage.applicationInfo.secondaryCpuAbi != null;
-                    boolean newPkgSupportMultiArch = pkg.applicationInfo.secondaryCpuAbi != null;
-                    if (isSystemApp(oldPackage) && oldPkgSupportMultiArch
-                            && !newPkgSupportMultiArch) {
-                        throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
-                                "Update to package " + pkgName11 + " doesn't support multi arch");
-                    }
-
                     // In case of rollback, remember per-user/profile install state
                     allUsers = sUserManager.getUserIds();
                     installedUsers = ps.queryInstalledUsers(allUsers, true);
@@ -16314,7 +16470,6 @@
                         Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
                                 + ", old=" + oldPackage);
                     }
-                    clearCodeCache = true;
                     res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
                     pkg.setApplicationInfoFlags(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP,
                             ApplicationInfo.FLAG_UPDATED_SYSTEM_APP);
@@ -16370,7 +16525,7 @@
             shouldCloseFreezerBeforeReturn = false;
             return new PrepareResult(args.installReason, targetVolumeUuid, installerPackageName,
                     args.user, replace, targetScanFlags, targetParseFlags, existingPackage, pkg,
-                    clearCodeCache, sysPkg, renamedPackage, freezer);
+                    replace /* clearCodeCache */, sysPkg, renamedPackage, freezer);
         } finally {
             if (shouldCloseFreezerBeforeReturn) {
                 freezer.close();
@@ -17637,30 +17792,58 @@
         return true;
     }
 
+    private static class DeletePackageAction {
+        public final PackageSetting deletingPs;
+
+        private DeletePackageAction(PackageSetting deletingPs) {
+            this.deletingPs = deletingPs;
+        }
+    }
+
+    /**
+     * @return a {@link DeletePackageAction} if the provided package may be deleted, {@code null}
+     * otherwise.
+     */
+    @Nullable
+    private DeletePackageAction mayDeletePackageLIF(@NonNull String packageName) {
+        synchronized (mPackages) {
+            final PackageSetting ps;
+            ps = mSettings.mPackages.get(packageName);
+            if (ps == null) {
+                return null;
+            }
+            return new DeletePackageAction(ps);
+        }
+    }
+
     /*
      * This method handles package deletion in general
      */
-    private boolean deletePackageLIF(String packageName, UserHandle user,
+    private boolean deletePackageLIF(@NonNull String packageName, UserHandle user,
             boolean deleteCodeAndResources, int[] allUserHandles, int flags,
             PackageRemovedInfo outInfo, boolean writeSettings,
             PackageParser.Package replacingPackage) {
-        if (packageName == null) {
-            Slog.w(TAG, "Attempt to delete null packageName.");
+        final DeletePackageAction action = mayDeletePackageLIF(packageName);
+        if (null == action) {
             return false;
         }
 
         if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user);
 
-        PackageSetting ps;
-        synchronized (mPackages) {
-            ps = mSettings.mPackages.get(packageName);
-            if (ps == null) {
-                Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
-                return false;
-            }
+        return executeDeletePackageLIF(action, packageName, user, deleteCodeAndResources,
+                allUserHandles, flags, outInfo, writeSettings, replacingPackage);
+    }
 
-            if (ps.parentPackageName != null && (!isSystemApp(ps)
-                    || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
+    private boolean executeDeletePackageLIF(DeletePackageAction action,
+            String packageName, UserHandle user, boolean deleteCodeAndResources,
+            int[] allUserHandles, int flags, PackageRemovedInfo outInfo,
+            boolean writeSettings, PackageParser.Package replacingPackage) {
+        final PackageSetting ps = action.deletingPs;
+        final boolean systemApp = isSystemApp(ps);
+        synchronized (mPackages) {
+
+            if (ps.parentPackageName != null
+                    && (!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) {
                 if (DEBUG_REMOVE) {
                     Slog.d(TAG, "Uninstalled child package:" + packageName + " for user:"
                             + ((user == null) ? UserHandle.USER_ALL : user));
@@ -17668,9 +17851,7 @@
                 final int removedUserId = (user != null) ? user.getIdentifier()
                         : UserHandle.USER_ALL;
 
-                if (!clearPackageStateForUserLIF(ps, removedUserId, outInfo)) {
-                    return false;
-                }
+                clearPackageStateForUserLIF(ps, removedUserId, outInfo);
                 markPackageUninstalledForUserLPw(ps, user);
                 scheduleWritePackageRestrictionsLocked(user);
                 return true;
@@ -17683,7 +17864,7 @@
         }
 
 
-        if (((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
+        if (((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
                 && user.getIdentifier() != UserHandle.USER_ALL)) {
             // The caller is asking that the package only be deleted for a single
             // user.  To do this, we just mark its uninstalled state and delete
@@ -17692,7 +17873,7 @@
             // semantics than normal for uninstalling system apps.
             markPackageUninstalledForUserLPw(ps, user);
 
-            if (!isSystemApp(ps)) {
+            if (!systemApp) {
                 // Do not uninstall the APK if an app should be cached
                 boolean keepUninstalledPackage = shouldKeepUninstalledPackageLPr(packageName);
                 if (ps.isAnyInstalled(sUserManager.getUserIds()) || keepUninstalledPackage) {
@@ -17700,9 +17881,7 @@
                     // we need to do is clear this user's data and save that
                     // it is uninstalled.
                     if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
-                    if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
-                        return false;
-                    }
+                    clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo);
                     scheduleWritePackageRestrictionsLocked(user);
                     return true;
                 } else {
@@ -17718,9 +17897,7 @@
                 // we need to do is clear this user's data and save that
                 // it is uninstalled.
                 if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
-                if (!clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo)) {
-                    return false;
-                }
+                clearPackageStateForUserLIF(ps, user.getIdentifier(), outInfo);
                 scheduleWritePackageRestrictionsLocked(user);
                 return true;
             }
@@ -17746,8 +17923,9 @@
             }
         }
 
-        boolean ret = false;
-        if (isSystemApp(ps)) {
+        // TODO(b/109941548): break reasons for ret = false out into mayDelete method
+        final boolean ret;
+        if (systemApp) {
             if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package: " + ps.name);
             // When an updated system application is deleted we delete the existing resources
             // as well and fall back to existing code in system partition
@@ -17776,7 +17954,7 @@
             // If we uninstalled an update to a system app there may be some
             // child packages that appeared as they are declared in the system
             // app but were not declared in the update.
-            if (isSystemApp(ps)) {
+            if (systemApp) {
                 synchronized (mPackages) {
                     PackageSetting updatedPs = mSettings.getPackageLPr(ps.name);
                     final int childCount = (updatedPs.childPackageNames != null)
@@ -17837,7 +18015,7 @@
         mSettings.writeKernelMappingLPr(ps);
     }
 
-    private boolean clearPackageStateForUserLIF(PackageSetting ps, int userId,
+    private void clearPackageStateForUserLIF(PackageSetting ps, int userId,
             PackageRemovedInfo outInfo) {
         final PackageParser.Package pkg;
         synchronized (mPackages) {
@@ -17873,8 +18051,6 @@
             outInfo.removedUsers = userIds;
             outInfo.broadcastUsers = userIds;
         }
-
-        return true;
     }
 
     @Override
@@ -23379,6 +23555,62 @@
 
         return mProtectedPackages.isPackageStateProtected(userId, packageName);
     }
+
+    static class ActiveInstallSession {
+        private final String mPackageName;
+        private final File mStagedDir;
+        private final IPackageInstallObserver2 mObserver;
+        private final PackageInstaller.SessionParams mSessionParams;
+        private final String mInstallerPackageName;
+        private final int mInstallerUid;
+        private final UserHandle mUser;
+        private final SigningDetails mSigningDetails;
+
+        ActiveInstallSession(String packageName, File stagedDir, IPackageInstallObserver2 observer,
+                PackageInstaller.SessionParams sessionParams, String installerPackageName,
+                int installerUid, UserHandle user, SigningDetails signingDetails) {
+            mPackageName = packageName;
+            mStagedDir = stagedDir;
+            mObserver = observer;
+            mSessionParams = sessionParams;
+            mInstallerPackageName = installerPackageName;
+            mInstallerUid = installerUid;
+            mUser = user;
+            mSigningDetails = signingDetails;
+        }
+
+        public String getPackageName() {
+            return mPackageName;
+        }
+
+        public File getStagedDir() {
+            return mStagedDir;
+        }
+
+        public IPackageInstallObserver2 getObserver() {
+            return mObserver;
+        }
+
+        public PackageInstaller.SessionParams getSessionParams() {
+            return mSessionParams;
+        }
+
+        public String getInstallerPackageName() {
+            return mInstallerPackageName;
+        }
+
+        public int getInstallerUid() {
+            return mInstallerUid;
+        }
+
+        public UserHandle getUser() {
+            return mUser;
+        }
+
+        public SigningDetails getSigningDetails() {
+            return mSigningDetails;
+        }
+    }
 }
 
 interface PackageSender {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index e25cca4..31711e5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -173,6 +173,8 @@
                     return runSetInstallLocation();
                 case "get-install-location":
                     return runGetInstallLocation();
+                case "install-add-session":
+                    return runInstallAddSession();
                 case "move-package":
                     return runMovePackage();
                 case "move-primary-storage":
@@ -920,7 +922,10 @@
                 pw.println("Error: must either specify a package size or an APK file");
                 return 1;
             }
-            if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, "base.apk",
+            final boolean isApex =
+                    (params.sessionParams.installFlags & PackageManager.INSTALL_APEX) != 0;
+            String splitName = "base." + (isApex ? "apex" : "apk");
+            if (doWriteSplit(sessionId, inPath, params.sessionParams.sizeBytes, splitName,
                     false /*logSuccess*/) != PackageInstaller.STATUS_SUCCESS) {
                 return 1;
             }
@@ -980,6 +985,23 @@
         return doWriteSplit(sessionId, path, sizeBytes, splitName, true /*logSuccess*/);
     }
 
+    private int runInstallAddSession() throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        final int parentSessionId = Integer.parseInt(getNextArg());
+
+        List<Integer> otherSessionIds = new ArrayList<>();
+        String opt;
+        while ((opt = getNextArg()) != null) {
+            otherSessionIds.add(Integer.parseInt(opt));
+        }
+        if (otherSessionIds.size() == 0) {
+            pw.println("Error: At least two sessions are required.");
+            return 1;
+        }
+        return doInstallAddSession(parentSessionId, ArrayUtils.convertToIntArray(otherSessionIds),
+                true /*logSuccess*/);
+    }
+
     private int runInstallRemove() throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
 
@@ -2262,6 +2284,12 @@
                 case "--force-sdk":
                     sessionParams.installFlags |= PackageManager.INSTALL_FORCE_SDK;
                     break;
+                case "--apex":
+                    sessionParams.installFlags |= PackageManager.INSTALL_APEX;
+                    break;
+                case "--multi-package":
+                    sessionParams.setMultiPackage();
+                    break;
                 default:
                     throw new IllegalArgumentException("Unknown option " + opt);
             }
@@ -2494,6 +2522,30 @@
         }
     }
 
+    private int doInstallAddSession(int parentId, int[] sessionIds, boolean logSuccess)
+            throws RemoteException {
+        final PrintWriter pw = getOutPrintWriter();
+        PackageInstaller.Session session = null;
+        try {
+            session = new PackageInstaller.Session(
+                    mInterface.getPackageInstaller().openSession(parentId));
+            if (!session.isMultiPackage()) {
+                getErrPrintWriter().println(
+                        "Error: parent session ID is not a multi-package session");
+                return 1;
+            }
+            for (int i = 0; i < sessionIds.length; i++) {
+                session.addChildSessionId(sessionIds[i]);
+            }
+            if (logSuccess) {
+                pw.println("Success");
+            }
+            return 0;
+        } finally {
+            IoUtils.closeQuietly(session);
+        }
+    }
+
     private int doRemoveSplit(int sessionId, String splitName, boolean logSuccess)
             throws RemoteException {
         final PrintWriter pw = getOutPrintWriter();
@@ -2515,24 +2567,26 @@
         }
     }
 
-    private int doCommitSession(int sessionId, boolean logSuccess) throws RemoteException {
+    private int doCommitSession(int sessionId, boolean logSuccess)
+            throws RemoteException {
+
         final PrintWriter pw = getOutPrintWriter();
         PackageInstaller.Session session = null;
         try {
             session = new PackageInstaller.Session(
                     mInterface.getPackageInstaller().openSession(sessionId));
-
-            // Sanity check that all .dm files match an apk.
-            // (The installer does not support standalone .dm files and will not process them.)
-            try {
-                DexMetadataHelper.validateDexPaths(session.getNames());
-            } catch (IllegalStateException | IOException e) {
-                pw.println("Warning [Could not validate the dex paths: " + e.getMessage() + "]");
+            if (!session.isMultiPackage()) {
+                // Sanity check that all .dm files match an apk.
+                // (The installer does not support standalone .dm files and will not process them.)
+                try {
+                    DexMetadataHelper.validateDexPaths(session.getNames());
+                } catch (IllegalStateException | IOException e) {
+                    pw.println(
+                            "Warning [Could not validate the dex paths: " + e.getMessage() + "]");
+                }
             }
-
             final LocalIntentReceiver receiver = new LocalIntentReceiver();
             session.commit(receiver.getIntentSender());
-
             final Intent result = receiver.getResult();
             final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
                     PackageInstaller.STATUS_FAILURE);
@@ -2803,6 +2857,7 @@
         pw.println("       [--referrer URI] [--abi ABI_NAME] [--force-sdk]");
         pw.println("       [--preload] [--instantapp] [--full] [--dont-kill]");
         pw.println("       [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
+        pw.println("       [--multi-package]");
         pw.println("    Like \"install\", but starts an install session.  Use \"install-write\"");
         pw.println("    to push data into the session, and \"install-commit\" to finish.");
         pw.println("");
@@ -2811,6 +2866,9 @@
         pw.println("    will be read from stdin.  Options are:");
         pw.println("      -S: size in bytes of package, required for stdin");
         pw.println("");
+        pw.println("  install-add-session MULTI_PACKAGE_SESSION_ID CHILD_SESSION_IDs");
+        pw.println("    Add one or more session IDs to a multi-package session.");
+        pw.println("");
         pw.println("  install-commit SESSION_ID");
         pw.println("    Commit the given active install session, installing the app.");
         pw.println("");
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/services/core/java/com/android/server/pm/PackageSessionProvider.java
similarity index 63%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to services/core/java/com/android/server/pm/PackageSessionProvider.java
index ede8695..af11e77 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/services/core/java/com/android/server/pm/PackageSessionProvider.java
@@ -14,8 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package com.android.server.pm;
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+/** Provides access to individual sessions managed by the install service */
+public interface PackageSessionProvider {
+
+    /**
+     * Get the sessions for the provided session IDs. Null will be returned for session IDs that
+     * do not exist.
+     */
+    PackageInstallerSession getSession(int sessionId);
+
+}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index e2818b7..6009bd3 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -20,6 +20,7 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
@@ -256,6 +257,7 @@
     private static final String ATTR_USER_SET = "set";
     private static final String ATTR_USER_FIXED = "fixed";
     private static final String ATTR_REVOKE_ON_UPGRADE = "rou";
+    private static final String ATTR_REVOKE_WHEN_REQUESTED = "rwr";
 
     // Flag mask of restored permission grants that are applied at install time
     private static final int USER_RUNTIME_GRANT_MASK =
@@ -2635,7 +2637,7 @@
         }
 
         for (final SharedUserSetting sus : mSharedUsers.values()) {
-            knownSet.remove(sus.getSandboxName());
+            knownSet.remove(sus.getStorageSandboxName());
         }
 
         // Remove any unclaimed mappings
@@ -2651,7 +2653,8 @@
     void writeKernelMappingLPr(SharedUserSetting sus) {
         if (mKernelMappingFilename == null || sus == null || sus.name == null) return;
 
-        writeKernelMappingLPr(sus.getSandboxName(), sus.userId, sus.getNotInstalledUserIds());
+        writeKernelMappingLPr(sus.getStorageSandboxName(),
+                sus.userId, sus.getNotInstalledUserIds());
     }
 
     void writeKernelMappingLPr(PackageSetting ps) {
@@ -5011,6 +5014,9 @@
                                 if ((g.grantBits&FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0) {
                                     pw.print(" revoke_on_upgrade");
                                 }
+                                if ((g.grantBits & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED) != 0) {
+                                    pw.print(" revoke_when_requested");
+                                }
                                 pw.println();
                             }
                         }
@@ -5326,6 +5332,11 @@
                                     if ((g.grantBits&FLAG_PERMISSION_REVOKE_ON_UPGRADE) != 0) {
                                         serializer.attribute(null, ATTR_REVOKE_ON_UPGRADE, "true");
                                     }
+                                    if ((g.grantBits & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED)
+                                            != 0) {
+                                        serializer.attribute(null, ATTR_REVOKE_WHEN_REQUESTED,
+                                                "true");
+                                    }
                                     serializer.endTag(null, TAG_PERMISSION_ENTRY);
                                 }
                                 serializer.endTag(null, TAG_RESTORED_RUNTIME_PERMISSIONS);
@@ -5512,6 +5523,10 @@
                         if ("true".equals(parser.getAttributeValue(null, ATTR_REVOKE_ON_UPGRADE))) {
                             permBits |= FLAG_PERMISSION_REVOKE_ON_UPGRADE;
                         }
+                        if ("true".equals(parser.getAttributeValue(null,
+                                ATTR_REVOKE_WHEN_REQUESTED))) {
+                            permBits |= FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
+                        }
 
                         if (isGranted || permBits != 0) {
                             rememberRestoredUserGrantLPr(pkgName, permName, isGranted, permBits, userId);
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 32826e5..d67144e 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -19,6 +19,7 @@
 import android.annotation.Nullable;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageParser;
+import android.os.storage.StorageManager;
 import android.service.pm.PackageServiceDumpProto;
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
@@ -166,8 +167,8 @@
         return excludedUserIds == null ? EmptyArray.INT : excludedUserIds;
     }
 
-    public String getSandboxName() {
-        return "shared:" + name;
+    public String getStorageSandboxName() {
+        return StorageManager.SHARED_SANDBOX_PREFIX + name;
     }
 
     /** Updates all fields in this shared user setting from another. */
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 392d4d8..580e4f4 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -30,10 +30,12 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings.Global;
+import android.util.Log;
 import android.util.Slog;
 import android.util.jar.StrictJarFile;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.pm.Installer;
 import com.android.server.pm.Installer.InstallerException;
@@ -74,7 +76,7 @@
     private static final String PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB_LIST =
             "pm.dexopt.priv-apps-oob-list";
 
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final Context mContext;
 
@@ -152,7 +154,7 @@
      * @param classPaths the class paths corresponding to the class loaders names from
      *     {@param classLoadersNames}. The the first element corresponds to the first class loader
      *     and so on. A classpath is represented as a list of dex files separated by
-     *     {@code File.pathSeparator}.
+     *     {@code File.pathSeparator}, or null if the class loader's classpath is not known.
      *     The dex files found in the first class path will be recorded in the usage file.
      * @param loaderIsa the ISA of the app loading the dex files
      * @param loaderUserId the user id which runs the code loading the dex files
@@ -168,7 +170,8 @@
         }
     }
 
-    private void notifyDexLoadInternal(ApplicationInfo loadingAppInfo,
+    @VisibleForTesting
+    /*package*/ void notifyDexLoadInternal(ApplicationInfo loadingAppInfo,
             List<String> classLoaderNames, List<String> classPaths, String loaderIsa,
             int loaderUserId) {
         if (classLoaderNames.size() != classPaths.size()) {
@@ -185,13 +188,29 @@
             return;
         }
 
+        // The first classpath should never be null because the first classloader
+        // should always be an instance of BaseDexClassLoader.
+        String firstClassPath = classPaths.get(0);
+        if (firstClassPath == null) {
+            return;
+        }
         // The classpath is represented as a list of dex files separated by File.pathSeparator.
-        String[] dexPathsToRegister = classPaths.get(0).split(File.pathSeparator);
+        String[] dexPathsToRegister = firstClassPath.split(File.pathSeparator);
 
         // Encode the class loader contexts for the dexPathsToRegister.
         String[] classLoaderContexts = DexoptUtils.processContextForDexLoad(
                 classLoaderNames, classPaths);
 
+        // A null classLoaderContexts means that there are unsupported class loaders in the
+        // chain.
+        if (classLoaderContexts == null) {
+            if (DEBUG) {
+                Slog.i(TAG, loadingAppInfo.packageName +
+                        " uses unsupported class loader in " + classLoaderNames);
+            }
+            return;
+        }
+
         int dexPathIndex = 0;
         for (String dexPath : dexPathsToRegister) {
             // Find the owning package name.
@@ -219,14 +238,10 @@
                 }
 
                 // Record dex file usage. If the current usage is a new pattern (e.g. new secondary,
-                // or UsedBytOtherApps), record will return true and we trigger an async write
+                // or UsedByOtherApps), record will return true and we trigger an async write
                 // to disk to make sure we don't loose the data in case of a reboot.
 
-                // A null classLoaderContexts means that there are unsupported class loaders in the
-                // chain.
-                String classLoaderContext = classLoaderContexts == null
-                        ? PackageDexUsage.UNSUPPORTED_CLASS_LOADER_CONTEXT
-                        : classLoaderContexts[dexPathIndex];
+                String classLoaderContext = classLoaderContexts[dexPathIndex];
                 if (mPackageDexUsage.record(searchResult.mOwningPackageName,
                         dexPath, loaderUserId, loaderIsa, isUsedByOtherApps, primaryOrSplit,
                         loadingAppInfo.packageName, classLoaderContext)) {
diff --git a/services/core/java/com/android/server/pm/dex/DexoptUtils.java b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
index e1310a2..d2600b5 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptUtils.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
@@ -318,7 +318,8 @@
         // is fine (they come over binder). Even if something changes we expect the sizes to be
         // very small and it shouldn't matter much.
         for (int i = 1; i < classLoadersNames.size(); i++) {
-            if (!ClassLoaderFactory.isValidClassLoaderName(classLoadersNames.get(i))) {
+            if (!ClassLoaderFactory.isValidClassLoaderName(classLoadersNames.get(i))
+                || classPaths.get(i) == null) {
                 return null;
             }
             String classpath = encodeClasspath(classPaths.get(i).split(File.pathSeparator));
diff --git a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
index 602ce3b..86f7380 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -21,6 +21,7 @@
 import android.os.Build;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FastPrintWriter;
 import com.android.server.pm.AbstractStatsBase;
 import com.android.server.pm.PackageManagerServiceUtils;
@@ -78,14 +79,16 @@
     // skip optimizations on that dex files.
     /*package*/ static final String VARIABLE_CLASS_LOADER_CONTEXT =
             "=VariableClassLoaderContext=";
-    // The marker used for unsupported class loader contexts.
-    /*package*/ static final String UNSUPPORTED_CLASS_LOADER_CONTEXT =
-            "=UnsupportedClassLoaderContext=";
     // The markers used for unknown class loader contexts. This can happen if the dex file was
     // recorded in a previous version and we didn't have a chance to update its usage.
     /*package*/ static final String UNKNOWN_CLASS_LOADER_CONTEXT =
             "=UnknownClassLoaderContext=";
 
+    // The marker used for unsupported class loader contexts (no longer written, may occur in old
+    // files so discarded on read).
+    private static final String UNSUPPORTED_CLASS_LOADER_CONTEXT =
+            "=UnsupportedClassLoaderContext=";
+
     // Map which structures the information we have on a package.
     // Maps package name to package data (which stores info about UsedByOtherApps and
     // secondary dex files.).
@@ -365,6 +368,12 @@
                 Set<String> loadingPackages = maybeReadLoadingPackages(in, version);
                 String classLoaderContext = maybeReadClassLoaderContext(in, version);
 
+                if (UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(classLoaderContext)) {
+                    // We used to record use of unsupported class loaders, but we no longer do.
+                    // Discard such entries; they will be deleted when we next write the file.
+                    continue;
+                }
+
                 int ownerUserId = Integer.parseInt(elems[0]);
                 boolean isUsedByOtherApps = readBoolean(elems[1]);
                 DexUseInfo dexUseInfo = new DexUseInfo(isUsedByOtherApps, ownerUserId,
@@ -709,13 +718,13 @@
         //      the compiled code will be private.
         private boolean mUsedByOtherAppsBeforeUpgrade;
 
-        public PackageUseInfo() {
+        /*package*/ PackageUseInfo() {
             mCodePathsUsedByOtherApps = new HashMap<>();
             mDexUseInfoMap = new HashMap<>();
         }
 
         // Creates a deep copy of the `other`.
-        public PackageUseInfo(PackageUseInfo other) {
+        private PackageUseInfo(PackageUseInfo other) {
             mCodePathsUsedByOtherApps = new HashMap<>();
             for (Map.Entry<String, Set<String>> e : other.mCodePathsUsedByOtherApps.entrySet()) {
                 mCodePathsUsedByOtherApps.put(e.getKey(), new HashSet<>(e.getValue()));
@@ -796,8 +805,9 @@
         // Packages who load this dex file.
         private final Set<String> mLoadingPackages;
 
-        public DexUseInfo(boolean isUsedByOtherApps, int ownerUserId, String classLoaderContext,
-                String loaderIsa) {
+        @VisibleForTesting
+        /* package */ DexUseInfo(boolean isUsedByOtherApps, int ownerUserId,
+                String classLoaderContext, String loaderIsa) {
             mIsUsedByOtherApps = isUsedByOtherApps;
             mOwnerUserId = ownerUserId;
             mClassLoaderContext = classLoaderContext;
@@ -809,7 +819,7 @@
         }
 
         // Creates a deep copy of the `other`.
-        public DexUseInfo(DexUseInfo other) {
+        private DexUseInfo(DexUseInfo other) {
             mIsUsedByOtherApps = other.mIsUsedByOtherApps;
             mOwnerUserId = other.mOwnerUserId;
             mClassLoaderContext = other.mClassLoaderContext;
@@ -827,11 +837,7 @@
             if (UNKNOWN_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext)) {
                 // Can happen if we read a previous version.
                 mClassLoaderContext = dexUseInfo.mClassLoaderContext;
-            } else if (UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(dexUseInfo.mClassLoaderContext)) {
-                // We detected an unsupported context.
-                mClassLoaderContext = UNSUPPORTED_CLASS_LOADER_CONTEXT;
-            } else if (!UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext) &&
-                    !Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) {
+            } else if (!Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) {
                 // We detected a context change.
                 mClassLoaderContext = VARIABLE_CLASS_LOADER_CONTEXT;
             }
@@ -846,7 +852,7 @@
             return mIsUsedByOtherApps;
         }
 
-        public int getOwnerUserId() {
+        /* package */ int getOwnerUserId() {
             return mOwnerUserId;
         }
 
@@ -860,17 +866,15 @@
 
         public String getClassLoaderContext() { return mClassLoaderContext; }
 
-        public boolean isUnsupportedClassLoaderContext() {
-            return UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext);
-        }
-
-        public boolean isUnknownClassLoaderContext() {
+        @VisibleForTesting
+        /* package */ boolean isUnknownClassLoaderContext() {
             // The class loader context may be unknown if we loaded the data from a previous version
             // which didn't save the context.
             return UNKNOWN_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext);
         }
 
-        public boolean isVariableClassLoaderContext() {
+        @VisibleForTesting
+        /* package */ boolean isVariableClassLoaderContext() {
             return VARIABLE_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext);
         }
     }
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index aae7b95..32b2bf0 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -22,6 +22,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.AppOpsManager;
 import android.app.DownloadManager;
 import android.app.SearchManager;
 import android.app.admin.DevicePolicyManager;
@@ -40,7 +41,6 @@
 import android.content.pm.ResolveInfo;
 import android.media.RingtoneManager;
 import android.net.Uri;
-import android.os.Binder;
 import android.os.Build;
 import android.os.Environment;
 import android.os.Handler;
@@ -880,9 +880,8 @@
     }
 
     private String getDefaultSystemHandlerActivityPackage(Intent intent, int userId) {
-        ResolveInfo handler = mServiceInternal.resolveIntent(intent,
-                intent.resolveType(mContext.getContentResolver()), DEFAULT_INTENT_QUERY_FLAGS,
-                userId, false, Binder.getCallingUid());
+        ResolveInfo handler = mContext.getPackageManager().resolveActivityAsUser(
+                intent, DEFAULT_INTENT_QUERY_FLAGS, userId);
         if (handler == null || handler.activityInfo == null) {
             return null;
         }
@@ -899,8 +898,8 @@
 
     private String getDefaultSystemHandlerServicePackage(
             Intent intent, int userId) {
-        List<ResolveInfo> handlers = mServiceInternal.queryIntentServices(
-                intent, DEFAULT_INTENT_QUERY_FLAGS, Binder.getCallingUid(), userId);
+        List<ResolveInfo> handlers = mContext.getPackageManager().queryIntentServicesAsUser(
+                intent, DEFAULT_INTENT_QUERY_FLAGS, userId);
         if (handlers == null) {
             return null;
         }
@@ -924,10 +923,8 @@
         for (String syncAdapterPackageName : syncAdapterPackageNames) {
             homeIntent.setPackage(syncAdapterPackageName);
 
-            ResolveInfo homeActivity = mServiceInternal.resolveIntent(homeIntent,
-                    homeIntent.resolveType(mContext.getContentResolver()),
-                    DEFAULT_INTENT_QUERY_FLAGS,
-                    userId, false, Binder.getCallingUid());
+            ResolveInfo homeActivity = mContext.getPackageManager().resolveActivityAsUser(
+                    homeIntent, DEFAULT_INTENT_QUERY_FLAGS, userId);
             if (homeActivity != null) {
                 continue;
             }
@@ -941,7 +938,7 @@
     }
 
     private String getDefaultProviderAuthorityPackage(String authority, int userId) {
-        ProviderInfo provider = mServiceInternal.resolveContentProvider(
+        ProviderInfo provider = mContext.getPackageManager().resolveContentProviderAsUser(
                 authority, DEFAULT_INTENT_QUERY_FLAGS, userId);
         if (provider != null) {
             return provider.packageName;
@@ -980,8 +977,9 @@
                 continue;
             }
 
-            final int flags = mServiceInternal.getPermissionFlagsTEMP(
-                    permission, packageName, userId);
+            UserHandle user = UserHandle.of(userId);
+            final int flags = mContext.getPackageManager()
+                    .getPermissionFlags(permission, packageName, user);
 
             // We didn't get this through the default grant policy. Move along.
             if ((flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) == 0) {
@@ -997,7 +995,7 @@
             if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0 && !systemFixed) {
                 continue;
             }
-            mServiceInternal.revokeRuntimePermission(packageName, permission, userId, false);
+            mContext.getPackageManager().revokeRuntimePermission(packageName, permission, user);
 
             if (DEBUG) {
                 Log.i(TAG, "revoked " + (systemFixed ? "fixed " : "not fixed ")
@@ -1007,8 +1005,43 @@
             // Remove the GRANTED_BY_DEFAULT flag without touching the others.
             // Note that we do not revoke FLAG_PERMISSION_SYSTEM_FIXED. That bit remains
             // sticky once set.
-            mServiceInternal.updatePermissionFlagsTEMP(permission, packageName,
-                    PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, 0, userId);
+            mContext.getPackageManager().updatePermissionFlags(permission, packageName,
+                    PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, 0, user);
+        }
+    }
+
+    /**
+     * Check if a permission is already fixed or is set by the user.
+     *
+     * <p>A permission should not be set by the default policy if the user or other policies already
+     * set the permission.
+     *
+     * @param flags The flags of the permission
+     *
+     * @return {@code true} iff the permission can be set without violating a policy of the users
+     *         intention
+     */
+    private boolean isFixedOrUserSet(int flags) {
+        return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
+                | PackageManager.FLAG_PERMISSION_USER_FIXED
+                | PackageManager.FLAG_PERMISSION_POLICY_FIXED
+                | PackageManager.FLAG_PERMISSION_SYSTEM_FIXED)) != 0;
+    }
+
+    /**
+     * Return the background permission for a permission.
+     *
+     * @param permission The name of the foreground permission
+     *
+     * @return The name of the background permission or {@code null} if the permission has no
+     *         background permission
+     */
+    private @Nullable String getBackgroundPermission(@NonNull String permission) {
+        try {
+            return mContext.getPackageManager().getPermissionInfo(permission,
+                    0).backgroundPermission;
+        } catch (NameNotFoundException e) {
+            return null;
         }
     }
 
@@ -1024,9 +1057,15 @@
             return;
         }
 
+        PackageManager pm = mContext.getPackageManager();
         final ArraySet<String> permissions = new ArraySet<>(permissionsWithoutSplits);
         ApplicationInfo applicationInfo = pkg.applicationInfo;
 
+        int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
+        if (systemFixed) {
+            newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+        }
+
         // Automatically attempt to grant split permissions to older APKs
         final List<PermissionManager.SplitPermissionInfo> splitPermissions =
                 mContext.getSystemService(PermissionManager.class).getSplitPermissions();
@@ -1066,9 +1105,28 @@
             }
         }
 
-        final int grantablePermissionCount = requestedPermissions.length;
-        for (int i = 0; i < grantablePermissionCount; i++) {
+        final int numRequestedPermissions = requestedPermissions.length;
+
+        // Sort requested permissions so that all permissions that are a foreground permission (i.e.
+        // permisions that have background permission) are before their background permissions.
+        final String[] sortedRequestedPermissions = new String[numRequestedPermissions];
+        int numForeground = 0;
+        int numOther = 0;
+        for (int i = 0; i < numRequestedPermissions; i++) {
             String permission = requestedPermissions[i];
+            if (getBackgroundPermission(permission) != null) {
+                sortedRequestedPermissions[numForeground] = permission;
+                numForeground++;
+            } else {
+                sortedRequestedPermissions[numRequestedPermissions - 1 - numOther] =
+                        permission;
+                numOther++;
+            }
+        }
+
+        for (int requestedPermissionNum = 0; requestedPermissionNum < numRequestedPermissions;
+                requestedPermissionNum++) {
+            String permission = requestedPermissions[requestedPermissionNum];
 
             // If there is a disabled system app it may request a permission the updated
             // version ot the data partition doesn't, In this case skip the permission.
@@ -1077,16 +1135,18 @@
             }
 
             if (permissions.contains(permission)) {
-                final int flags = mServiceInternal.getPermissionFlagsTEMP(
-                        permission, pkg.packageName, userId);
+                UserHandle user = UserHandle.of(userId);
+                final int flags = mContext.getPackageManager().getPermissionFlags(
+                        permission, pkg.packageName, user);
 
-                // If any flags are set to the permission, then it is either set in
-                // its current state by the system or device/profile owner or the user.
-                // In all these cases we do not want to clobber the current state.
+                // Certain flags imply that the permission's current state by the system or
+                // device/profile owner or the user. In these cases we do not want to clobber the
+                // current state.
+                //
                 // Unless the caller wants to override user choices. The override is
                 // to make sure we can grant the needed permission to the default
                 // sms and phone apps after the user chooses this in the UI.
-                if (flags == 0 || ignoreSystemPackage) {
+                if (!isFixedOrUserSet(flags) || ignoreSystemPackage) {
                     // Never clobber policy fixed permissions.
                     // We must allow the grant of a system-fixed permission because
                     // system-fixed is sticky, but the permission itself may be revoked.
@@ -1094,20 +1154,58 @@
                         continue;
                     }
 
-                    mServiceInternal.grantRuntimePermission(
-                            pkg.packageName, permission, userId, false);
+                    int uid = UserHandle.getUid(userId,
+                            UserHandle.getAppId(pkg.applicationInfo.uid));
+                    String op = AppOpsManager.permissionToOp(permission);
+
+                    mContext.getPackageManager()
+                            .grantRuntimePermission(pkg.packageName, permission, user);
+
+                    mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName,
+                            newFlags, newFlags, user);
+
+                    List<String> fgPerms = mPermissionManager.getBackgroundPermissions()
+                            .get(permission);
+                    if (fgPerms != null) {
+                        int numFgPerms = fgPerms.size();
+                        for (int fgPermNum = 0; fgPermNum < numFgPerms; fgPermNum++) {
+                            String fgPerm = fgPerms.get(fgPermNum);
+
+                            if (pm.checkPermission(fgPerm, pkg.packageName)
+                                    == PackageManager.PERMISSION_GRANTED) {
+                                // Upgrade the app-op state of the fg permission to allow bg access
+                                mContext.getSystemService(AppOpsManager.class).setMode(
+                                        AppOpsManager.permissionToOp(fgPerm), uid,
+                                        pkg.packageName, AppOpsManager.MODE_ALLOWED);
+
+                                break;
+                            }
+                        }
+                    }
+
+                    String bgPerm = getBackgroundPermission(permission);
+                    if (bgPerm == null) {
+                        if (op != null) {
+                            mContext.getSystemService(AppOpsManager.class).setMode(op, uid,
+                                    pkg.packageName, AppOpsManager.MODE_ALLOWED);
+                        }
+                    } else {
+                        int mode;
+                        if (pm.checkPermission(bgPerm, pkg.packageName)
+                                == PackageManager.PERMISSION_GRANTED) {
+                            mode = AppOpsManager.MODE_ALLOWED;
+                        } else {
+                            mode = AppOpsManager.MODE_FOREGROUND;
+                        }
+
+                        mContext.getSystemService(AppOpsManager.class).setMode(op, uid,
+                                pkg.packageName, mode);
+                    }
+
                     if (DEBUG) {
                         Log.i(TAG, "Granted " + (systemFixed ? "fixed " : "not fixed ")
                                 + permission + " to default handler " + pkg);
                     }
-
-                    int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
-                    if (systemFixed) {
-                        newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
-                    }
-
-                    mServiceInternal.updatePermissionFlagsTEMP(permission, pkg.packageName,
-                            newFlags, newFlags, userId);
                 }
 
                 // If a component gets a permission for being the default handler A
@@ -1119,8 +1217,8 @@
                         Log.i(TAG, "Granted not fixed " + permission + " to default handler "
                                 + pkg);
                     }
-                    mServiceInternal.updatePermissionFlagsTEMP(permission, pkg.packageName,
-                            PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, 0, userId);
+                    mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName,
+                            PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, 0, user);
                 }
             }
         }
@@ -1137,10 +1235,12 @@
 
     private PackageInfo getPackageInfo(String pkg,
             @PackageManager.PackageInfoFlags int extraFlags) {
-        return mServiceInternal.getPackageInfo(pkg,
-                DEFAULT_PACKAGE_INFO_QUERY_FLAGS | extraFlags,
-                //TODO is this the right filterCallingUid?
-                UserHandle.USER_SYSTEM, UserHandle.USER_SYSTEM);
+        try {
+            return mContext.getPackageManager().getPackageInfo(pkg,
+                    DEFAULT_PACKAGE_INFO_QUERY_FLAGS | extraFlags);
+        } catch (NameNotFoundException e) {
+            return null;
+        }
     }
 
     private boolean isSysComponentOrPersistentPlatformSignedPrivApp(PackageInfo pkg) {
diff --git a/services/core/java/com/android/server/pm/permission/OWNERS b/services/core/java/com/android/server/pm/permission/OWNERS
index ffc4731..88b97ea 100644
--- a/services/core/java/com/android/server/pm/permission/OWNERS
+++ b/services/core/java/com/android/server/pm/permission/OWNERS
@@ -1,8 +1,9 @@
 per-file DefaultPermissionGrantPolicy.java = bpoiesz@google.com
-per-file DefaultPermissionGrantPolicy.java = fkupolov@google.com
 per-file DefaultPermissionGrantPolicy.java = hackbod@android.com
 per-file DefaultPermissionGrantPolicy.java = jsharkey@android.com
 per-file DefaultPermissionGrantPolicy.java = svetoslavganov@google.com
 per-file DefaultPermissionGrantPolicy.java = toddke@google.com
 per-file DefaultPermissionGrantPolicy.java = yamasani@google.com
 per-file DefaultPermissionGrantPolicy.java = patb@google.com
+per-file DefaultPermissionGrantPolicy.java = eugenesusla@google.com
+per-file DefaultPermissionGrantPolicy.java = moltmann@google.com
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
index 80a5fbb6..ec15c16 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
@@ -107,11 +107,7 @@
      */
     public abstract void addAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);
     public abstract void addAllPermissionGroups(@NonNull PackageParser.Package pkg, boolean chatty);
-    public abstract void removeAllPermissions(
-            @NonNull PackageParser.Package pkg,
-            @NonNull List<String> allPackageNames,
-            @Nullable PermissionCallback permissionCallback,
-            boolean chatty);
+    public abstract void removeAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty);
     public abstract boolean addDynamicPermission(@NonNull PermissionInfo info, boolean async,
             int callingUid, @Nullable PermissionCallback callback);
     public abstract void removeDynamicPermission(@NonNull String permName, int callingUid,
@@ -185,4 +181,4 @@
 
     /** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
     public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
-}
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 4b6760c..b788935 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -16,10 +16,28 @@
 
 package com.android.server.pm.permission;
 
+import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_DEFAULT;
+import static android.app.AppOpsManager.MODE_ERRORED;
+import static android.app.AppOpsManager.MODE_FOREGROUND;
+import static android.app.AppOpsManager.MODE_IGNORED;
+import static android.app.AppOpsManager.OP_NONE;
+import static android.app.AppOpsManager.permissionToOp;
+import static android.app.AppOpsManager.permissionToOpCode;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+import static android.os.UserHandle.getAppId;
+import static android.os.UserHandle.getUid;
 
 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
@@ -30,8 +48,10 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.AppOpsManager;
+import android.app.AppOpsManagerInternal;
 import android.content.Context;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser;
@@ -39,7 +59,6 @@
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.metrics.LogMaker;
-import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
@@ -51,6 +70,7 @@
 import android.os.UserManagerInternal;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageManagerInternal;
+import android.permission.PermissionManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -154,6 +174,13 @@
     @GuardedBy("mLock")
     private boolean mSystemReady;
 
+    /**
+     * For each foreground/background permission the mapping:
+     * Background permission -> foreground permissions
+     */
+    @GuardedBy("mLock")
+    private ArrayMap<String, List<String>> mBackgroundPermissions;
+
     PermissionManagerService(Context context,
             @Nullable DefaultPermissionGrantedCallback defaultGrantCallback,
             @NonNull Object externalLock) {
@@ -478,9 +505,8 @@
                                         " to " + newPermissionGroupName);
 
                                 try {
-                                    revokeRuntimePermission(permissionName, packageName,
-                                            mSettings.getPermission(permissionName), false,
-                                            Process.SYSTEM_UID, userId, permissionCallback, false);
+                                    revokeRuntimePermission(permissionName, packageName, false,
+                                            Process.SYSTEM_UID, userId, permissionCallback);
                                 } catch (IllegalArgumentException e) {
                                     Slog.e(TAG, "Could not revoke " + permissionName + " from "
                                             + packageName, e);
@@ -573,59 +599,9 @@
 
     }
 
-    private void revokeAllPermissions(
-            @NonNull List<BasePermission> bps,
-            @NonNull List<String> allPackageNames,
-            @Nullable PermissionCallback permissionCallback) {
-        AsyncTask.execute(() -> {
-            final int numRemovedPermissions = bps.size();
-            for (int permissionNum = 0; permissionNum < numRemovedPermissions; permissionNum++) {
-                final int[] userIds = mUserManagerInt.getUserIds();
-                final int numUserIds = userIds.length;
-
-                final int numPackages = allPackageNames.size();
-                for (int packageNum = 0; packageNum < numPackages; packageNum++) {
-                    final String packageName = allPackageNames.get(packageNum);
-                    final ApplicationInfo applicationInfo = mPackageManagerInt.getApplicationInfo(
-                            packageName, 0, Process.SYSTEM_UID, UserHandle.USER_SYSTEM);
-                    if (applicationInfo != null
-                            && applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
-                        continue;
-                    }
-                    for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
-                        final int userId = userIds[userIdNum];
-                        final String permissionName = bps.get(permissionNum).getName();
-                        if (checkPermission(permissionName, packageName, UserHandle.USER_SYSTEM,
-                                userId) == PackageManager.PERMISSION_GRANTED) {
-                            try {
-                                revokeRuntimePermission(
-                                        permissionName,
-                                        packageName,
-                                        bps.get(permissionNum),
-                                        false,
-                                        Process.SYSTEM_UID,
-                                        userId,
-                                        permissionCallback,
-                                        true);
-                            } catch (IllegalArgumentException e) {
-                                Slog.e(TAG, "Could not revoke " + permissionName + " from "
-                                        + packageName, e);
-                            }
-                        }
-                    }
-                }
-            }
-        });
-    }
-
-    private void removeAllPermissions(
-            @NonNull PackageParser.Package pkg,
-            @NonNull List<String> allPackageNames,
-            @Nullable PermissionCallback permissionCallback,
-            boolean chatty) {
+    private void removeAllPermissions(PackageParser.Package pkg, boolean chatty) {
         synchronized (mLock) {
             int N = pkg.permissions.size();
-            List<BasePermission> bps = new ArrayList<BasePermission>(N);
             StringBuilder r = null;
             for (int i=0; i<N; i++) {
                 PackageParser.Permission p = pkg.permissions.get(i);
@@ -634,9 +610,6 @@
                     bp = mSettings.mPermissionTrees.get(p.info.name);
                 }
                 if (bp != null && bp.isPermission(p)) {
-                    if ((p.info.getProtection() & PermissionInfo.PROTECTION_DANGEROUS) != 0) {
-                        bps.add(bp);
-                    }
                     bp.setPermission(null);
                     if (DEBUG_REMOVE && chatty) {
                         if (r == null) {
@@ -655,7 +628,6 @@
                     }
                 }
             }
-            revokeAllPermissions(bps, allPackageNames, permissionCallback);
             if (r != null) {
                 if (DEBUG_REMOVE) Log.d(TAG, "  Permissions: " + r);
             }
@@ -737,8 +709,24 @@
         }
     }
 
-    private void grantPermissions(PackageParser.Package pkg, boolean replace,
-            String packageOfInterest, PermissionCallback callback) {
+    /**
+     * Restore the permission state for a package.
+     *
+     * <ul>
+     *     <li>During boot the state gets restored from the disk</li>
+     *     <li>During app update the state gets restored from the last version of the app</li>
+     * </ul>
+     *
+     * <p>This restores the permission state for all users.
+     *
+     * @param pkg the package the permissions belong to
+     * @param replace if the package is getting replaced (this might change the requested
+     *                permissions of this package)
+     * @param packageOfInterest If this is the name of {@code pkg} add extra logging
+     * @param callback Result call back
+     */
+    private void restorePermissionState(@NonNull PackageParser.Package pkg, boolean replace,
+            @Nullable String packageOfInterest, @Nullable PermissionCallback callback) {
         // IMPORTANT: There are two types of permissions: install and runtime.
         // Install time permissions are granted when the app is installed to
         // all device users and users added in the future. Runtime permissions
@@ -866,7 +854,8 @@
                 }
 
                 if (DEBUG_PERMISSIONS) {
-                    Slog.i(TAG, "Granting permission " + perm + " to package " + pkg.packageName);
+                    Slog.i(TAG, "Considering granting permission " + perm + " to package "
+                            + pkg.packageName);
                 }
 
                 if (grant != GRANT_DENIED) {
@@ -1055,6 +1044,11 @@
                 // changed.
                 ps.setInstallPermissionsFixed(true);
             }
+
+            updatedUserIds = revokePermissionsNoLongerImplicitLocked(permissionsState, pkg,
+                    updatedUserIds);
+            updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions,
+                    permissionsState, pkg, updatedUserIds);
         }
 
         // Persist the runtime permissions state for users with changes. If permissions
@@ -1065,6 +1059,317 @@
         }
     }
 
+    /**
+     * Set app op for a app-op related to a permission.
+     *
+     * @param permission The permission the app-op belongs to
+     * @param pkg The package the permission belongs to
+     * @param userId The user to be changed
+     * @param mode The new mode to set
+     */
+    private void setAppOpMode(@NonNull String permission, @NonNull PackageParser.Package pkg,
+            @UserIdInt int userId, int mode) {
+        AppOpsManagerInternal appOpsInternal = LocalServices.getService(
+                AppOpsManagerInternal.class);
+
+        appOpsInternal.setMode(permissionToOpCode(permission),
+                getUid(userId, getAppId(pkg.applicationInfo.uid)), pkg.packageName, mode,
+                (pkg.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0);
+    }
+
+    /**
+     * Revoke permissions that are not implicit anymore and that have
+     * {@link PackageManager#FLAG_PERMISSION_REVOKE_WHEN_REQUESTED} set.
+     *
+     * @param ps The state of the permissions of the package
+     * @param pkg The package that is currently looked at
+     * @param updatedUserIds a list of user ids that needs to be amended if the permission state
+     *                       for a user is changed.
+     *
+     * @return The updated value of the {@code updatedUserIds} parameter
+     */
+    private @NonNull int[] revokePermissionsNoLongerImplicitLocked(
+            @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg,
+            @NonNull int[] updatedUserIds) {
+        AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+
+        String pkgName = pkg.packageName;
+
+        int[] users = UserManagerService.getInstance().getUserIds();
+        int numUsers = users.length;
+        for (int i = 0; i < numUsers; i++) {
+            int userId = users[i];
+
+            for (String permission : ps.getPermissions(userId)) {
+                if (!pkg.implicitPermissions.contains(permission)) {
+                    if (!ps.hasInstallPermission(permission)) {
+                        int flags = ps.getRuntimePermissionState(permission, userId).getFlags();
+
+                        if ((flags & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED) != 0) {
+                            BasePermission bp = mSettings.getPermissionLocked(permission);
+
+                            ps.updatePermissionFlags(bp, userId,
+                                    FLAG_PERMISSION_REVOKE_WHEN_REQUESTED
+                                            | FLAG_PERMISSION_USER_FIXED | FLAG_PERMISSION_USER_SET,
+                                    0);
+                            updatedUserIds = ArrayUtils.appendInt(updatedUserIds,
+                                    userId);
+
+                            if ((flags & (FLAG_PERMISSION_GRANTED_BY_DEFAULT
+                                    | FLAG_PERMISSION_POLICY_FIXED | FLAG_PERMISSION_SYSTEM_FIXED))
+                                    == 0) {
+                                if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+                                    if (permissionToOpCode(permission) != OP_NONE) {
+                                        setAppOpMode(permission, pkg, userId, MODE_IGNORED);
+
+                                        if (DEBUG_PERMISSIONS) {
+                                            Slog.i(TAG, "Revoking app-op "
+                                                    + permissionToOp(permission) + " for " + pkgName
+                                                    + " as it is now requested");
+                                        }
+                                    }
+                                } else {
+                                    int revokeResult = ps.revokeRuntimePermission(bp, userId);
+                                    if (revokeResult
+                                            != PermissionsState.PERMISSION_OPERATION_FAILURE) {
+
+                                        if (DEBUG_PERMISSIONS) {
+                                            Slog.i(TAG, "Revoking runtime permission " + permission
+                                                    + " for " + pkgName
+                                                    + " as it is now requested");
+                                        }
+                                    }
+                                }
+
+                                List<String> fgPerms = mBackgroundPermissions.get(permission);
+                                if (fgPerms != null) {
+                                    int numFgPerms = fgPerms.size();
+                                    for (int fgPermNum = 0; fgPermNum < numFgPerms; fgPermNum++) {
+                                        String fgPerm = fgPerms.get(fgPermNum);
+
+                                        int mode = appOpsManager.unsafeCheckOpRaw(
+                                                permissionToOp(fgPerm),
+                                                getUid(userId, getAppId(pkg.applicationInfo.uid)),
+                                                pkgName);
+
+                                        if (mode == MODE_ALLOWED) {
+                                            setAppOpMode(fgPerm, pkg, userId, MODE_FOREGROUND);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return updatedUserIds;
+    }
+
+    /**
+     * {@code newPerm} is newly added; Inherit the state from {@code sourcePerms}.
+     *
+     * <p>A single new permission can be split off from several source permissions. In this case
+     * the most leniant state is inherited.
+     *
+     * <p>Warning: This does not handle foreground / background permissions
+     *
+     * @param sourcePerms The permissions to inherit from
+     * @param newPerm The permission to inherit to
+     * @param ps The permission state of the package
+     * @param pkg The package requesting the permissions
+     * @param userId The user the permission belongs to
+     */
+    private void inheritPermissionStateToNewImplicitPermissionLocked(
+            @NonNull ArraySet<String> sourcePerms, @NonNull String newPerm,
+            @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg,
+            @UserIdInt int userId) {
+        AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+        String pkgName = pkg.packageName;
+
+        if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+            if (permissionToOp(newPerm) != null) {
+                int mostLenientSourceMode = MODE_ERRORED;
+
+                // Find most lenient source permission state.
+                int numSourcePerms = sourcePerms.size();
+                for (int i = 0; i < numSourcePerms; i++) {
+                    String sourcePerm = sourcePerms.valueAt(i);
+
+                    if (ps.hasRuntimePermission(sourcePerm, userId)) {
+                        String sourceOp = permissionToOp(sourcePerm);
+
+                        if (sourceOp != null) {
+                            int mode = appOpsManager.unsafeCheckOpRaw(sourceOp,
+                                    getUid(userId, getAppId(pkg.applicationInfo.uid)), pkgName);
+
+                            if (mode == MODE_FOREGROUND) {
+                                throw new IllegalArgumentException("split permission" + sourcePerm
+                                        + " has app-op state " + AppOpsManager.MODE_NAMES[mode]);
+                            }
+
+                            // Leniency order: allowed > ignored > default
+                            if (mode == MODE_ALLOWED) {
+                                mostLenientSourceMode = MODE_ALLOWED;
+                                break;
+                            } else if (mode == MODE_IGNORED) {
+                                mostLenientSourceMode = MODE_IGNORED;
+                            } else if (mode == MODE_DEFAULT
+                                    && mostLenientSourceMode != MODE_IGNORED) {
+                                mostLenientSourceMode = MODE_DEFAULT;
+                            }
+                        }
+                    }
+                }
+
+                if (mostLenientSourceMode != MODE_ERRORED) {
+                    if (DEBUG_PERMISSIONS) {
+                        Slog.i(TAG, newPerm + " inherits app-ops state " + mostLenientSourceMode
+                                + " from " + sourcePerms + " for " + pkgName);
+                    }
+
+                    setAppOpMode(newPerm, pkg, userId, mostLenientSourceMode);
+                }
+            }
+        } else {
+            boolean isGranted = false;
+
+            int numSourcePerm = sourcePerms.size();
+            for (int i = 0; i < numSourcePerm; i++) {
+                String sourcePerm = sourcePerms.valueAt(i);
+                if (ps.hasRuntimePermission(sourcePerm, userId)
+                        && ps.getRuntimePermissionState(sourcePerm, userId).isGranted()) {
+                    isGranted = true;
+                    break;
+                }
+            }
+
+            if (isGranted) {
+                if (DEBUG_PERMISSIONS) {
+                    Slog.i(TAG, newPerm + " inherits runtime perm grant from " + sourcePerms
+                            + " for " + pkgName);
+                }
+
+                ps.grantRuntimePermission(mSettings.getPermissionLocked(newPerm), userId);
+            }
+        }
+    }
+
+    /**
+     * Set the state of a implicit permission that is seen for the first time.
+     *
+     * @param origPs The permission state of the package before the split
+     * @param ps The new permission state
+     * @param pkg The package the permission belongs to
+     * @param updatedUserIds List of users for which the permission state has already been changed
+     *
+     * @return  List of users for which the permission state has been changed
+     */
+    private @NonNull int[] setInitialGrantForNewImplicitPermissionsLocked(
+            @NonNull PermissionsState origPs,
+            @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg,
+            @NonNull int[] updatedUserIds) {
+        AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
+
+        String pkgName = pkg.packageName;
+        ArraySet<String> newImplicitPermissions = new ArraySet<>();
+
+        int numRequestedPerms = pkg.requestedPermissions.size();
+        for (int i = 0; i < numRequestedPerms; i++) {
+            BasePermission bp = mSettings.getPermissionLocked(pkg.requestedPermissions.get(i));
+            if (bp != null) {
+                String perm = bp.getName();
+
+                if (!origPs.hasRequestedPermission(perm) && pkg.implicitPermissions.contains(
+                        perm)) {
+                    newImplicitPermissions.add(perm);
+
+                    if (DEBUG_PERMISSIONS) {
+                        Slog.i(TAG, perm + " is newly added for " + pkgName);
+                    }
+                }
+            }
+        }
+
+        ArrayMap<String, ArraySet<String>> newToSplitPerms = new ArrayMap<>();
+
+        int numSplitPerms = PermissionManager.SPLIT_PERMISSIONS.size();
+        for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
+            PermissionManager.SplitPermissionInfo spi =
+                    PermissionManager.SPLIT_PERMISSIONS.get(splitPermNum);
+
+            List<String> newPerms = spi.getNewPermissions();
+            int numNewPerms = newPerms.size();
+            for (int newPermNum = 0; newPermNum < numNewPerms; newPermNum++) {
+                String newPerm = newPerms.get(newPermNum);
+
+                ArraySet<String> splitPerms = newToSplitPerms.get(newPerm);
+                if (splitPerms == null) {
+                    splitPerms = new ArraySet<>();
+                    newToSplitPerms.put(newPerm, splitPerms);
+                }
+
+                splitPerms.add(spi.getSplitPermission());
+            }
+        }
+
+        int numNewImplicitPerms = newImplicitPermissions.size();
+        for (int newImplicitPermNum = 0; newImplicitPermNum < numNewImplicitPerms;
+                newImplicitPermNum++) {
+            String newPerm = newImplicitPermissions.valueAt(newImplicitPermNum);
+            ArraySet<String> sourcePerms = newToSplitPerms.get(newPerm);
+
+            if (sourcePerms != null) {
+                if (!ps.hasInstallPermission(newPerm)) {
+                    BasePermission bp = mSettings.getPermissionLocked(newPerm);
+
+                    int[] users = UserManagerService.getInstance().getUserIds();
+                    int numUsers = users.length;
+                    for (int userNum = 0; userNum < numUsers; userNum++) {
+                        int userId = users[userNum];
+
+                        ps.updatePermissionFlags(bp, userId,
+                                FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
+                                FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
+                        updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
+
+                        // SPECIAL BEHAVIOR for background location. Foreground only by default.
+                        if (newPerm.equals(ACCESS_BACKGROUND_LOCATION)) {
+                            int numSourcePerms = sourcePerms.size();
+                            for (int sourcePermNum = 0; sourcePermNum < numSourcePerms;
+                                    sourcePermNum++) {
+                                String sourcePerm = sourcePerms.valueAt(sourcePermNum);
+
+                                if (appOpsManager.unsafeCheckOpNoThrow(permissionToOp(sourcePerm),
+                                        getUid(userId, getAppId(pkg.applicationInfo.uid)), pkgName)
+                                        == MODE_ALLOWED) {
+                                    setAppOpMode(sourcePerm, pkg, userId, MODE_FOREGROUND);
+                                }
+                            }
+                        } else {
+                            if (!origPs.hasRequestedPermission(sourcePerms)) {
+                                // Both permissions are new, do nothing
+                                if (DEBUG_PERMISSIONS) {
+                                    Slog.i(TAG, newPerm + " does not inherit from " + sourcePerms
+                                            + " for " + pkgName
+                                            + " as split permission is also new");
+                                }
+
+                                break;
+                            } else {
+                                inheritPermissionStateToNewImplicitPermissionLocked(sourcePerms,
+                                        newPerm, ps, pkg, userId);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return updatedUserIds;
+    }
+
     private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) {
         boolean allowed = false;
         final int NP = PackageParser.NEW_PERMISSIONS.length;
@@ -1571,10 +1876,9 @@
         }
 
     }
-    
-    private void revokeRuntimePermission(String permName, String packageName, BasePermission bp,
-            boolean overridePolicy, int callingUid, int userId, PermissionCallback callback,
-            boolean permissionRemoved) {
+
+    private void revokeRuntimePermission(String permName, String packageName,
+            boolean overridePolicy, int callingUid, int userId, PermissionCallback callback) {
         if (!mUserManagerInt.exists(userId)) {
             Log.e(TAG, "No such user:" + userId);
             return;
@@ -1599,7 +1903,7 @@
         if (mPackageManagerInt.filterAppAccess(pkg, Binder.getCallingUid(), userId)) {
             throw new IllegalArgumentException("Unknown package: " + packageName);
         }
-
+        final BasePermission bp = mSettings.getPermissionLocked(permName);
         if (bp == null) {
             throw new IllegalArgumentException("Unknown permission: " + permName);
         }
@@ -1812,7 +2116,30 @@
         // and make sure there are no dangling permissions.
         flags = updatePermissions(changingPkgName, changingPkg, flags);
 
-        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "grantPermissions");
+        synchronized (mLock) {
+            if (mBackgroundPermissions == null) {
+                // Cache background -> foreground permission mapping.
+                // Only system declares background permissions, hence mapping does never change.
+                mBackgroundPermissions = new ArrayMap<>();
+                for (BasePermission bp : mSettings.getAllPermissionsLocked()) {
+                    if (bp.perm != null && bp.perm.info != null
+                            && bp.perm.info.backgroundPermission != null) {
+                        String fgPerm = bp.name;
+                        String bgPerm = bp.perm.info.backgroundPermission;
+
+                        List<String> fgPerms = mBackgroundPermissions.get(bgPerm);
+                        if (fgPerms == null) {
+                            fgPerms = new ArrayList<>();
+                            mBackgroundPermissions.put(bgPerm, fgPerms);
+                        }
+
+                        fgPerms.add(fgPerm);
+                    }
+                }
+            }
+        }
+
+        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "restorePermissionState");
         // Now update the permissions for all packages, in particular
         // replace the granted permissions of the system packages.
         if ((flags & UPDATE_PERMISSIONS_ALL) != 0) {
@@ -1822,7 +2149,7 @@
                     final String volumeUuid = getVolumeUuidForPackage(pkg);
                     final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0)
                             && Objects.equals(replaceVolumeUuid, volumeUuid);
-                    grantPermissions(pkg, replace, changingPkgName, callback);
+                    restorePermissionState(pkg, replace, changingPkgName, callback);
                 }
             }
         }
@@ -1832,7 +2159,7 @@
             final String volumeUuid = getVolumeUuidForPackage(changingPkg);
             final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_PKG) != 0)
                     && Objects.equals(replaceVolumeUuid, volumeUuid);
-            grantPermissions(changingPkg, replace, changingPkgName, callback);
+            restorePermissionState(changingPkg, replace, changingPkgName, callback);
         }
         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
     }
@@ -2129,6 +2456,17 @@
         mMetricsLogger.write(log);
     }
 
+    /**
+     * Get the mapping of background permissions to their foreground permissions.
+     *
+     * <p>Only initialized in the system server.
+     *
+     * @return the map &lt;bg permission -> list&lt;fg perm&gt;&gt;
+     */
+    public @Nullable ArrayMap<String, List<String>> getBackgroundPermissions() {
+        return mBackgroundPermissions;
+    }
+
     private class PermissionManagerInternalImpl extends PermissionManagerInternal {
         @Override
         public void systemReady() {
@@ -2156,10 +2494,8 @@
             PermissionManagerService.this.addAllPermissionGroups(pkg, chatty);
         }
         @Override
-        public void removeAllPermissions(Package pkg, List<String> allPackageNames,
-                PermissionCallback permissionCallback, boolean chatty) {
-            PermissionManagerService.this.removeAllPermissions(
-                    pkg, allPackageNames, permissionCallback, chatty);
+        public void removeAllPermissions(Package pkg, boolean chatty) {
+            PermissionManagerService.this.removeAllPermissions(pkg, chatty);
         }
         @Override
         public boolean addDynamicPermission(PermissionInfo info, boolean async, int callingUid,
@@ -2195,8 +2531,7 @@
                 boolean overridePolicy, int callingUid, int userId,
                 PermissionCallback callback) {
             PermissionManagerService.this.revokeRuntimePermission(permName, packageName,
-                    mSettings.getPermission(permName), overridePolicy, callingUid, userId,
-                    callback, false);
+                    overridePolicy, callingUid, userId, callback);
         }
         @Override
         public void updatePermissions(String packageName, Package pkg, boolean replaceGrant,
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 4341902..282746a 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -41,6 +41,7 @@
 import static android.os.Build.VERSION_CODES.O;
 import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
 import static android.view.Display.STATE_OFF;
 import static android.view.WindowManager.DOCKED_LEFT;
 import static android.view.WindowManager.DOCKED_RIGHT;
@@ -155,6 +156,7 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
+import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.ActivityThread;
 import android.app.AppOpsManager;
@@ -665,9 +667,6 @@
     SleepToken mDreamingSleepToken;
     SleepToken mScreenOffSleepToken;
     volatile boolean mKeyguardOccluded;
-    boolean mHomePressed;
-    boolean mHomeConsumed;
-    boolean mHomeDoubleTapPending;
     Intent mHomeIntent;
     Intent mCarDockIntent;
     Intent mDeskDockIntent;
@@ -865,7 +864,7 @@
                     launchVoiceAssistWithWakeLock();
                     break;
                 case MSG_POWER_DELAYED_PRESS:
-                    powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
+                    powerPress((Long) msg.obj, msg.arg1 != 0, msg.arg2);
                     finishPowerKeyPress();
                     break;
                 case MSG_POWER_LONG_PRESS:
@@ -1340,7 +1339,7 @@
                 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
                     goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
                             PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
-                    launchHomeFromHotKey();
+                    launchHomeFromHotKey(DEFAULT_DISPLAY);
                     break;
                 case SHORT_PRESS_POWER_GO_HOME:
                     shortPressPowerGoHome();
@@ -1369,7 +1368,8 @@
     }
 
     private void shortPressPowerGoHome() {
-        launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
+        launchHomeFromHotKey(DEFAULT_DISPLAY, true /* awakenFromDreams */,
+                false /*respectKeyguard*/);
         if (isKeyguardShowingAndNotOccluded()) {
             // Notify keyguard so it can do any special handling for the power button since the
             // device will not power off and only launch home.
@@ -1505,7 +1505,8 @@
 
     private void sleepPress() {
         if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) {
-            launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/);
+            launchHomeFromHotKey(DEFAULT_DISPLAY, false /* awakenDreams */,
+                    true /*respectKeyguard*/);
         }
     }
 
@@ -1683,7 +1684,7 @@
                 Settings.Secure.TV_USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
     }
 
-    private void handleShortPressOnHome() {
+    private void handleShortPressOnHome(int displayId) {
         // Turn on the connected TV and switch HDMI input if we're a HDMI playback device.
         final HdmiControl hdmiControl = getHdmiControl();
         if (hdmiControl != null) {
@@ -1698,7 +1699,7 @@
         }
 
         // Go home!
-        launchHomeFromHotKey();
+        launchHomeFromHotKey(displayId);
     }
 
     /**
@@ -1745,26 +1746,6 @@
         }
     }
 
-    private void handleLongPressOnHome(int deviceId) {
-        if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
-            return;
-        }
-        mHomeConsumed = true;
-        performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
-                "Home - Long Press");
-        switch (mLongPressOnHomeBehavior) {
-            case LONG_PRESS_HOME_ALL_APPS:
-                launchAllAppsAction();
-                break;
-            case LONG_PRESS_HOME_ASSIST:
-                launchAssistAction(null, deviceId);
-                break;
-            default:
-                Log.w(TAG, "Undefined home long press behavior: " + mLongPressOnHomeBehavior);
-                break;
-        }
-    }
-
     private void launchAllAppsAction() {
         Intent intent = new Intent(Intent.ACTION_ALL_APPS);
         if (mHasFeatureLeanback) {
@@ -1781,13 +1762,6 @@
         startActivityAsUser(intent, UserHandle.CURRENT);
     }
 
-    private void handleDoubleTapOnHome() {
-        if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
-            mHomeConsumed = true;
-            toggleRecentApps();
-        }
-    }
-
     private void showPictureInPictureMenu(KeyEvent event) {
         if (DEBUG_INPUT) Log.d(TAG, "showPictureInPictureMenu event=" + event);
         mHandler.removeMessages(MSG_SHOW_PICTURE_IN_PICTURE_MENU);
@@ -1803,15 +1777,147 @@
         }
     }
 
-    private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
-        @Override
-        public void run() {
-            if (mHomeDoubleTapPending) {
-                mHomeDoubleTapPending = false;
-                handleShortPressOnHome();
+    /** A handler to handle home keys per display */
+    private class DisplayHomeButtonHandler {
+
+        private final int mDisplayId;
+
+        private boolean mHomeDoubleTapPending;
+        private boolean mHomePressed;
+        private boolean mHomeConsumed;
+
+        private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() {
+            @Override
+            public void run() {
+                if (mHomeDoubleTapPending) {
+                    mHomeDoubleTapPending = false;
+                    handleShortPressOnHome(mDisplayId);
+                }
+            }
+        };
+
+        DisplayHomeButtonHandler(int displayId) {
+            mDisplayId = displayId;
+        }
+
+        int handleHomeButton(WindowState win, KeyEvent event) {
+            final boolean keyguardOn = keyguardOn();
+            final int repeatCount = event.getRepeatCount();
+            final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
+            final boolean canceled = event.isCanceled();
+
+            if (DEBUG_INPUT) {
+                Log.d(TAG, String.format("handleHomeButton in display#%d mHomePressed = %b",
+                        mDisplayId, mHomePressed));
+            }
+
+            // If we have released the home key, and didn't do anything else
+            // while it was pressed, then it is time to go home!
+            if (!down) {
+                if (mDisplayId == DEFAULT_DISPLAY) {
+                    cancelPreloadRecentApps();
+                }
+
+                mHomePressed = false;
+                if (mHomeConsumed) {
+                    mHomeConsumed = false;
+                    return -1;
+                }
+
+                if (canceled) {
+                    Log.i(TAG, "Ignoring HOME; event canceled.");
+                    return -1;
+                }
+
+                // Delay handling home if a double-tap is possible.
+                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
+                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
+                    mHomeDoubleTapPending = true;
+                    mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
+                            ViewConfiguration.getDoubleTapTimeout());
+                    return -1;
+                }
+
+                handleShortPressOnHome(mDisplayId);
+                return -1;
+            }
+
+            // If a system window has focus, then it doesn't make sense
+            // right now to interact with applications.
+            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
+            if (attrs != null) {
+                final int type = attrs.type;
+                if (type == TYPE_KEYGUARD_DIALOG
+                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+                    // the "app" is keyguard, so give it the key
+                    return 0;
+                }
+                for (int t : WINDOW_TYPES_WHERE_HOME_DOESNT_WORK) {
+                    if (type == t) {
+                        // don't do anything, but also don't pass it to the app
+                        return -1;
+                    }
+                }
+            }
+
+            // Remember that home is pressed and handle special actions.
+            if (repeatCount == 0) {
+                mHomePressed = true;
+                if (mHomeDoubleTapPending) {
+                    mHomeDoubleTapPending = false;
+                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
+                    handleDoubleTapOnHome();
+                // TODO(multi-display): Remove display id check once we support recents on
+                // multi-display
+                } else if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI
+                        && mDisplayId == DEFAULT_DISPLAY) {
+                    preloadRecentApps();
+                }
+            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
+                if (!keyguardOn) {
+                    handleLongPressOnHome(event.getDeviceId());
+                }
+            }
+            return -1;
+        }
+
+        private void handleDoubleTapOnHome() {
+            if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
+                mHomeConsumed = true;
+                toggleRecentApps();
             }
         }
-    };
+
+        private void handleLongPressOnHome(int deviceId) {
+            if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
+                return;
+            }
+            mHomeConsumed = true;
+            performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+                    "Home - Long Press");
+            switch (mLongPressOnHomeBehavior) {
+                case LONG_PRESS_HOME_ALL_APPS:
+                    launchAllAppsAction();
+                    break;
+                case LONG_PRESS_HOME_ASSIST:
+                    launchAssistAction(null, deviceId);
+                    break;
+                default:
+                    Log.w(TAG, "Undefined home long press behavior: "
+                            + mLongPressOnHomeBehavior);
+                    break;
+            }
+        }
+
+        @Override
+        public String toString() {
+            return String.format("mDisplayId = %d, mHomePressed = %b", mDisplayId, mHomePressed);
+        }
+    }
+
+    /** A DisplayHomeButtonHandler map indexed by display id */
+    private final SparseArray<DisplayHomeButtonHandler> mDisplayHomeButtonHandlers =
+            new SparseArray<>();
 
     private boolean isRoundWindow() {
         return mContext.getResources().getConfiguration().isScreenRound();
@@ -3258,6 +3364,7 @@
             WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
         };
 
+    // TODO(b/117479243): handle it in InputPolicy
     /** {@inheritDoc} */
     @Override
     public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
@@ -3268,11 +3375,11 @@
         final int flags = event.getFlags();
         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
         final boolean canceled = event.isCanceled();
+        final int displayId = event.getDisplayId();
 
         if (DEBUG_INPUT) {
             Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
-                    + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
-                    + " canceled=" + canceled);
+                    + repeatCount + " keyguardOn=" + keyguardOn + " canceled=" + canceled);
         }
 
         // If we think we might have a volume down & power key chord on the way
@@ -3357,71 +3464,12 @@
         // it handle it, because that gives us the correct 5 second
         // timeout.
         if (keyCode == KeyEvent.KEYCODE_HOME) {
-
-            // If we have released the home key, and didn't do anything else
-            // while it was pressed, then it is time to go home!
-            if (!down) {
-                cancelPreloadRecentApps();
-
-                mHomePressed = false;
-                if (mHomeConsumed) {
-                    mHomeConsumed = false;
-                    return -1;
-                }
-
-                if (canceled) {
-                    Log.i(TAG, "Ignoring HOME; event canceled.");
-                    return -1;
-                }
-
-                // Delay handling home if a double-tap is possible.
-                if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) {
-                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case
-                    mHomeDoubleTapPending = true;
-                    mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable,
-                            ViewConfiguration.getDoubleTapTimeout());
-                    return -1;
-                }
-
-                handleShortPressOnHome();
-                return -1;
+            DisplayHomeButtonHandler handler = mDisplayHomeButtonHandlers.get(displayId);
+            if (handler == null) {
+                handler = new DisplayHomeButtonHandler(displayId);
+                mDisplayHomeButtonHandlers.put(displayId, handler);
             }
-
-            // If a system window has focus, then it doesn't make sense
-            // right now to interact with applications.
-            WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
-            if (attrs != null) {
-                final int type = attrs.type;
-                if (type == TYPE_KEYGUARD_DIALOG
-                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
-                    // the "app" is keyguard, so give it the key
-                    return 0;
-                }
-                final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
-                for (int i=0; i<typeCount; i++) {
-                    if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
-                        // don't do anything, but also don't pass it to the app
-                        return -1;
-                    }
-                }
-            }
-
-            // Remember that home is pressed and handle special actions.
-            if (repeatCount == 0) {
-                mHomePressed = true;
-                if (mHomeDoubleTapPending) {
-                    mHomeDoubleTapPending = false;
-                    mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable);
-                    handleDoubleTapOnHome();
-                } else if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) {
-                    preloadRecentApps();
-                }
-            } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
-                if (!keyguardOn) {
-                    handleLongPressOnHome(event.getDeviceId());
-                }
-            }
-            return -1;
+            return handler.handleHomeButton(win, event);
         } else if (keyCode == KeyEvent.KEYCODE_MENU) {
             // Hijack modified menu keys for debugging features
             final int chordBug = KeyEvent.META_SHIFT_ON;
@@ -3819,6 +3867,7 @@
         }
     }
 
+    // TODO(b/117479243): handle it in InputPolicy
     /** {@inheritDoc} */
     @Override
     public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
@@ -3861,7 +3910,7 @@
                         event.getAction(), fallbackAction.keyCode,
                         event.getRepeatCount(), fallbackAction.metaState,
                         event.getDeviceId(), event.getScanCode(),
-                        flags, event.getSource(), null);
+                        flags, event.getSource(), event.getDisplayId(), null);
 
                 if (!interceptFallback(win, fallbackEvent, policyFlags)) {
                     fallbackEvent.recycle();
@@ -3990,8 +4039,12 @@
     }
 
     private void startActivityAsUser(Intent intent, UserHandle handle) {
+        startActivityAsUser(intent, null, handle);
+    }
+
+    private void startActivityAsUser(Intent intent, Bundle bundle, UserHandle handle) {
         if (isUserSetupComplete()) {
-            mContext.startActivityAsUser(intent, handle);
+            mContext.startActivityAsUser(intent, bundle, handle);
         } else {
             Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent);
         }
@@ -4066,15 +4119,16 @@
         }
     }
 
-    void launchHomeFromHotKey() {
-        launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/);
+    void launchHomeFromHotKey(int displayId) {
+        launchHomeFromHotKey(displayId, true /* awakenFromDreams */, true /*respectKeyguard*/);
     }
 
     /**
      * A home key -> launch home action was detected.  Take the appropriate action
      * given the situation with the keyguard.
      */
-    void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
+    void launchHomeFromHotKey(int displayId, final boolean awakenFromDreams,
+            final boolean respectKeyguard) {
         // Abort possibly stuck animations.
         mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe);
 
@@ -4091,7 +4145,7 @@
                     @Override
                     public void onKeyguardExitResult(boolean success) {
                         if (success) {
-                            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
+                            startDockOrHome(displayId, true /*fromHomeKey*/, awakenFromDreams);
                         }
                     }
                 });
@@ -4112,7 +4166,7 @@
             hideRecentApps(false, true);
         } else {
             // Otherwise, just launch Home
-            startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);
+            startDockOrHome(displayId, true /*fromHomeKey*/, awakenFromDreams);
         }
     }
 
@@ -5673,7 +5727,7 @@
         mDefaultDisplayPolicy.setHdmiPlugged(plugged, true /* force */);
     }
 
-
+    // TODO(b/117479243): handle it in InputPolicy
     /** {@inheritDoc} */
     @Override
     public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
@@ -5686,6 +5740,7 @@
         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
         final boolean canceled = event.isCanceled();
         final int keyCode = event.getKeyCode();
+        final int displayId = event.getDisplayId();
 
         final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
 
@@ -6189,7 +6244,7 @@
         return true;
     }
 
-
+    // TODO(b/117479243): handle it in InputPolicy
     /** {@inheritDoc} */
     @Override
     public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
@@ -7265,7 +7320,7 @@
         return null;
     }
 
-    void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
+    void startDockOrHome(int displayId, boolean fromHomeKey, boolean awakenFromDreams) {
         try {
             ActivityManager.getService().stopAppSwitches();
         } catch (RemoteException e) {}
@@ -7295,8 +7350,13 @@
         } else {
             intent = mHomeIntent;
         }
+        final Bundle bundle = getLaunchDisplayIdBundle(displayId);
+        startActivityAsUser(intent, bundle, UserHandle.CURRENT);
+    }
 
-        startActivityAsUser(intent, UserHandle.CURRENT);
+    private @Nullable Bundle getLaunchDisplayIdBundle(int displayId) {
+        return (displayId == INVALID_DISPLAY) ? null
+                : ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle();
     }
 
     /**
@@ -7310,7 +7370,7 @@
         }
         if (false) {
             // This code always brings home to the front.
-            startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */);
+            startDockOrHome(DEFAULT_DISPLAY, false /*fromHomeKey*/, true /* awakenFromDreams */);
         } else {
             // This code brings home to the front or, if it is already
             // at the front, puts the device to sleep.
@@ -7321,7 +7381,7 @@
                 } else {
                     ActivityManager.getService().stopAppSwitches();
                     sendCloseSystemWindows();
-                    Intent dock = createHomeDockIntent();
+                    final Intent dock = createHomeDockIntent();
                     if (dock != null) {
                         int result = ActivityTaskManager.getService()
                                 .startActivityAsUser(null, null, dock,
@@ -8009,7 +8069,13 @@
                 pw.print(incallBackBehaviorToString(mIncallBackBehavior));
                 pw.print(" mEndcallBehavior=");
                 pw.println(endcallBehaviorToString(mEndcallBehavior));
-        pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
+        pw.print(prefix);
+        // TODO(b/117479243): handle it in InputPolicy
+        pw.print("mDisplayHomeButtonHandlers=");
+        for (int i = 0; i < mDisplayHomeButtonHandlers.size(); i++) {
+            final int key = mDisplayHomeButtonHandlers.keyAt(i);
+            pw.println(mDisplayHomeButtonHandlers.get(key));
+        }
         pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
                 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
         pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 1e0b52a..ae1090c 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -1,13 +1,11 @@
 package com.android.server.policy.keyguard;
 
-import static android.view.Display.INVALID_DISPLAY;
 import static com.android.server.wm.KeyguardServiceDelegateProto.INTERACTIVE_STATE;
 import static com.android.server.wm.KeyguardServiceDelegateProto.OCCLUDED;
 import static com.android.server.wm.KeyguardServiceDelegateProto.SCREEN_STATE;
 import static com.android.server.wm.KeyguardServiceDelegateProto.SECURE;
 import static com.android.server.wm.KeyguardServiceDelegateProto.SHOWING;
 
-import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -212,10 +210,10 @@
             mHandler.post(() -> {
                 try {
                     // There are no longer any keyguard windows on secondary displays, so pass
-                    // INVALID_DISPLAY. All that means is that showWhenLocked activities on
-                    // secondary displays now get to show.
+                    // {@code null}. All that means is that showWhenLocked activities on
+                    // external displays now get to show.
                     ActivityTaskManager.getService().setLockScreenShown(true /* keyguardShowing */,
-                            false /* aodShowing */, INVALID_DISPLAY);
+                            false /* aodShowing */, null /* secondaryDisplaysShowing */);
                 } catch (RemoteException e) {
                     // Local call.
                 }
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index a55b49f..f78d263 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -20,7 +20,7 @@
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.security.IKeystoreService;
+import android.security.keystore.IKeystoreService;
 import android.util.Slog;
 
 import com.android.internal.policy.IKeyguardService;
diff --git a/services/core/java/com/android/server/power/BatterySaverPolicy.java b/services/core/java/com/android/server/power/BatterySaverPolicy.java
index 4f8e6b6..6d7b04c 100644
--- a/services/core/java/com/android/server/power/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/BatterySaverPolicy.java
@@ -57,16 +57,32 @@
 
     public static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE.
 
-    // Secure setting for GPS behavior when battery saver mode is on.
-    public static final String SECURE_KEY_GPS_MODE = "batterySaverGpsMode";
-
     private static final String KEY_GPS_MODE = "gps_mode";
     private static final String KEY_VIBRATION_DISABLED = "vibration_disabled";
     private static final String KEY_ANIMATION_DISABLED = "animation_disabled";
     private static final String KEY_SOUNDTRIGGER_DISABLED = "soundtrigger_disabled";
-    private static final String KEY_FIREWALL_DISABLED = "firewall_disabled";
+
+    /**
+     * Disable turning on the network firewall when Battery Saver is turned on.
+     * If set to false, the firewall WILL be turned on when Battery Saver is turned on.
+     * If set to true, the firewall WILL NOT be turned on when Battery Saver is turned on.
+     */
+    private static final String KEY_ACTIVATE_FIREWALL_DISABLED = "firewall_disabled";
+
+    /**
+     * Disable turning on the special low power screen brightness dimming when Battery Saver is
+     * turned on.
+     * If set to false, the screen brightness dimming WILL be turned on by Battery Saver.
+     * If set to true, the screen brightness WILL NOT be turned on by Battery Saver.
+     */
     private static final String KEY_ADJUST_BRIGHTNESS_DISABLED = "adjust_brightness_disabled";
-    private static final String KEY_DATASAVER_DISABLED = "datasaver_disabled";
+
+    /**
+     * Disable turning on Data Saver when Battery Saver is turned on.
+     * If set to false, Data Saver WILL be turned on when Battery Saver is turned on.
+     * If set to true, Data Saver WILL NOT be turned on when Battery Saver is turned on.
+     */
+    private static final String KEY_ACTIVATE_DATASAVER_DISABLED = "datasaver_disabled";
     private static final String KEY_LAUNCH_BOOST_DISABLED = "launch_boost_disabled";
     private static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor";
     private static final String KEY_FULLBACKUP_DEFERRED = "fullbackup_deferred";
@@ -82,6 +98,28 @@
     private static final String KEY_CPU_FREQ_INTERACTIVE = "cpufreq-i";
     private static final String KEY_CPU_FREQ_NONINTERACTIVE = "cpufreq-n";
 
+    private static final Policy sDefaultPolicy = new Policy(
+            0.5f,  /* adjustBrightnessFactor */
+            true,  /* deferFullBackup */
+            true,  /* deferKeyValueBackup */
+            false, /* disableAnimation */
+            true,  /* disableAod */
+            true,  /* disableLaunchBoost */
+            true,  /* disableOptionalSensors */
+            true,  /* disableSoundTrigger */
+            true,  /* disableVibration */
+            false, /* enableAdjustBrightness */
+            false, /* enableDataSaver */
+            true,  /* enableFirewall */
+            false, /* enableQuickDoze */
+            new ArrayMap<>(), /* filesForInteractive */
+            new ArrayMap<>(), /* filesForNoninteractive */
+            true, /* forceAllAppsStandby */
+            true, /* forceBackgroundCheck */
+            PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF, /* gpsMode */
+            false /* sendTronLog */
+    );
+
     private final Object mLock;
     private final Handler mHandler;
 
@@ -101,145 +139,20 @@
     private String mEventLogKeys;
 
     /**
-     * {@code true} if vibration is disabled in battery saver mode.
-     *
-     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
-     * @see #KEY_VIBRATION_DISABLED
-     */
-    @GuardedBy("mLock")
-    private boolean mVibrationDisabledConfig;
-
-    /**
-     * Whether vibration should *really* be disabled -- i.e. {@link #mVibrationDisabledConfig}
+     * Whether vibration should *really* be disabled -- i.e. {@link Policy#disableVibration}
      * is true *and* {@link #mAccessibilityEnabled} is false.
      */
     @GuardedBy("mLock")
-    private boolean mVibrationDisabledEffective;
+    private boolean mDisableVibrationEffective;
 
     /**
-     * {@code true} if animation is disabled in battery saver mode.
-     *
-     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
-     * @see #KEY_ANIMATION_DISABLED
+     * Whether accessibility is currently enabled or not.
      */
     @GuardedBy("mLock")
-    private boolean mAnimationDisabled;
+    private boolean mAccessibilityEnabled;
 
-    /**
-     * {@code true} if sound trigger is disabled in battery saver mode
-     * in battery saver mode.
-     *
-     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
-     * @see #KEY_SOUNDTRIGGER_DISABLED
-     */
     @GuardedBy("mLock")
-    private boolean mSoundTriggerDisabled;
-
-    /**
-     * {@code true} if full backup is deferred in battery saver mode.
-     *
-     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
-     * @see #KEY_FULLBACKUP_DEFERRED
-     */
-    @GuardedBy("mLock")
-    private boolean mFullBackupDeferred;
-
-    /**
-     * {@code true} if key value backup is deferred in battery saver mode.
-     *
-     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
-     * @see #KEY_KEYVALUE_DEFERRED
-     */
-    @GuardedBy("mLock")
-    private boolean mKeyValueBackupDeferred;
-
-    /**
-     * {@code true} if network policy firewall is disabled in battery saver mode.
-     *
-     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
-     * @see #KEY_FIREWALL_DISABLED
-     */
-    @GuardedBy("mLock")
-    private boolean mFireWallDisabled;
-
-    /**
-     * {@code true} if adjust brightness is disabled in battery saver mode.
-     *
-     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
-     * @see #KEY_ADJUST_BRIGHTNESS_DISABLED
-     */
-    @GuardedBy("mLock")
-    private boolean mAdjustBrightnessDisabled;
-
-    /**
-     * {@code true} if data saver is disabled in battery saver mode.
-     *
-     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
-     * @see #KEY_DATASAVER_DISABLED
-     */
-    @GuardedBy("mLock")
-    private boolean mDataSaverDisabled;
-
-    /**
-     * {@code true} if launch boost should be disabled on battery saver.
-     */
-    @GuardedBy("mLock")
-    private boolean mLaunchBoostDisabled;
-
-    /**
-     * This is the flag to decide the gps mode in battery saver mode.
-     *
-     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
-     * @see #KEY_GPS_MODE
-     */
-    @GuardedBy("mLock")
-    private int mGpsMode;
-
-    /**
-     * This is the flag to decide the how much to adjust the screen brightness. This is
-     * the float value from 0 to 1 where 1 means don't change brightness.
-     *
-     * @see Settings.Global#BATTERY_SAVER_CONSTANTS
-     * @see #KEY_ADJUST_BRIGHTNESS_FACTOR
-     */
-    @GuardedBy("mLock")
-    private float mAdjustBrightnessFactor;
-
-    /**
-     * Whether to put all apps in the stand-by mode.
-     */
-    @GuardedBy("mLock")
-    private boolean mForceAllAppsStandby;
-
-    /**
-     * Whether to put all apps in the stand-by mode.
-     */
-    @GuardedBy("mLock")
-    private boolean mForceBackgroundCheck;
-
-    /**
-     * Whether to show non-essential sensors (e.g. edge sensors) or not.
-     */
-    @GuardedBy("mLock")
-    private boolean mOptionalSensorsDisabled;
-
-    /**
-     * Whether AOD is enabled or not.
-     */
-    @GuardedBy("mLock")
-    private boolean mAodDisabled;
-
-    /**
-     * Whether Quick Doze is enabled or not.
-     */
-    @GuardedBy("mLock")
-    private boolean mQuickDozeEnabled;
-
-    /**
-     * Whether BatterySavingStats should send tron events.
-     */
-    @GuardedBy("mLock")
-    private boolean mSendTronLog;
+    private Policy mCurrPolicy = sDefaultPolicy;
 
     private final Context mContext;
     private final ContentResolver mContentResolver;
@@ -248,30 +161,6 @@
     @GuardedBy("mLock")
     private final List<BatterySaverPolicyListener> mListeners = new ArrayList<>();
 
-    /**
-     * List of [Filename -> content] that should be written when battery saver is activated
-     * and the device is interactive.
-     *
-     * We use this to change the max CPU frequencies.
-     */
-    @GuardedBy("mLock")
-    private ArrayMap<String, String> mFilesForInteractive;
-
-    /**
-     * List of [Filename -> content] that should be written when battery saver is activated
-     * and the device is non-interactive.
-     *
-     * We use this to change the max CPU frequencies.
-     */
-    @GuardedBy("mLock")
-    private ArrayMap<String, String> mFilesForNoninteractive;
-
-    /**
-     * Whether accessibility is enabled or not.
-     */
-    @GuardedBy("mLock")
-    private boolean mAccessibilityEnabled;
-
     public interface BatterySaverPolicyListener {
         void onBatterySaverPolicyChanged(BatterySaverPolicy policy);
     }
@@ -379,36 +268,7 @@
 
         final KeyValueListParser parser = new KeyValueListParser(',');
 
-        // Non-device-specific parameters.
-        try {
-            parser.setString(setting);
-        } catch (IllegalArgumentException e) {
-            Slog.wtf(TAG, "Bad battery saver constants: " + setting);
-        }
-
-        mVibrationDisabledConfig = parser.getBoolean(KEY_VIBRATION_DISABLED, true);
-        mAnimationDisabled = parser.getBoolean(KEY_ANIMATION_DISABLED, false);
-        mSoundTriggerDisabled = parser.getBoolean(KEY_SOUNDTRIGGER_DISABLED, true);
-        mFullBackupDeferred = parser.getBoolean(KEY_FULLBACKUP_DEFERRED, true);
-        mKeyValueBackupDeferred = parser.getBoolean(KEY_KEYVALUE_DEFERRED, true);
-        mFireWallDisabled = parser.getBoolean(KEY_FIREWALL_DISABLED, false);
-        mAdjustBrightnessDisabled = parser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED, true);
-        mAdjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, 0.5f);
-        mDataSaverDisabled = parser.getBoolean(KEY_DATASAVER_DISABLED, true);
-        mLaunchBoostDisabled = parser.getBoolean(KEY_LAUNCH_BOOST_DISABLED, true);
-        mForceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY, true);
-        mForceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK, true);
-        mOptionalSensorsDisabled = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED, true);
-        mAodDisabled = parser.getBoolean(KEY_AOD_DISABLED, true);
-        mQuickDozeEnabled = parser.getBoolean(KEY_QUICK_DOZE_ENABLED, false);
-        mSendTronLog = parser.getBoolean(KEY_SEND_TRON_LOG, false);
-
-        // Get default value from Settings.Secure
-        final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE,
-                PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF);
-        mGpsMode = parser.getInt(KEY_GPS_MODE, defaultGpsMode);
-
-        // Non-device-specific parameters.
+        // Device-specific parameters.
         try {
             parser.setString(deviceSpecificSetting);
         } catch (IllegalArgumentException e) {
@@ -416,41 +276,280 @@
                     + deviceSpecificSetting);
         }
 
-        mFilesForInteractive = (new CpuFrequencies()).parseString(
-                parser.getString(KEY_CPU_FREQ_INTERACTIVE, "")).toSysFileMap();
+        final String cpuFreqInteractive = parser.getString(KEY_CPU_FREQ_INTERACTIVE, "");
+        final String cpuFreqNoninteractive = parser.getString(KEY_CPU_FREQ_NONINTERACTIVE, "");
 
-        mFilesForNoninteractive = (new CpuFrequencies()).parseString(
-                parser.getString(KEY_CPU_FREQ_NONINTERACTIVE, "")).toSysFileMap();
+        // Non-device-specific parameters.
+        try {
+            parser.setString(setting);
+        } catch (IllegalArgumentException e) {
+            Slog.wtf(TAG, "Bad battery saver constants: " + setting);
+        }
+
+        float adjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR,
+                sDefaultPolicy.adjustBrightnessFactor);
+        boolean deferFullBackup = parser.getBoolean(KEY_FULLBACKUP_DEFERRED,
+                sDefaultPolicy.deferFullBackup);
+        boolean deferKeyValueBackup = parser.getBoolean(KEY_KEYVALUE_DEFERRED,
+                sDefaultPolicy.deferKeyValueBackup);
+        boolean disableAnimation = parser.getBoolean(KEY_ANIMATION_DISABLED,
+                sDefaultPolicy.disableAnimation);
+        boolean disableAod = parser.getBoolean(KEY_AOD_DISABLED, sDefaultPolicy.disableAod);
+        boolean disableLaunchBoost = parser.getBoolean(KEY_LAUNCH_BOOST_DISABLED,
+                sDefaultPolicy.disableLaunchBoost);
+        boolean disableOptionalSensors = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED,
+                sDefaultPolicy.disableOptionalSensors);
+        boolean disableSoundTrigger = parser.getBoolean(KEY_SOUNDTRIGGER_DISABLED,
+                sDefaultPolicy.disableSoundTrigger);
+        boolean disableVibrationConfig = parser.getBoolean(KEY_VIBRATION_DISABLED,
+                sDefaultPolicy.disableVibration);
+        boolean enableAdjustBrightness = !parser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED,
+                !sDefaultPolicy.enableAdjustBrightness);
+        boolean enableDataSaver = !parser.getBoolean(KEY_ACTIVATE_DATASAVER_DISABLED,
+                !sDefaultPolicy.enableDataSaver);
+        boolean enableFirewall = !parser.getBoolean(KEY_ACTIVATE_FIREWALL_DISABLED,
+                !sDefaultPolicy.enableFirewall);
+        boolean enableQuickDoze = parser.getBoolean(KEY_QUICK_DOZE_ENABLED,
+                sDefaultPolicy.enableQuickDoze);
+        boolean forceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY,
+                sDefaultPolicy.forceAllAppsStandby);
+        boolean forceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK,
+                sDefaultPolicy.forceBackgroundCheck);
+        int gpsMode = parser.getInt(KEY_GPS_MODE, sDefaultPolicy.gpsMode);
+        boolean sendTronLog = parser.getBoolean(KEY_SEND_TRON_LOG, sDefaultPolicy.sendTronLog);
+
+        mCurrPolicy = new Policy(
+                adjustBrightnessFactor,
+                deferFullBackup,
+                deferKeyValueBackup,
+                disableAnimation,
+                disableAod,
+                disableLaunchBoost,
+                disableOptionalSensors,
+                disableSoundTrigger,
+                /* disableVibration */
+                disableVibrationConfig,
+                enableAdjustBrightness,
+                enableDataSaver,
+                enableFirewall,
+                enableQuickDoze,
+                /* filesForInteractive */
+                (new CpuFrequencies()).parseString(cpuFreqInteractive).toSysFileMap(),
+                /* filesForNoninteractive */
+                (new CpuFrequencies()).parseString(cpuFreqNoninteractive).toSysFileMap(),
+                forceAllAppsStandby,
+                forceBackgroundCheck,
+                gpsMode,
+                sendTronLog
+        );
 
         // Update the effective policy.
-        mVibrationDisabledEffective = mVibrationDisabledConfig
+        mDisableVibrationEffective = mCurrPolicy.disableVibration
                 && !mAccessibilityEnabled; // Don't disable vibration when accessibility is on.
 
         final StringBuilder sb = new StringBuilder();
 
-        if (mForceAllAppsStandby) sb.append("A");
-        if (mForceBackgroundCheck) sb.append("B");
+        if (mCurrPolicy.forceAllAppsStandby) sb.append("A");
+        if (mCurrPolicy.forceBackgroundCheck) sb.append("B");
 
-        if (mVibrationDisabledEffective) sb.append("v");
-        if (mAnimationDisabled) sb.append("a");
-        if (mSoundTriggerDisabled) sb.append("s");
-        if (mFullBackupDeferred) sb.append("F");
-        if (mKeyValueBackupDeferred) sb.append("K");
-        if (!mFireWallDisabled) sb.append("f");
-        if (!mDataSaverDisabled) sb.append("d");
-        if (!mAdjustBrightnessDisabled) sb.append("b");
+        if (mDisableVibrationEffective) sb.append("v");
+        if (mCurrPolicy.disableAnimation) sb.append("a");
+        if (mCurrPolicy.disableSoundTrigger) sb.append("s");
+        if (mCurrPolicy.deferFullBackup) sb.append("F");
+        if (mCurrPolicy.deferKeyValueBackup) sb.append("K");
+        if (mCurrPolicy.enableFirewall) sb.append("f");
+        if (mCurrPolicy.enableDataSaver) sb.append("d");
+        if (mCurrPolicy.enableAdjustBrightness) sb.append("b");
 
-        if (mLaunchBoostDisabled) sb.append("l");
-        if (mOptionalSensorsDisabled) sb.append("S");
-        if (mAodDisabled) sb.append("o");
-        if (mQuickDozeEnabled) sb.append("q");
-        if (mSendTronLog) sb.append("t");
+        if (mCurrPolicy.disableLaunchBoost) sb.append("l");
+        if (mCurrPolicy.disableOptionalSensors) sb.append("S");
+        if (mCurrPolicy.disableAod) sb.append("o");
+        if (mCurrPolicy.enableQuickDoze) sb.append("q");
+        if (mCurrPolicy.sendTronLog) sb.append("t");
 
-        sb.append(mGpsMode);
+        sb.append(mCurrPolicy.gpsMode);
 
         mEventLogKeys = sb.toString();
 
-        mBatterySavingStats.setSendTronLog(mSendTronLog);
+        mBatterySavingStats.setSendTronLog(mCurrPolicy.sendTronLog);
+    }
+
+    private static class Policy {
+        /**
+         * This is the flag to decide the how much to adjust the screen brightness. This is
+         * the float value from 0 to 1 where 1 means don't change brightness.
+         *
+         * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+         * @see #KEY_ADJUST_BRIGHTNESS_FACTOR
+         */
+        public final float adjustBrightnessFactor;
+
+        /**
+         * {@code true} if full backup is deferred in battery saver mode.
+         *
+         * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+         * @see #KEY_FULLBACKUP_DEFERRED
+         */
+        public final boolean deferFullBackup;
+
+        /**
+         * {@code true} if key value backup is deferred in battery saver mode.
+         *
+         * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+         * @see #KEY_KEYVALUE_DEFERRED
+         */
+        public final boolean deferKeyValueBackup;
+
+        /**
+         * {@code true} if animation is disabled in battery saver mode.
+         *
+         * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+         * @see #KEY_ANIMATION_DISABLED
+         */
+        public final boolean disableAnimation;
+
+        /**
+         * {@code true} if AOD is disabled in battery saver mode.
+         */
+        public final boolean disableAod;
+
+        /**
+         * {@code true} if launch boost should be disabled on battery saver.
+         */
+        public final boolean disableLaunchBoost;
+
+        /**
+         * Whether to show non-essential sensors (e.g. edge sensors) or not.
+         */
+        public final boolean disableOptionalSensors;
+
+        /**
+         * {@code true} if sound trigger is disabled in battery saver mode
+         * in battery saver mode.
+         *
+         * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+         * @see #KEY_SOUNDTRIGGER_DISABLED
+         */
+        public final boolean disableSoundTrigger;
+
+        /**
+         * {@code true} if vibration is disabled in battery saver mode.
+         *
+         * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+         * @see #KEY_VIBRATION_DISABLED
+         */
+        public final boolean disableVibration;
+
+        /**
+         * {@code true} if low power mode brightness adjustment should be turned on in battery saver
+         * mode.
+         *
+         * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+         * @see #KEY_ADJUST_BRIGHTNESS_DISABLED
+         */
+        public final boolean enableAdjustBrightness;
+
+        /**
+         * {@code true} if data saver should be turned on in battery saver mode.
+         *
+         * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+         * @see #KEY_ACTIVATE_DATASAVER_DISABLED
+         */
+        public final boolean enableDataSaver;
+
+        /**
+         * {@code true} if network policy firewall should be turned on in battery saver mode.
+         *
+         * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+         * @see #KEY_ACTIVATE_FIREWALL_DISABLED
+         */
+        public final boolean enableFirewall;
+
+        /**
+         * Whether Quick Doze is enabled or not.
+         */
+        public final boolean enableQuickDoze;
+
+        /**
+         * List of [Filename -> content] that should be written when battery saver is activated
+         * and the device is interactive.
+         *
+         * We use this to change the max CPU frequencies.
+         */
+        public final ArrayMap<String, String> filesForInteractive;
+
+        /**
+         * List of [Filename -> content] that should be written when battery saver is activated
+         * and the device is non-interactive.
+         *
+         * We use this to change the max CPU frequencies.
+         */
+        public final ArrayMap<String, String> filesForNoninteractive;
+
+        /**
+         * Whether to put all apps in the stand-by mode.
+         */
+        public final boolean forceAllAppsStandby;
+
+        /**
+         * Whether to put all apps in the stand-by mode.
+         */
+        public final boolean forceBackgroundCheck;
+
+        /**
+         * This is the flag to decide the gps mode in battery saver mode.
+         *
+         * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+         * @see #KEY_GPS_MODE
+         */
+        public final int gpsMode;
+
+        /**
+         * Whether BatterySavingStats should send tron events.
+         */
+        public final boolean sendTronLog;
+
+        Policy(
+                float adjustBrightnessFactor,
+                boolean deferFullBackup,
+                boolean deferKeyValueBackup,
+                boolean disableAnimation,
+                boolean disableAod,
+                boolean disableLaunchBoost,
+                boolean disableOptionalSensors,
+                boolean disableSoundTrigger,
+                boolean disableVibration,
+                boolean enableAdjustBrightness,
+                boolean enableDataSaver,
+                boolean enableFirewall,
+                boolean enableQuickDoze,
+                ArrayMap<String, String> filesForInteractive,
+                ArrayMap<String, String> filesForNoninteractive,
+                boolean forceAllAppsStandby,
+                boolean forceBackgroundCheck,
+                int gpsMode,
+                boolean sendTronLog) {
+
+            this.adjustBrightnessFactor = adjustBrightnessFactor;
+            this.deferFullBackup = deferFullBackup;
+            this.deferKeyValueBackup = deferKeyValueBackup;
+            this.disableAnimation = disableAnimation;
+            this.disableAod = disableAod;
+            this.disableLaunchBoost = disableLaunchBoost;
+            this.disableOptionalSensors = disableOptionalSensors;
+            this.disableSoundTrigger = disableSoundTrigger;
+            this.disableVibration = disableVibration;
+            this.enableAdjustBrightness = enableAdjustBrightness;
+            this.enableDataSaver = enableDataSaver;
+            this.enableFirewall = enableFirewall;
+            this.enableQuickDoze = enableQuickDoze;
+            this.filesForInteractive = filesForInteractive;
+            this.filesForNoninteractive = filesForNoninteractive;
+            this.forceAllAppsStandby = forceAllAppsStandby;
+            this.forceBackgroundCheck = forceBackgroundCheck;
+            this.gpsMode = gpsMode;
+            this.sendTronLog = sendTronLog;
+        }
     }
 
     /**
@@ -473,47 +572,47 @@
             switch (type) {
                 case ServiceType.GPS:
                     return builder.setBatterySaverEnabled(realMode)
-                            .setGpsMode(mGpsMode)
+                            .setGpsMode(mCurrPolicy.gpsMode)
                             .build();
                 case ServiceType.ANIMATION:
-                    return builder.setBatterySaverEnabled(mAnimationDisabled)
+                    return builder.setBatterySaverEnabled(mCurrPolicy.disableAnimation)
                             .build();
                 case ServiceType.FULL_BACKUP:
-                    return builder.setBatterySaverEnabled(mFullBackupDeferred)
+                    return builder.setBatterySaverEnabled(mCurrPolicy.deferFullBackup)
                             .build();
                 case ServiceType.KEYVALUE_BACKUP:
-                    return builder.setBatterySaverEnabled(mKeyValueBackupDeferred)
+                    return builder.setBatterySaverEnabled(mCurrPolicy.deferKeyValueBackup)
                             .build();
                 case ServiceType.NETWORK_FIREWALL:
-                    return builder.setBatterySaverEnabled(!mFireWallDisabled)
+                    return builder.setBatterySaverEnabled(mCurrPolicy.enableFirewall)
                             .build();
                 case ServiceType.SCREEN_BRIGHTNESS:
-                    return builder.setBatterySaverEnabled(!mAdjustBrightnessDisabled)
-                            .setBrightnessFactor(mAdjustBrightnessFactor)
+                    return builder.setBatterySaverEnabled(mCurrPolicy.enableAdjustBrightness)
+                            .setBrightnessFactor(mCurrPolicy.adjustBrightnessFactor)
                             .build();
                 case ServiceType.DATA_SAVER:
-                    return builder.setBatterySaverEnabled(!mDataSaverDisabled)
+                    return builder.setBatterySaverEnabled(mCurrPolicy.enableDataSaver)
                             .build();
                 case ServiceType.SOUND:
-                    return builder.setBatterySaverEnabled(mSoundTriggerDisabled)
+                    return builder.setBatterySaverEnabled(mCurrPolicy.disableSoundTrigger)
                             .build();
                 case ServiceType.VIBRATION:
-                    return builder.setBatterySaverEnabled(mVibrationDisabledEffective)
+                    return builder.setBatterySaverEnabled(mDisableVibrationEffective)
                             .build();
                 case ServiceType.FORCE_ALL_APPS_STANDBY:
-                    return builder.setBatterySaverEnabled(mForceAllAppsStandby)
+                    return builder.setBatterySaverEnabled(mCurrPolicy.forceAllAppsStandby)
                             .build();
                 case ServiceType.FORCE_BACKGROUND_CHECK:
-                    return builder.setBatterySaverEnabled(mForceBackgroundCheck)
+                    return builder.setBatterySaverEnabled(mCurrPolicy.forceBackgroundCheck)
                             .build();
                 case ServiceType.OPTIONAL_SENSORS:
-                    return builder.setBatterySaverEnabled(mOptionalSensorsDisabled)
+                    return builder.setBatterySaverEnabled(mCurrPolicy.disableOptionalSensors)
                             .build();
                 case ServiceType.AOD:
-                    return builder.setBatterySaverEnabled(mAodDisabled)
+                    return builder.setBatterySaverEnabled(mCurrPolicy.disableAod)
                             .build();
                 case ServiceType.QUICK_DOZE:
-                    return builder.setBatterySaverEnabled(mQuickDozeEnabled)
+                    return builder.setBatterySaverEnabled(mCurrPolicy.enableQuickDoze)
                             .build();
                 default:
                     return builder.setBatterySaverEnabled(realMode)
@@ -524,19 +623,20 @@
 
     public int getGpsMode() {
         synchronized (mLock) {
-            return mGpsMode;
+            return mCurrPolicy.gpsMode;
         }
     }
 
     public ArrayMap<String, String> getFileValues(boolean interactive) {
         synchronized (mLock) {
-            return interactive ? mFilesForInteractive : mFilesForNoninteractive;
+            return interactive ? mCurrPolicy.filesForInteractive
+                    : mCurrPolicy.filesForNoninteractive;
         }
     }
 
     public boolean isLaunchBoostDisabled() {
         synchronized (mLock) {
-            return mLaunchBoostDisabled;
+            return mCurrPolicy.disableLaunchBoost;
         }
     }
 
@@ -560,31 +660,35 @@
 
             pw.println();
             pw.println("  mAccessibilityEnabled=" + mAccessibilityEnabled);
-            pw.println("  " + KEY_VIBRATION_DISABLED + ":config=" + mVibrationDisabledConfig);
-            pw.println("  " + KEY_VIBRATION_DISABLED + ":effective=" + mVibrationDisabledEffective);
-            pw.println("  " + KEY_ANIMATION_DISABLED + "=" + mAnimationDisabled);
-            pw.println("  " + KEY_FULLBACKUP_DEFERRED + "=" + mFullBackupDeferred);
-            pw.println("  " + KEY_KEYVALUE_DEFERRED + "=" + mKeyValueBackupDeferred);
-            pw.println("  " + KEY_FIREWALL_DISABLED + "=" + mFireWallDisabled);
-            pw.println("  " + KEY_DATASAVER_DISABLED + "=" + mDataSaverDisabled);
-            pw.println("  " + KEY_LAUNCH_BOOST_DISABLED + "=" + mLaunchBoostDisabled);
-            pw.println("  " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + mAdjustBrightnessDisabled);
-            pw.println("  " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mAdjustBrightnessFactor);
-            pw.println("  " + KEY_GPS_MODE + "=" + mGpsMode);
-            pw.println("  " + KEY_FORCE_ALL_APPS_STANDBY + "=" + mForceAllAppsStandby);
-            pw.println("  " + KEY_FORCE_BACKGROUND_CHECK + "=" + mForceBackgroundCheck);
-            pw.println("  " + KEY_OPTIONAL_SENSORS_DISABLED + "=" + mOptionalSensorsDisabled);
-            pw.println("  " + KEY_AOD_DISABLED + "=" + mAodDisabled);
-            pw.println("  " + KEY_QUICK_DOZE_ENABLED + "=" + mQuickDozeEnabled);
-            pw.println("  " + KEY_SEND_TRON_LOG + "=" + mSendTronLog);
+            pw.println("  " + KEY_VIBRATION_DISABLED + ":config=" + mCurrPolicy.disableVibration);
+            pw.println("  " + KEY_VIBRATION_DISABLED + ":effective=" + mDisableVibrationEffective);
+            pw.println("  " + KEY_ANIMATION_DISABLED + "=" + mCurrPolicy.disableAnimation);
+            pw.println("  " + KEY_FULLBACKUP_DEFERRED + "=" + mCurrPolicy.deferFullBackup);
+            pw.println("  " + KEY_KEYVALUE_DEFERRED + "=" + mCurrPolicy.deferKeyValueBackup);
+            pw.println("  " + KEY_ACTIVATE_FIREWALL_DISABLED + "=" + !mCurrPolicy.enableFirewall);
+            pw.println("  " + KEY_ACTIVATE_DATASAVER_DISABLED + "=" + !mCurrPolicy.enableDataSaver);
+            pw.println("  " + KEY_LAUNCH_BOOST_DISABLED + "=" + mCurrPolicy.disableLaunchBoost);
+            pw.println("  " + KEY_ADJUST_BRIGHTNESS_DISABLED + "="
+                    + !mCurrPolicy.enableAdjustBrightness);
+            pw.println(
+                    "  " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mCurrPolicy.adjustBrightnessFactor);
+            pw.println("  " + KEY_GPS_MODE + "=" + mCurrPolicy.gpsMode);
+            pw.println("  " + KEY_FORCE_ALL_APPS_STANDBY + "=" + mCurrPolicy.forceAllAppsStandby);
+            pw.println("  " + KEY_FORCE_BACKGROUND_CHECK + "=" + mCurrPolicy.forceBackgroundCheck);
+            pw.println("  " + KEY_OPTIONAL_SENSORS_DISABLED + "="
+                    + mCurrPolicy.disableOptionalSensors);
+            pw.println("  " + KEY_AOD_DISABLED + "=" + mCurrPolicy.disableAod);
+            pw.println("  " + KEY_SOUNDTRIGGER_DISABLED + "=" + mCurrPolicy.disableSoundTrigger);
+            pw.println("  " + KEY_QUICK_DOZE_ENABLED + "=" + mCurrPolicy.enableQuickDoze);
+            pw.println("  " + KEY_SEND_TRON_LOG + "=" + mCurrPolicy.sendTronLog);
             pw.println();
 
             pw.print("  Interactive File values:\n");
-            dumpMap(pw, "    ", mFilesForInteractive);
+            dumpMap(pw, "    ", mCurrPolicy.filesForInteractive);
             pw.println();
 
             pw.print("  Noninteractive File values:\n");
-            dumpMap(pw, "    ", mFilesForNoninteractive);
+            dumpMap(pw, "    ", mCurrPolicy.filesForNoninteractive);
         }
     }
 
diff --git a/services/core/java/com/android/server/power/OWNERS b/services/core/java/com/android/server/power/OWNERS
index d118c4e..20e4985 100644
--- a/services/core/java/com/android/server/power/OWNERS
+++ b/services/core/java/com/android/server/power/OWNERS
@@ -2,3 +2,4 @@
 
 per-file BatterySaverPolicy.java=omakoto@google.com
 per-file ShutdownThread.java=fkupolov@google.com
+per-file ThermalManagerService.java=wvw@google.com
\ No newline at end of file
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 43a9c78..29d6237 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -4439,6 +4439,42 @@
         }
 
         @Override // Binder call
+        public boolean setDynamicPowerSavings(boolean dynamicPowerSavingsEnabled,
+                int disableThreshold) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER,
+                    "updateDynamicPowerSavings");
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                final ContentResolver resolver = mContext.getContentResolver();
+                boolean success = Settings.Global.putInt(resolver,
+                        Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
+                        disableThreshold);
+                if (success) {
+                    // abort updating if we weren't able to succeed on the threshold
+                    success &= Settings.Global.putInt(resolver,
+                            Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED,
+                            dynamicPowerSavingsEnabled ? 1 : 0);
+                }
+                return success;
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public int getPowerSaveMode() {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER, null);
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return Settings.Global.getInt(mContext.getContentResolver(),
+                        Settings.Global.AUTOMATIC_POWER_SAVER_MODE,
+                        PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
         public boolean isDeviceIdleMode() {
             final long ident = Binder.clearCallingIdentity();
             try {
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
new file mode 100644
index 0000000..812fd82
--- /dev/null
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2018 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.power;
+
+import android.content.Context;
+import android.hardware.thermal.V1_0.ThermalStatus;
+import android.hardware.thermal.V1_0.ThermalStatusCode;
+import android.hardware.thermal.V1_1.IThermalCallback;
+import android.hardware.thermal.V2_0.IThermalChangedCallback;
+import android.hardware.thermal.V2_0.ThrottlingSeverity;
+import android.os.Binder;
+import android.os.HwBinder;
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
+import android.os.PowerManager;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
+import com.android.server.FgThread;
+import com.android.server.SystemService;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * This is a system service that listens to HAL thermal events and dispatch those to listeners.
+ * <p>The service will also trigger actions based on severity of the throttling status.</p>
+ *
+ * @hide
+ */
+public class ThermalManagerService extends SystemService {
+    private static final String TAG = ThermalManagerService.class.getSimpleName();
+
+    /** Registered observers of the thermal changed events. Cookie is used to store type */
+    @GuardedBy("mLock")
+    private final RemoteCallbackList<IThermalEventListener> mThermalEventListeners =
+            new RemoteCallbackList<>();
+
+    /** Lock to protect HAL handles and listen list. */
+    private final Object mLock = new Object();
+
+    /** Newly registered callback. */
+    @GuardedBy("mLock")
+    private IThermalEventListener mNewListenerCallback = null;
+
+    /** Newly registered callback type, null means not filter type. */
+    @GuardedBy("mLock")
+    private Integer mNewListenerType = null;
+
+    /** Local PMS handle. */
+    private final PowerManager mPowerManager;
+
+    /** Proxy object for the Thermal HAL 2.0 service. */
+    @GuardedBy("mLock")
+    private android.hardware.thermal.V2_0.IThermal mThermalHal20 = null;
+
+    /** Proxy object for the Thermal HAL 1.1 service. */
+    @GuardedBy("mLock")
+    private android.hardware.thermal.V1_1.IThermal mThermalHal11 = null;
+
+    /** Cookie for matching the right end point. */
+    private static final int THERMAL_HAL_DEATH_COOKIE = 5612;
+
+    /** HWbinder callback for Thermal HAL 2.0. */
+    private final IThermalChangedCallback.Stub mThermalCallback20 =
+            new IThermalChangedCallback.Stub() {
+                @Override
+                public void notifyThrottling(
+                        android.hardware.thermal.V2_0.Temperature temperature) {
+                    android.os.Temperature thermalSvcTemp = new android.os.Temperature(
+                            temperature.value, temperature.type, temperature.name,
+                            temperature.throttlingStatus);
+                    final long token = Binder.clearCallingIdentity();
+                    try {
+                        notifyThrottlingImpl(thermalSvcTemp);
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            };
+
+    /** HWbinder callback for Thermal HAL 1.1. */
+    private final IThermalCallback.Stub mThermalCallback11 =
+            new IThermalCallback.Stub() {
+                @Override
+                public void notifyThrottling(boolean isThrottling,
+                        android.hardware.thermal.V1_0.Temperature temperature) {
+                    android.os.Temperature thermalSvcTemp = new android.os.Temperature(
+                            temperature.currentValue, temperature.type, temperature.name,
+                            isThrottling ? ThrottlingSeverity.SEVERE : ThrottlingSeverity.NONE);
+                    final long token = Binder.clearCallingIdentity();
+                    try {
+                        notifyThrottlingImpl(thermalSvcTemp);
+                    } finally {
+                        Binder.restoreCallingIdentity(token);
+                    }
+                }
+            };
+
+    public ThermalManagerService(Context context) {
+        super(context);
+        mPowerManager = context.getSystemService(PowerManager.class);
+    }
+
+    private void setNewListener(IThermalEventListener listener, Integer type) {
+        synchronized (mLock) {
+            mNewListenerCallback = listener;
+            mNewListenerType = type;
+        }
+    }
+
+    private void clearNewListener() {
+        synchronized (mLock) {
+            mNewListenerCallback = null;
+            mNewListenerType = null;
+        }
+    }
+
+    private final IThermalService.Stub mService = new IThermalService.Stub() {
+        @Override
+        public void registerThermalEventListener(IThermalEventListener listener) {
+            synchronized (mLock) {
+                mThermalEventListeners.register(listener, null);
+                // Notify its callback after new client registered.
+                setNewListener(listener, null);
+                long token = Binder.clearCallingIdentity();
+                try {
+                    notifyCurrentTemperaturesLocked();
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                    clearNewListener();
+                }
+            }
+        }
+
+        @Override
+        public void registerThermalEventListenerWithType(IThermalEventListener listener, int type) {
+            synchronized (mLock) {
+                mThermalEventListeners.register(listener, new Integer(type));
+                setNewListener(listener, new Integer(type));
+                // Notify its callback after new client registered.
+                long token = Binder.clearCallingIdentity();
+                try {
+                    notifyCurrentTemperaturesLocked();
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                    clearNewListener();
+                }
+            }
+        }
+
+        @Override
+        public void unregisterThermalEventListener(IThermalEventListener listener) {
+            synchronized (mLock) {
+                long token = Binder.clearCallingIdentity();
+                try {
+                    mThermalEventListeners.unregister(listener);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        }
+
+        @Override
+        public List<android.os.Temperature> getCurrentTemperatures() {
+            List<android.os.Temperature> ret;
+            long token = Binder.clearCallingIdentity();
+            try {
+                ret = getCurrentTemperaturesInternal(false, 0 /* not used */);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+            return ret;
+        }
+
+        @Override
+        public List<android.os.Temperature> getCurrentTemperaturesWithType(int type) {
+            List<android.os.Temperature> ret;
+            long token = Binder.clearCallingIdentity();
+            try {
+                ret = getCurrentTemperaturesInternal(true, type);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+            return ret;
+        }
+
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
+            pw.println("ThermalEventListeners dump:");
+            synchronized (mLock) {
+                mThermalEventListeners.dump(pw, "\t");
+                pw.println("ThermalHAL 1.1 connected: " + (mThermalHal11 != null ? "yes" : "no"));
+                pw.println("ThermalHAL 2.0 connected: " + (mThermalHal20 != null ? "yes" : "no"));
+            }
+        }
+    };
+
+    private List<android.os.Temperature> getCurrentTemperaturesInternal(boolean shouldFilter,
+            int type) {
+        List<android.os.Temperature> ret = new ArrayList<>();
+        synchronized (mLock) {
+            if (mThermalHal20 == null) {
+                return ret;
+            }
+            try {
+                mThermalHal20.getCurrentTemperatures(shouldFilter, type,
+                        (ThermalStatus status,
+                                ArrayList<android.hardware.thermal.V2_0.Temperature>
+                                        temperatures) -> {
+                            if (ThermalStatusCode.SUCCESS == status.code) {
+                                for (android.hardware.thermal.V2_0.Temperature
+                                        temperature : temperatures) {
+                                    ret.add(new android.os.Temperature(
+                                            temperature.value, temperature.type, temperature.name,
+                                            temperature.throttlingStatus));
+                                }
+                            } else {
+                                Slog.e(TAG,
+                                        "Couldn't get temperatures because of HAL error: "
+                                                + status.debugMessage);
+                            }
+
+                        });
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Couldn't getCurrentTemperatures, reconnecting...", e);
+                connectToHalLocked();
+                // Post to listeners after reconnect to HAL.
+                notifyCurrentTemperaturesLocked();
+            }
+        }
+        return ret;
+    }
+
+    private void notifyListener(android.os.Temperature temperature, IThermalEventListener listener,
+            Integer type) {
+        // Skip if listener registered with a different type
+        if (type != null && type != temperature.getType()) {
+            return;
+        }
+        final boolean thermalCallbackQueued = FgThread.getHandler().post(() -> {
+            try {
+                listener.notifyThrottling(temperature);
+            } catch (RemoteException | RuntimeException e) {
+                Slog.e(TAG, "Thermal callback failed to call", e);
+            }
+        });
+        if (!thermalCallbackQueued) {
+            Slog.e(TAG, "Thermal callback failed to queue");
+        }
+    }
+
+    private void notifyThrottlingImpl(android.os.Temperature temperature) {
+        synchronized (mLock) {
+            // Thermal Shutdown for Skin temperature
+            if (temperature.getStatus() == android.os.Temperature.THROTTLING_SHUTDOWN
+                    && temperature.getType() == android.os.Temperature.TYPE_SKIN) {
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    mPowerManager.shutdown(false, PowerManager.SHUTDOWN_THERMAL_STATE, false);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+
+            if (mNewListenerCallback != null) {
+                // Only notify current newly added callback.
+                notifyListener(temperature, mNewListenerCallback, mNewListenerType);
+            } else {
+                final int length = mThermalEventListeners.beginBroadcast();
+                try {
+                    for (int i = 0; i < length; i++) {
+                        final IThermalEventListener listener =
+                                mThermalEventListeners.getBroadcastItem(i);
+                        final Integer type = (Integer) mThermalEventListeners.getBroadcastCookie(i);
+                        notifyListener(temperature, listener, type);
+                    }
+                } finally {
+                    mThermalEventListeners.finishBroadcast();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(Context.THERMAL_SERVICE, mService);
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+            onActivityManagerReady();
+        }
+    }
+
+    private void notifyCurrentTemperaturesCallbackLocked(ThermalStatus status,
+            ArrayList<android.hardware.thermal.V2_0.Temperature> temperatures) {
+        if (ThermalStatusCode.SUCCESS != status.code) {
+            Slog.e(TAG, "Couldn't get temperatures because of HAL error: "
+                    + status.debugMessage);
+            return;
+        }
+        for (android.hardware.thermal.V2_0.Temperature temperature : temperatures) {
+            android.os.Temperature thermal_svc_temp =
+                    new android.os.Temperature(
+                            temperature.value, temperature.type,
+                            temperature.name,
+                            temperature.throttlingStatus);
+            notifyThrottlingImpl(thermal_svc_temp);
+        }
+    }
+
+    private void notifyCurrentTemperaturesLocked() {
+        if (mThermalHal20 == null) {
+            return;
+        }
+        try {
+            mThermalHal20.getCurrentTemperatures(false, 0,
+                    this::notifyCurrentTemperaturesCallbackLocked);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Couldn't get temperatures, reconnecting...", e);
+            connectToHalLocked();
+        }
+    }
+
+    private void onActivityManagerReady() {
+        synchronized (mLock) {
+            connectToHalLocked();
+            // Post to listeners after connect to HAL.
+            notifyCurrentTemperaturesLocked();
+        }
+    }
+
+    final class DeathRecipient implements HwBinder.DeathRecipient {
+        @Override
+        public void serviceDied(long cookie) {
+            if (cookie == THERMAL_HAL_DEATH_COOKIE) {
+                Slog.e(TAG, "Thermal HAL service died cookie: " + cookie);
+                synchronized (mLock) {
+                    connectToHalLocked();
+                    // Post to listeners after reconnect to HAL.
+                    notifyCurrentTemperaturesLocked();
+                }
+            }
+        }
+    }
+
+    private void connectToHalLocked() {
+        try {
+            mThermalHal20 = android.hardware.thermal.V2_0.IThermal.getService();
+            mThermalHal20.linkToDeath(new DeathRecipient(), THERMAL_HAL_DEATH_COOKIE);
+            mThermalHal20.registerThermalChangedCallback(mThermalCallback20, false,
+                    0 /* not used */);
+        } catch (NoSuchElementException | RemoteException e) {
+            Slog.e(TAG, "Thermal HAL 2.0 service not connected, trying 1.1.");
+            mThermalHal20 = null;
+            try {
+                mThermalHal11 = android.hardware.thermal.V1_1.IThermal.getService();
+                mThermalHal11.linkToDeath(new DeathRecipient(), THERMAL_HAL_DEATH_COOKIE);
+                mThermalHal11.registerThermalCallback(mThermalCallback11);
+            } catch (NoSuchElementException | RemoteException e2) {
+                Slog.e(TAG,
+                        "Thermal HAL 1.1 service not connected, no thermal call back "
+                                + "will be called.");
+                mThermalHal11 = null;
+            }
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
index 5569822..6400c88 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
@@ -93,8 +93,8 @@
      */
     private final Plugin[] mPlugins;
 
-    public static final int REASON_AUTOMATIC_ON = 0;
-    public static final int REASON_AUTOMATIC_OFF = 1;
+    public static final int REASON_PERCENTAGE_AUTOMATIC_ON = 0;
+    public static final int REASON_PERCENTAGE_AUTOMATIC_OFF = 1;
     public static final int REASON_MANUAL_ON = 2;
     public static final int REASON_MANUAL_OFF = 3;
     public static final int REASON_STICKY_RESTORE = 4;
@@ -102,6 +102,8 @@
     public static final int REASON_POLICY_CHANGED = 6;
     public static final int REASON_PLUGGED_IN = 7;
     public static final int REASON_SETTING_CHANGED = 8;
+    public static final int REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON = 9;
+    public static final int REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF = 10;
 
     /**
      * Plugin interface. All methods are guaranteed to be called on the same (handler) thread.
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
index 20ceed43..f262f6d 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.database.ContentObserver;
 import android.os.Handler;
+import android.os.PowerManager;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Settings.Global;
@@ -87,6 +88,11 @@
     /** Config flag to track if battery saver's sticky behaviour is disabled. */
     private final boolean mBatterySaverStickyBehaviourDisabled;
 
+    /** Config flag to track default disable threshold for Dynamic Power Savings enabled battery
+     * saver. */
+    @GuardedBy("mLock")
+    private final int mDynamicPowerSavingsDefaultDisableThreshold;
+
     /**
      * Previously known value of Global.LOW_POWER_MODE_TRIGGER_LEVEL.
      * (Currently only used in dumpsys.)
@@ -94,6 +100,23 @@
     @GuardedBy("mLock")
     private int mSettingBatterySaverTriggerThreshold;
 
+    /** Previously known value of Global.AUTOMATIC_POWER_SAVER_MODE. */
+    @GuardedBy("mLock")
+    private int mSettingAutomaticBatterySaver;
+
+    /** When to disable battery saver again if it was enabled due to an external suggestion.
+     *  Corresponds to Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD.
+     */
+    @GuardedBy("mLock")
+    private int mDynamicPowerSavingsDisableThreshold;
+
+    /**
+     * Whether we've received a suggestion that battery saver should be on from an external app.
+     * Updates when Global.DYNAMIC_POWER_SAVINGS_ENABLED changes.
+     */
+    @GuardedBy("mLock")
+    private boolean mDynamicPowerSavingsBatterySaver;
+
     /**
      * Whether BS has been manually disabled while the battery level is low, in which case we
      * shouldn't auto re-enable it until the battery level is not low.
@@ -130,13 +153,15 @@
 
         mBatterySaverStickyBehaviourDisabled = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled);
+        mDynamicPowerSavingsDefaultDisableThreshold = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold);
     }
 
     private boolean isBatterySaverEnabled() {
         return mBatterySaverController.isEnabled();
     }
 
-    private boolean isAutoBatterySaverConfigured() {
+    private boolean isAutoBatterySaverConfiguredLocked() {
         return mSettingBatterySaverTriggerThreshold > 0;
     }
 
@@ -165,6 +190,15 @@
             cr.registerContentObserver(Settings.Global.getUriFor(
                     Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
                     false, mSettingsObserver, UserHandle.USER_SYSTEM);
+            cr.registerContentObserver(Settings.Global.getUriFor(
+                    Global.AUTOMATIC_POWER_SAVER_MODE),
+                    false, mSettingsObserver, UserHandle.USER_SYSTEM);
+            cr.registerContentObserver(Settings.Global.getUriFor(
+                    Global.DYNAMIC_POWER_SAVINGS_ENABLED),
+                    false, mSettingsObserver, UserHandle.USER_SYSTEM);
+            cr.registerContentObserver(Settings.Global.getUriFor(
+                    Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD),
+                    false, mSettingsObserver, UserHandle.USER_SYSTEM);
 
             synchronized (mLock) {
 
@@ -202,11 +236,20 @@
                 Settings.Global.LOW_POWER_MODE, 0) != 0;
         final boolean lowPowerModeEnabledSticky = getGlobalSetting(
                 Settings.Global.LOW_POWER_MODE_STICKY, 0) != 0;
+        final boolean dynamicPowerSavingsBatterySaver = getGlobalSetting(
+                Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0) != 0;
         final int lowPowerModeTriggerLevel = getGlobalSetting(
                 Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
+        final int automaticBatterySaver = getGlobalSetting(
+                Global.AUTOMATIC_POWER_SAVER_MODE,
+                PowerManager.POWER_SAVER_MODE_PERCENTAGE);
+        final int dynamicPowerSavingsDisableThreshold = getGlobalSetting(
+                Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
+                mDynamicPowerSavingsDefaultDisableThreshold);
 
         setSettingsLocked(lowPowerModeEnabled, lowPowerModeEnabledSticky,
-                lowPowerModeTriggerLevel);
+                lowPowerModeTriggerLevel, automaticBatterySaver, dynamicPowerSavingsBatterySaver,
+                dynamicPowerSavingsDisableThreshold);
     }
 
     /**
@@ -218,11 +261,16 @@
     @GuardedBy("mLock")
     @VisibleForTesting
     void setSettingsLocked(boolean batterySaverEnabled, boolean batterySaverEnabledSticky,
-            int batterySaverTriggerThreshold) {
+            int batterySaverTriggerThreshold, int automaticBatterySaver,
+            boolean dynamicPowerSavingsBatterySaver, int dynamicPowerSavingsDisableThreshold) {
         if (DEBUG) {
             Slog.d(TAG, "setSettings: enabled=" + batterySaverEnabled
                     + " sticky=" + batterySaverEnabledSticky
-                    + " threshold=" + batterySaverTriggerThreshold);
+                    + " threshold=" + batterySaverTriggerThreshold
+                    + " automaticBatterySaver=" + automaticBatterySaver
+                    + " dynamicPowerSavingsBatterySaver=" + dynamicPowerSavingsBatterySaver
+                    + " dynamicPowerSavingsDisableThreshold="
+                    + dynamicPowerSavingsDisableThreshold);
         }
 
         mSettingsLoaded = true;
@@ -232,14 +280,23 @@
                 mSettingBatterySaverEnabledSticky != batterySaverEnabledSticky;
         final boolean thresholdChanged
                 = mSettingBatterySaverTriggerThreshold != batterySaverTriggerThreshold;
+        final boolean automaticModeChanged = mSettingAutomaticBatterySaver != automaticBatterySaver;
+        final boolean dynamicPowerSavingsThresholdChanged =
+                mDynamicPowerSavingsDisableThreshold != dynamicPowerSavingsDisableThreshold;
+        final boolean dynamicPowerSavingsBatterySaverChanged =
+                mDynamicPowerSavingsBatterySaver != dynamicPowerSavingsBatterySaver;
 
-        if (!(enabledChanged || stickyChanged || thresholdChanged)) {
+        if (!(enabledChanged || stickyChanged || thresholdChanged || automaticModeChanged
+                || dynamicPowerSavingsThresholdChanged || dynamicPowerSavingsBatterySaverChanged)) {
             return;
         }
 
         mSettingBatterySaverEnabled = batterySaverEnabled;
         mSettingBatterySaverEnabledSticky = batterySaverEnabledSticky;
         mSettingBatterySaverTriggerThreshold = batterySaverTriggerThreshold;
+        mSettingAutomaticBatterySaver = automaticBatterySaver;
+        mDynamicPowerSavingsDisableThreshold = dynamicPowerSavingsDisableThreshold;
+        mDynamicPowerSavingsBatterySaver = dynamicPowerSavingsBatterySaver;
 
         if (thresholdChanged) {
             // To avoid spamming the event log, we throttle logging here.
@@ -287,6 +344,17 @@
         }
     }
 
+    @GuardedBy("mLock")
+    private boolean isBatteryLowLocked() {
+        final boolean percentageLow =
+                mSettingAutomaticBatterySaver == PowerManager.POWER_SAVER_MODE_PERCENTAGE
+                && mIsBatteryLevelLow;
+        final boolean dynamicPowerSavingsLow =
+                mSettingAutomaticBatterySaver == PowerManager.POWER_SAVER_MODE_DYNAMIC
+                && mBatteryLevel <= mDynamicPowerSavingsDisableThreshold;
+        return percentageLow || dynamicPowerSavingsLow;
+    }
+
     /**
      * Decide whether to auto-start / stop battery saver.
      */
@@ -299,12 +367,14 @@
                     + " mIsBatteryLevelLow=" + mIsBatteryLevelLow
                     + " mBatterySaverSnoozing=" + mBatterySaverSnoozing
                     + " mIsPowered=" + mIsPowered
+                    + " mSettingAutomaticBatterySaver=" + mSettingAutomaticBatterySaver
                     + " mSettingBatterySaverEnabledSticky=" + mSettingBatterySaverEnabledSticky);
         }
         if (!(mBootCompleted && mSettingsLoaded && mBatteryStatusSet)) {
             return; // Not fully initialized yet.
         }
-        if (!mIsBatteryLevelLow) {
+
+        if (!isBatteryLowLocked()) {
             updateSnoozingLocked(false, "Battery not low");
         }
         if (mIsPowered) {
@@ -319,20 +389,35 @@
                     BatterySaverController.REASON_STICKY_RESTORE,
                     "Sticky restore");
 
-        } else if (mIsBatteryLevelLow) {
-            if (!mBatterySaverSnoozing && isAutoBatterySaverConfigured()) {
+        } else if (mSettingAutomaticBatterySaver
+                == PowerManager.POWER_SAVER_MODE_PERCENTAGE
+                && isAutoBatterySaverConfiguredLocked()) {
+            if (mIsBatteryLevelLow && !mBatterySaverSnoozing) {
                 enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ false,
-                        BatterySaverController.REASON_AUTOMATIC_ON,
-                        "Auto ON");
+                        BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_ON,
+                        "Percentage Auto ON");
+            } else {
+                // Battery not low
+                enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
+                        BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_OFF,
+                        "Percentage Auto OFF");
             }
-        } else { // Battery not low
-            enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
-                    BatterySaverController.REASON_AUTOMATIC_OFF,
-                    "Auto OFF");
+        } else if (mSettingAutomaticBatterySaver
+                == PowerManager.POWER_SAVER_MODE_DYNAMIC) {
+            if (mBatteryLevel >= mDynamicPowerSavingsDisableThreshold) {
+                enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
+                        BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF,
+                        "Dynamic Warning Auto OFF");
+            } else if (mDynamicPowerSavingsBatterySaver && !mBatterySaverSnoozing) {
+                enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ false,
+                        BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON,
+                        "Dynamic Warning Auto ON");
+            }
         }
+        // do nothing if automatic battery saver mode = PERCENTAGE and low warning threshold = 0%
     }
 
-    /**
+  /**
      * {@link com.android.server.power.PowerManagerService} calls it when
      * {@link android.os.PowerManager#setPowerSaveMode} is called.
      *
@@ -383,7 +468,7 @@
                 // When battery saver is disabled manually (while battery saver is enabled)
                 // when the battery level is low, we "snooze" BS -- i.e. disable auto battery saver.
                 // We resume auto-BS once the battery level is not low, or the device is plugged in.
-                if (isBatterySaverEnabled() && mIsBatteryLevelLow) {
+                if (isBatterySaverEnabled() && isBatteryLowLocked()) {
                     updateSnoozingLocked(true, "Manual snooze");
                 }
             }
diff --git a/services/core/java/com/android/server/role/RemoteRoleControllerService.java b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
index b670291..7d34270 100644
--- a/services/core/java/com/android/server/role/RemoteRoleControllerService.java
+++ b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
@@ -16,10 +16,10 @@
 
 package com.android.server.role;
 
-import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.annotation.WorkerThread;
 import android.app.role.IRoleManagerCallback;
 import android.app.role.RoleManagerCallback;
 import android.content.ComponentName;
@@ -34,6 +34,7 @@
 import android.rolecontrollerservice.RoleControllerService;
 import android.util.Slog;
 
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.function.pooled.PooledLambda;
 
 import java.util.ArrayDeque;
@@ -44,9 +45,13 @@
  */
 public class RemoteRoleControllerService {
 
+    static final boolean DEBUG = false;
     private static final String LOG_TAG = RemoteRoleControllerService.class.getSimpleName();
 
     @NonNull
+    private static final Handler sCallbackHandler = BackgroundThread.getHandler();
+
+    @NonNull
     private final Connection mConnection;
 
     public RemoteRoleControllerService(@UserIdInt int userId, @NonNull Context context) {
@@ -87,6 +92,16 @@
                 service.onClearRoleHolders(roleName, callbackDelegate), callback));
     }
 
+    /**
+     * Performs granting of default roles and permissions and appops
+     *
+     * @see RoleControllerService#onGrantDefaultRoles(RoleManagerCallback)
+     */
+    public void onGrantDefaultRoles(@NonNull IRoleManagerCallback callback) {
+        mConnection.enqueueCall(
+                new Connection.Call(IRoleControllerService::onGrantDefaultRoles, callback));
+    }
+
     private static final class Connection implements ServiceConnection {
 
         private static final long UNBIND_DELAY_MILLIS = 15 * 1000;
@@ -106,9 +121,6 @@
         private final Queue<Call> mPendingCalls = new ArrayDeque<>();
 
         @NonNull
-        private final Handler mMainHandler = Handler.getMain();
-
-        @NonNull
         private final Runnable mUnbindRunnable = this::unbind;
 
         Connection(@UserIdInt int userId, @NonNull Context context) {
@@ -116,14 +128,14 @@
             mContext = context;
         }
 
-        @MainThread
         @Override
+        @WorkerThread
         public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder service) {
             mService = IRoleControllerService.Stub.asInterface(service);
             executePendingCalls();
         }
 
-        @MainThread
+        @WorkerThread
         private void executePendingCalls() {
             while (!mPendingCalls.isEmpty()) {
                 Call call = mPendingCalls.poll();
@@ -132,26 +144,33 @@
             scheduleUnbind();
         }
 
-        @MainThread
         @Override
+        @WorkerThread
         public void onServiceDisconnected(@NonNull ComponentName name) {
             mService = null;
         }
 
-        @MainThread
         @Override
+        @WorkerThread
         public void onBindingDied(@NonNull ComponentName name) {
             unbind();
         }
 
         public void enqueueCall(@NonNull Call call) {
-            mMainHandler.post(PooledLambda.obtainRunnable(this::executeCall, call));
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "Enqueue " + call);
+            }
+            sCallbackHandler.executeOrSendMessage(PooledLambda.obtainMessage(
+                    Connection::executeCall, this, call));
         }
 
-        @MainThread
+        @WorkerThread
         private void executeCall(@NonNull Call call) {
             ensureBound();
             if (mService == null) {
+                if (DEBUG) {
+                    Slog.i(LOG_TAG, "Delaying until service connected: " + call);
+                }
                 mPendingCalls.offer(call);
                 return;
             }
@@ -159,24 +178,28 @@
             scheduleUnbind();
         }
 
-        @MainThread
+        @WorkerThread
         private void ensureBound() {
-            mMainHandler.removeCallbacks(mUnbindRunnable);
+            sCallbackHandler.removeCallbacks(mUnbindRunnable);
             if (!mBound) {
                 Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
                 intent.setPackage(mContext.getPackageManager()
                         .getPermissionControllerPackageName());
+                // Use direct handler to ensure onServiceConnected callback happens in the same
+                // call frame, as required by onGrantDefaultRoles
+                //
+                // Note that as a result, onServiceConnected may happen not on main thread!
                 mBound = mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE,
-                        UserHandle.of(mUserId));
+                        sCallbackHandler, UserHandle.of(mUserId));
             }
         }
 
         private void scheduleUnbind() {
-            mMainHandler.removeCallbacks(mUnbindRunnable);
-            mMainHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS);
+            sCallbackHandler.removeCallbacks(mUnbindRunnable);
+            sCallbackHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS);
         }
 
-        @MainThread
+        @WorkerThread
         private void unbind() {
             if (mBound) {
                 mService = null;
@@ -196,9 +219,6 @@
             private final IRoleManagerCallback mCallback;
 
             @NonNull
-            private final Handler mMainHandler = Handler.getMain();
-
-            @NonNull
             private final Runnable mTimeoutRunnable = () -> notifyCallback(false);
 
             private boolean mCallbackNotified;
@@ -209,10 +229,13 @@
                 mCallback = callback;
             }
 
-            @MainThread
+            @WorkerThread
             public void execute(IRoleControllerService service) {
+                if (DEBUG) {
+                    Slog.i(LOG_TAG, "Executing " + this);
+                }
                 try {
-                    mMainHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS);
+                    sCallbackHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS);
                     mCallExecutor.execute(service, new CallbackDelegate());
                 } catch (RemoteException e) {
                     Slog.e(LOG_TAG, "Error calling RoleControllerService", e);
@@ -220,13 +243,13 @@
                 }
             }
 
-            @MainThread
+            @WorkerThread
             private void notifyCallback(boolean success) {
                 if (mCallbackNotified) {
                     return;
                 }
                 mCallbackNotified = true;
-                mMainHandler.removeCallbacks(mTimeoutRunnable);
+                sCallbackHandler.removeCallbacks(mTimeoutRunnable);
                 try {
                     if (success) {
                         mCallback.onSuccess();
@@ -239,10 +262,15 @@
                 }
             }
 
+            @Override
+            public String toString() {
+                return "Call with callback: " + mCallback;
+            }
+
             @FunctionalInterface
             public interface CallExecutor {
 
-                @MainThread
+                @WorkerThread
                 void execute(IRoleControllerService service, IRoleManagerCallback callbackDelegate)
                         throws RemoteException;
             }
@@ -251,13 +279,14 @@
 
                 @Override
                 public void onSuccess() throws RemoteException {
-                    mMainHandler.post(PooledLambda.obtainRunnable(Call.this::notifyCallback, true));
+                    sCallbackHandler.sendMessage(PooledLambda.obtainMessage(
+                            Call::notifyCallback, Call.this, true));
                 }
 
                 @Override
                 public void onFailure() throws RemoteException {
-                    mMainHandler.post(PooledLambda.obtainRunnable(Call.this::notifyCallback,
-                            false));
+                    sCallbackHandler.sendMessage(PooledLambda.obtainMessage(
+                            Call::notifyCallback, Call.this, false));
                 }
             }
         }
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index b7d2ce2..d01e762 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -45,6 +45,10 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 /**
  * Service for role management.
@@ -104,13 +108,39 @@
     @Override
     public void onStart() {
         publishBinderService(Context.ROLE_SERVICE, new Stub());
+        //TODO add watch for new user creation and run default grants for them
+        //TODO add package update watch to detect PermissionController upgrade and run def. grants
     }
 
     @Override
     public void onStartUser(@UserIdInt int userId) {
         synchronized (mLock) {
+            //TODO only call into PermissionController if it or system upgreaded (for boot time)
             getUserStateLocked(userId);
         }
+        //TODO consider calling grants only when certain conditions are met
+        // such as OS or PermissionController upgrade
+        if (RemoteRoleControllerService.DEBUG) {
+            Slog.i(LOG_TAG, "Granting default permissions...");
+            CompletableFuture<Void> result = new CompletableFuture<>();
+            getControllerService(userId).onGrantDefaultRoles(
+                    new IRoleManagerCallback.Stub() {
+                        @Override
+                        public void onSuccess() {
+                            result.complete(null);
+                        }
+
+                        @Override
+                        public void onFailure() {
+                            result.completeExceptionally(new RuntimeException());
+                        }
+                    });
+            try {
+                result.get(5, TimeUnit.SECONDS);
+            } catch (InterruptedException | ExecutionException | TimeoutException e) {
+                Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e);
+            }
+        }
     }
 
     @GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index caa7c28..becc962 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -73,7 +73,7 @@
      * Maps role names to its holders' package names. The values should never be null.
      */
     @GuardedBy("RoleManagerService.mLock")
-    private ArrayMap<String, ArraySet<String>> mRoles = new ArrayMap<>();
+    private ArrayMap<String, ArraySet<String>> mRoles = null;
 
     @GuardedBy("RoleManagerService.mLock")
     private boolean mDestroyed;
@@ -188,7 +188,8 @@
             roles.put(roleName, roleHolders);
         }
         mWriteHandler.removeCallbacksAndMessages(null);
-        mWriteHandler.sendMessage(PooledLambda.obtainMessage(this::writeSync, version, roles));
+        mWriteHandler.sendMessage(PooledLambda.obtainMessage(
+                RoleUserState::writeSync, this, version, roles));
     }
 
     @WorkerThread
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 4d3fc1a..3050409 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -15,7 +15,13 @@
  */
 package com.android.server.stats;
 
+import static android.os.Process.getPidsForCommands;
+import static android.os.Process.getUidForPid;
+
 import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.server.am.MemoryStatUtil.MEMORY_STAT_INTERESTING_NATIVE_PROCESSES;
+import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs;
+import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs;
 
 import android.annotation.Nullable;
 import android.app.ActivityManagerInternal;
@@ -35,9 +41,13 @@
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
 import android.hardware.fingerprint.FingerprintManager;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkRequest;
 import android.net.NetworkStats;
 import android.net.wifi.IWifiManager;
 import android.net.wifi.WifiActivityEnergyInfo;
+import android.os.BatteryStats;
 import android.os.BatteryStatsInternal;
 import android.os.Binder;
 import android.os.Bundle;
@@ -78,6 +88,8 @@
 import com.android.internal.app.procstats.IProcessStats;
 import com.android.internal.app.procstats.ProcessStats;
 import com.android.internal.net.NetworkStatsFactory;
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
 import com.android.internal.os.BinderCallsStats.ExportedCallStat;
 import com.android.internal.os.KernelCpuSpeedReader;
 import com.android.internal.os.KernelCpuThreadReader;
@@ -96,6 +108,7 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.SystemServiceManager;
+import com.android.server.am.MemoryStatUtil.MemoryStat;
 import com.android.server.storage.DiskStatsFileLogger;
 import com.android.server.storage.DiskStatsLoggingService;
 
@@ -195,6 +208,10 @@
     @Nullable
     private final KernelCpuThreadReader mKernelCpuThreadReader;
 
+    private BatteryStatsHelper mBatteryStatsHelper = null;
+    private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000;
+    private long mBatteryStatsHelperTimestampMs = -MAX_BATTERY_STATS_HELPER_FREQUENCY_MS;
+
     private static IThermalService sThermalService;
     private File mBaseDir =
             new File(SystemServiceManager.ensureSystemDir(), "stats_companion");
@@ -253,8 +270,8 @@
         if (b != null) {
             sThermalService = IThermalService.Stub.asInterface(b);
             try {
-                sThermalService.registerThermalEventListener(
-                        new ThermalEventListener());
+                sThermalService.registerThermalEventListenerWithType(
+                        new ThermalEventListener(), Temperature.TYPE_SKIN);
                 Slog.i(TAG, "register thermal listener successfully");
             } catch (RemoteException e) {
                 // Should never happen.
@@ -264,6 +281,12 @@
             Slog.e(TAG, "cannot find thermalservice, no throttling push notifications");
         }
 
+        // Default NetworkRequest should cover all transport types.
+        final NetworkRequest request = new NetworkRequest.Builder().build();
+        final ConnectivityManager connectivityManager =
+                (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+        connectivityManager.registerNetworkCallback(request, new ConnectivityStatsCallback());
+
         HandlerThread handlerThread = new HandlerThread(TAG);
         handlerThread.start();
         mHandler = new CompanionHandler(handlerThread.getLooper());
@@ -350,6 +373,8 @@
         List<Integer> uids = new ArrayList<>();
         List<Long> versions = new ArrayList<>();
         List<String> apps = new ArrayList<>();
+        List<String> versionStrings = new ArrayList<>();
+        List<String> installers = new ArrayList<>();
 
         // Add in all the apps for every user/profile.
         for (UserInfo profile : users) {
@@ -357,14 +382,24 @@
                     pm.getInstalledPackagesAsUser(PackageManager.MATCH_KNOWN_PACKAGES, profile.id);
             for (int j = 0; j < pi.size(); j++) {
                 if (pi.get(j).applicationInfo != null) {
+                    String installer;
+                    try {
+                        installer = pm.getInstallerPackageName(pi.get(j).packageName);
+                    } catch (IllegalArgumentException e) {
+                        installer = "";
+                    }
+                    installers.add(installer == null ? "" : installer);
                     uids.add(pi.get(j).applicationInfo.uid);
                     versions.add(pi.get(j).getLongVersionCode());
+                    versionStrings.add(pi.get(j).versionName);
                     apps.add(pi.get(j).packageName);
                 }
             }
         }
-        sStatsd.informAllUidData(toIntArray(uids), toLongArray(versions), apps.toArray(new
-                String[apps.size()]));
+        sStatsd.informAllUidData(toIntArray(uids), toLongArray(versions),
+                versionStrings.toArray(new String[versionStrings.size()]),
+                apps.toArray(new String[apps.size()]),
+                installers.toArray(new String[installers.size()]));
         if (DEBUG) {
             Slog.d(TAG, "Sent data for " + uids.size() + " apps");
         }
@@ -406,7 +441,14 @@
                         int uid = b.getInt(Intent.EXTRA_UID);
                         String app = intent.getData().getSchemeSpecificPart();
                         PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER);
-                        sStatsd.informOnePackage(app, uid, pi.getLongVersionCode());
+                        String installer;
+                        try {
+                            installer = pm.getInstallerPackageName(app);
+                        } catch (IllegalArgumentException e) {
+                            installer = "";
+                        }
+                        sStatsd.informOnePackage(app, uid, pi.getLongVersionCode(), pi.versionName,
+                                installer == null ? "" : installer);
                     }
                 } catch (Exception e) {
                     Slog.w(TAG, "Failed to inform statsd of an app update", e);
@@ -1012,17 +1054,23 @@
     private void pullNativeProcessMemoryState(
             int tagId, long elapsedNanos, long wallClockNanos,
             List<StatsLogEventWrapper> pulledData) {
-        List<ProcessMemoryState> processMemoryStates = LocalServices.getService(
-                ActivityManagerInternal.class).getMemoryStateForNativeProcesses();
-        for (ProcessMemoryState processMemoryState : processMemoryStates) {
+        int[] pids = getPidsForCommands(MEMORY_STAT_INTERESTING_NATIVE_PROCESSES);
+        for (int i = 0; i < pids.length; i++) {
+            int pid = pids[i];
+            MemoryStat memoryStat = readMemoryStatFromProcfs(pid);
+            if (memoryStat == null) {
+                continue;
+            }
+            int uid = getUidForPid(pid);
+            String processName = readCmdlineFromProcfs(pid);
             StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
-            e.writeInt(processMemoryState.uid);
-            e.writeString(processMemoryState.processName);
-            e.writeLong(processMemoryState.pgfault);
-            e.writeLong(processMemoryState.pgmajfault);
-            e.writeLong(processMemoryState.rssInBytes);
-            e.writeLong(processMemoryState.rssHighWatermarkInBytes);
-            e.writeLong(processMemoryState.startTimeNanos);
+            e.writeInt(uid);
+            e.writeString(processName);
+            e.writeLong(memoryStat.pgfault);
+            e.writeLong(memoryStat.pgmajfault);
+            e.writeLong(memoryStat.rssInBytes);
+            e.writeLong(memoryStat.rssHighWatermarkInBytes);
+            e.writeLong(memoryStat.startTimeNanos);
             pulledData.add(e);
         }
     }
@@ -1408,6 +1456,73 @@
         pulledData.add(e);
     }
 
+    private BatteryStatsHelper getBatteryStatsHelper() {
+        if (mBatteryStatsHelper == null) {
+            final long callingToken = Binder.clearCallingIdentity();
+            try {
+                // clearCallingIdentity required for BatteryStatsHelper.checkWifiOnly().
+                mBatteryStatsHelper = new BatteryStatsHelper(mContext, false);
+            } finally {
+                Binder.restoreCallingIdentity(callingToken);
+            }
+            mBatteryStatsHelper.create((Bundle) null);
+        }
+        long currentTime = SystemClock.elapsedRealtime();
+        if (currentTime - mBatteryStatsHelperTimestampMs >= MAX_BATTERY_STATS_HELPER_FREQUENCY_MS) {
+            // Load BatteryStats and do all the calculations.
+            mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.USER_ALL);
+            // Calculations are done so we don't need to save the raw BatteryStats data in RAM.
+            mBatteryStatsHelper.clearStats();
+            mBatteryStatsHelperTimestampMs = currentTime;
+        }
+        return mBatteryStatsHelper;
+    }
+
+    private void pullDeviceCalculatedPowerUse(int tagId,
+            long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
+        BatteryStatsHelper bsHelper = getBatteryStatsHelper();
+        StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+        e.writeFloat((float) bsHelper.getComputedPower());
+        pulledData.add(e);
+    }
+
+    private void pullDeviceCalculatedPowerBlameUid(int tagId,
+            long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
+        final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
+        if (sippers == null) {
+            return;
+        }
+        for (BatterySipper bs : sippers) {
+            if (bs.drainType != bs.drainType.APP) {
+                continue;
+            }
+            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+            e.writeInt(bs.uidObj.getUid());
+            e.writeFloat((float) bs.totalPowerMah);
+            pulledData.add(e);
+        }
+    }
+
+    private void pullDeviceCalculatedPowerBlameOther(int tagId,
+            long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
+        final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
+        if (sippers == null) {
+            return;
+        }
+        for (BatterySipper bs : sippers) {
+            if (bs.drainType == bs.drainType.APP) {
+                continue; // This is a separate atom; see pullDeviceCalculatedPowerBlameUid().
+            }
+            if (bs.drainType == bs.drainType.USER) {
+                continue; // This is not supported. We purposefully calculate over USER_ALL.
+            }
+            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+            e.writeInt(bs.drainType.ordinal());
+            e.writeFloat((float) bs.totalPowerMah);
+            pulledData.add(e);
+        }
+    }
+
     private void pullDiskIo(int tagId, long elapsedNanos, final long wallClockNanos,
             List<StatsLogEventWrapper> pulledData) {
         mStoragedUidIoStatsReader.readAbsolute((uid, fgCharsRead, fgCharsWrite, fgBytesRead,
@@ -1633,6 +1748,18 @@
                 pullCpuTimePerThreadFreq(tagId, elapsedNanos, wallClockNanos, ret);
                 break;
             }
+            case StatsLog.DEVICE_CALCULATED_POWER_USE: {
+                pullDeviceCalculatedPowerUse(tagId, elapsedNanos, wallClockNanos, ret);
+                break;
+            }
+            case StatsLog.DEVICE_CALCULATED_POWER_BLAME_UID: {
+                pullDeviceCalculatedPowerBlameUid(tagId, elapsedNanos, wallClockNanos, ret);
+                break;
+            }
+            case StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER: {
+                pullDeviceCalculatedPowerBlameOther(tagId, elapsedNanos, wallClockNanos, ret);
+                break;
+            }
             default:
                 Slog.w(TAG, "No such tagId data as " + tagId);
                 return null;
@@ -1853,9 +1980,28 @@
     // Thermal event received from vendor thermal management subsystem
     private static final class ThermalEventListener extends IThermalEventListener.Stub {
         @Override
-        public void notifyThrottling(boolean isThrottling, Temperature temp) {
+        public void notifyThrottling(Temperature temp) {
+            boolean isThrottling = temp.getStatus() >= Temperature.THROTTLING_SEVERE;
             StatsLog.write(StatsLog.THERMAL_THROTTLING, temp.getType(),
-                    isThrottling ? 1 : 0, temp.getValue());
+                    isThrottling ?
+                            StatsLog.THERMAL_THROTTLING_STATE_CHANGED__STATE__START :
+                            StatsLog.THERMAL_THROTTLING_STATE_CHANGED__STATE__STOP,
+                    temp.getValue());
+        }
+    }
+
+    private static final class ConnectivityStatsCallback extends
+            ConnectivityManager.NetworkCallback {
+        @Override
+        public void onAvailable(Network network) {
+            StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
+                    StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__CONNECTED);
+        }
+
+        @Override
+        public void onLost(Network network) {
+            StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
+                    StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED);
         }
     }
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 79eab6b..3e07ebe 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -37,6 +37,7 @@
 import android.service.notification.NotificationStats;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.R;
@@ -140,13 +141,14 @@
             switch (which) {
                 case 1:
                     what1 = what;
-                    return;
+                    break;
                 case 2:
                     what2 = what;
-                    return;
+                    break;
                 default:
                     Slog.w(TAG, "Can't set unsupported disable flag " + which
                             + ": 0x" + Integer.toHexString(what));
+                    break;
             }
             this.pkg = pkg;
         }
@@ -566,11 +568,11 @@
 
     @Override
     public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
-            boolean requireConfirmation) {
+            boolean requireConfirmation, int userId) {
         enforceBiometricDialog();
         if (mBar != null) {
             try {
-                mBar.showBiometricDialog(bundle, receiver, type, requireConfirmation);
+                mBar.showBiometricDialog(bundle, receiver, type, requireConfirmation, userId);
             } catch (RemoteException ex) {
             }
         }
@@ -670,6 +672,20 @@
         // Ensure state for the current user is applied, even if passed a non-current user.
         final int net1 = gatherDisableActionsLocked(mCurrentUserId, 1);
         final int net2 = gatherDisableActionsLocked(mCurrentUserId, 2);
+
+        // TODO(b/113914868): investigation log for disappearing home button
+        if (whichFlag == 1 && pkg.contains("systemui")) {
+            String disabledData = "{ ";
+            for (int i = 0; i < mDisableRecords.size(); i++) {
+                DisableRecord tok = mDisableRecords.get(i);
+                disabledData += "    ([" + i + "] " + tok + "), ";
+            }
+            disabledData += " }";
+            Log.d(TAG, "disabledlocked (b/113914868): net1=" + net1 + ", mDisabled1=" + mDisabled1
+                    + ", token=" + token + ", mDisableRecords=" + mDisableRecords.size() + " => "
+                    + disabledData);
+        }
+
         if (net1 != mDisabled1 || net2 != mDisabled2) {
             mDisabled1 = net1;
             mDisabled2 = net2;
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 5fb1def..751ae0d 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -21,6 +21,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
@@ -51,6 +52,7 @@
 import android.annotation.Nullable;
 import android.app.ActivityOptions;
 import android.app.WindowConfiguration;
+import android.content.res.Configuration;
 import android.graphics.Point;
 import android.os.UserHandle;
 import android.util.IntArray;
@@ -156,7 +158,7 @@
     }
 
     void updateBounds() {
-        mDisplay.getSize(mTmpDisplaySize);
+        mDisplay.getRealSize(mTmpDisplaySize);
         setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
     }
 
@@ -938,6 +940,25 @@
         return mStacks.indexOf(stack);
     }
 
+    @Override
+    public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
+        final int currRotation = getOverrideConfiguration().windowConfiguration.getRotation();
+        if (currRotation != ROTATION_UNDEFINED
+                && currRotation != overrideConfiguration.windowConfiguration.getRotation()
+                && getWindowContainerController() != null) {
+            getWindowContainerController().applyRotation(currRotation,
+                    overrideConfiguration.windowConfiguration.getRotation());
+        }
+        super.onOverrideConfigurationChanged(overrideConfiguration);
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newParentConfig) {
+        // update resources before cascade so that docked/pinned stacks use the correct info
+        getWindowContainerController().preOnConfigurationChanged();
+        super.onConfigurationChanged(newParentConfig);
+    }
+
     void onLockTaskPackagesUpdated() {
         for (int i = mStacks.size() - 1; i >= 0; --i) {
             mStacks.get(i).onLockTaskPackagesUpdated();
@@ -1010,29 +1031,50 @@
 
     void remove() {
         final boolean destroyContentOnRemoval = shouldDestroyContentOnRemove();
+        ActivityStack lastReparentedStack = null;
+        mPreferredTopFocusableStack = null;
 
         // Stacks could be reparented from the removed display to other display. While
         // reparenting the last stack of the removed display, the remove display is ready to be
         // released (no more ActivityStack). But, we cannot release it at that moment or the
         // related WindowContainer and WindowContainerController will also be removed. So, we
         // set display as removed after reparenting stack finished.
-        for (int i = mStacks.size() - 1; i >= 0; --i) {
-            final ActivityStack stack = mStacks.get(i);
-            // Always finish non-standard type stacks.
-            if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
-                stack.finishAllActivitiesLocked(true /* immediately */);
-            } else {
-                // If default display is in split-window mode, set windowing mode of the stack to
-                // split-screen secondary. Otherwise, set the windowing mode to undefined by
-                // default to let stack inherited the windowing mode from the new display.
-                int windowingMode = mSupervisor.getDefaultDisplay().hasSplitScreenPrimaryStack()
-                        ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY : WINDOWING_MODE_UNDEFINED;
-                mSupervisor.moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY, true);
-                stack.setWindowingMode(windowingMode);
+        final ActivityDisplay toDisplay = mSupervisor.getDefaultDisplay();
+        mSupervisor.beginDeferResume();
+        try {
+            int numStacks = mStacks.size();
+            // Keep the order from bottom to top.
+            for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
+                final ActivityStack stack = mStacks.get(stackNdx);
+                // Always finish non-standard type stacks.
+                if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
+                    stack.finishAllActivitiesLocked(true /* immediately */);
+                } else {
+                    // If default display is in split-window mode, set windowing mode of the stack
+                    // to split-screen secondary. Otherwise, set the windowing mode to undefined by
+                    // default to let stack inherited the windowing mode from the new display.
+                    final int windowingMode = toDisplay.hasSplitScreenPrimaryStack()
+                            ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+                            : WINDOWING_MODE_UNDEFINED;
+                    stack.reparent(toDisplay, true /* onTop */, true /* displayRemoved */);
+                    stack.setWindowingMode(windowingMode);
+                    lastReparentedStack = stack;
+                }
+                // Stacks may be removed from this display. Ensure each stack will be processed and
+                // the loop will end.
+                stackNdx -= numStacks - mStacks.size();
+                numStacks = mStacks.size();
             }
+        } finally {
+            mSupervisor.endDeferResume();
         }
         mRemoved = true;
 
+        // Only update focus/visibility for the last one because there may be many stacks are
+        // reparented and the intermediate states are unnecessary.
+        if (lastReparentedStack != null) {
+            lastReparentedStack.postReparent();
+        }
         releaseSelfIfNeeded();
 
         if (!mAllSleepTokens.isEmpty()) {
@@ -1061,16 +1103,16 @@
     }
 
     /**
+     * Checks if system decorations should be shown on this display.
+     *
      * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
      */
     boolean supportsSystemDecorations() {
-        return mDisplay.supportsSystemDecorations()
-                // TODO (b/111363427): Remove this and set the new FLAG_SHOULD_SHOW_LAUNCHER flag
-                // (b/114338689) whenever vr 2d display id is set.
-                || mDisplayId == mSupervisor.mService.mVr2dDisplayId;
+        return mWindowContainerController.supportsSystemDecorations();
     }
 
-    private boolean shouldDestroyContentOnRemove() {
+    @VisibleForTesting
+    boolean shouldDestroyContentOnRemove() {
         return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
new file mode 100644
index 0000000..e3133ef
--- /dev/null
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2018 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.wm;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Intent;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Observe activity manager launch sequences.
+ *
+ * The activity manager can have at most 1 concurrent launch sequences. Calls to this interface
+ * are ordered by a happens-before relation for each defined state transition (see below).
+ *
+ * When a new launch sequence is made, that sequence is in the {@code INTENT_STARTED} state which
+ * is communicated by the {@link #onIntentStarted} callback. This is a transient state.
+ *
+ * The intent can fail to launch the activity, in which case the sequence's state transitions to
+ * {@code INTENT_FAILED} via {@link #onIntentFailed}. This is a terminal state.
+ *
+ * If an activity is successfully started, the launch sequence's state will transition into
+ * {@code STARTED} via {@link #onActivityLaunched}. This is a transient state.
+ *
+ * It must then transition to either {@code CANCELLED} with {@link #onActivityLaunchCancelled}
+ * or into {@code FINISHED} with {@link #onActivityLaunchFinished}. These are terminal states.
+ *
+ * Note that the {@link ActivityRecord} provided as a parameter to some state transitions isn't
+ * necessarily the same within a single launch sequence: it is only the top-most activity at the
+ * time (if any). Trampoline activities coalesce several activity starts into a single launch
+ * sequence.
+ *
+ * Upon reaching a terminal state, it is considered that there are no active launch sequences
+ * until a subsequent transition into {@code INTENT_STARTED} initiates a new launch sequence.
+ *
+ * <pre>
+ *        ┌⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┐     ┌⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┐     ╔══════════════════════════╗
+ *    ╴╴▶ ⋮ INTENT_STARTED ⋮ ──▶ ⋮     ACTIVITY_LAUNCHED     ⋮ ──▶ ║ ACTIVITY_LAUNCH_FINISHED ║
+ *        └⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┘     └⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯┘     ╚══════════════════════════╝
+ *          :                      :
+ *          :                      :
+ *          ▼                      ▼
+ *        ╔════════════════╗     ╔═══════════════════════════╗
+ *        ║ INTENT_FAILED  ║     ║ ACTIVITY_LAUNCH_CANCELLED ║
+ *        ╚════════════════╝     ╚═══════════════════════════╝
+ * </pre>
+ */
+public interface ActivityMetricsLaunchObserver {
+    /**
+     * The 'temperature' at which a launch sequence had started.
+     *
+     * The lower the temperature the more work has to be done during start-up.
+     * A 'cold' temperature means that a new process has been started and likely
+     * nothing is cached.
+     *
+     * A hot temperature means the existing activity is brought to the foreground.
+     * It may need to regenerate some objects as a result of {@code onTrimMemory}.
+     *
+     * A warm temperature is in the middle; an existing process is used, but the activity
+     * has to be created from scratch with {@code #onCreate}.
+     *
+     * @see https://developer.android.com/topic/performance/vitals/launch-time
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            TEMPERATURE_COLD,
+            TEMPERATURE_WARM,
+            TEMPERATURE_HOT
+    })
+    @interface Temperature {}
+
+    /** Cold launch sequence: a new process has started. */
+    public static final int TEMPERATURE_COLD = 1;
+    /** Warm launch sequence: process reused, but activity has to be created. */
+    public static final int TEMPERATURE_WARM = 2;
+    /** Hot launch sequence: process reused, activity brought-to-top. */
+    public static final int TEMPERATURE_HOT = 3;
+
+    /**
+     * Notifies the observer that a new launch sequence has begun as a result of a new intent.
+     *
+     * Once a launch sequence begins, the resolved activity will either subsequently start with
+     * {@link #onActivityLaunched} or abort early (for example due to a resolution error or due to
+     * a security error) with {@link #onIntentFailed}.
+     *
+     * Multiple calls to this method cannot occur without first terminating the current
+     * launch sequence.
+     */
+    public void onIntentStarted(@NonNull Intent intent);
+
+    /**
+     * Notifies the observer that the current launch sequence has failed to launch an activity.
+     *
+     * This function call terminates the current launch sequence. The next method call, if any,
+     * must be {@link #onIntentStarted}.
+     *
+     * Examples of this happening:
+     *  - Failure to resolve to an activity
+     *  - Calling package did not have the security permissions to call the requested activity
+     *  - Resolved activity was already running and only needed to be brought to the top
+     *
+     * Multiple calls to this method cannot occur without first terminating the current
+     * launch sequence.
+     */
+    public void onIntentFailed();
+
+    /**
+     * Notifies the observer that the current launch sequence had begun starting an activity.
+     *
+     * This is an intermediate state: once an activity begins starting, the entire launch sequence
+     * will later terminate by either finishing or cancelling.
+     *
+     * The initial activity is the first activity to be started as part of a launch sequence:
+     * it is represented by {@param activity} However, it isn't
+     * necessarily the activity which will be considered as displayed when the activity
+     * finishes launching (e.g. {@code activity} in {@link #onActivityLaunchFinished}).
+     *
+     * Multiple calls to this method cannot occur without first terminating the current
+     * launch sequence.
+     */
+    public void onActivityLaunched(@NonNull ActivityRecord activity,
+                                   @Temperature int temperature);
+
+    /**
+     * Notifies the observer that the current launch sequence has been aborted.
+     *
+     * This function call terminates the current launch sequence. The next method call, if any,
+     * must be {@link #onIntentStarted}.
+     *
+     * This can happen for many reasons, for example the user switches away to another app
+     * prior to the launch sequence completing, or the application being killed.
+     *
+     * Multiple calls to this method cannot occur without first terminating the current
+     * launch sequence.
+     *
+     * @param abortingActivity the last activity that had the top-most window during abort
+     *                         (this can be {@code null} in rare situations its unknown).
+     *
+     * @apiNote The aborting activity isn't necessarily the same as the starting activity;
+     *          in the case of a trampoline, multiple activities could've been started
+     *          and only the latest activity is reported here.
+     */
+    public void onActivityLaunchCancelled(@Nullable ActivityRecord abortingActivity);
+
+    /**
+     * Notifies the observer that the current launch sequence has been successfully finished.
+     *
+     * This function call terminates the current launch sequence. The next method call, if any,
+     * must be {@link #onIntentStarted}.
+     *
+     * A launch sequence is considered to be successfully finished when a frame is fully
+     * drawn for the first time: the top-most activity at the time is what's reported here.
+     *
+     * @param finalActivity the top-most activity whose windows were first to fully draw
+     *
+     * Multiple calls to this method cannot occur without first terminating the current
+     * launch sequence.
+     *
+     * @apiNote The finishing activity isn't necessarily the same as the starting activity;
+     *          in the case of a trampoline, multiple activities could've been started
+     *          and only the latest activity that was top-most during first-frame drawn
+     *          is reported here.
+     */
+    public void onActivityLaunchFinished(@NonNull ActivityRecord finalActivity);
+}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 8bde7dd..1c08d03 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -72,14 +72,15 @@
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME;
 import static com.android.server.am.MemoryStatUtil.MemoryStat;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT;
 
+import android.app.WindowConfiguration.WindowingMode;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -141,15 +142,21 @@
     private final Context mContext;
     private final MetricsLogger mMetricsLogger = new MetricsLogger();
 
+    // set to INVALID_START_TIME in reset.
+    // set to valid value in notifyActivityLaunching
     private long mCurrentTransitionStartTime = INVALID_START_TIME;
     private long mLastTransitionStartTime = INVALID_START_TIME;
 
     private int mCurrentTransitionDeviceUptime;
     private int mCurrentTransitionDelayMs;
+
+    /** If the any app transitions have been logged as starting, after the latest reset. */
     private boolean mLoggedTransitionStarting;
 
+    /** Map : @WindowingMode int => WindowingModeTransitionInfo */
     private final SparseArray<WindowingModeTransitionInfo> mWindowingModeTransitionInfo =
             new SparseArray<>();
+    /** Map : @WindowingMode int => WindowingModeTransitionInfo */
     private final SparseArray<WindowingModeTransitionInfo> mLastWindowingModeTransitionInfo =
             new SparseArray<>();
     private final H mHandler;
@@ -157,6 +164,12 @@
     private ArtManagerInternal mArtManagerInternal;
     private final StringBuilder mStringBuilder = new StringBuilder();
 
+    /**
+     * Due to the global single concurrent launch sequence, all calls to this observer must be made
+     * in-order on the same thread to fulfill the "happens-before" guarantee in LaunchObserver.
+     */
+    private final ActivityMetricsLaunchObserver mLaunchObserver = null;
+
     private final class H extends Handler {
 
         public H(Looper looper) {
@@ -175,6 +188,7 @@
     }
 
     private final class WindowingModeTransitionInfo {
+        /** The latest activity to have been launched. */
         private ActivityRecord launchedActivity;
         private int startResult;
         private boolean currentTransitionProcessRunning;
@@ -273,7 +287,7 @@
             return;
         }
 
-        int windowingMode = stack.getWindowingMode();
+        @WindowingMode int windowingMode = stack.getWindowingMode();
         if (windowingMode == WINDOWING_MODE_PINNED) {
             stack = mSupervisor.findStackBehind(stack);
             windowingMode = stack.getWindowingMode();
@@ -301,11 +315,19 @@
      * Notifies the tracker at the earliest possible point when we are starting to launch an
      * activity.
      */
-    void notifyActivityLaunching() {
+    void notifyActivityLaunching(Intent intent) {
+        if (DEBUG_METRICS) {
+            Slog.i(TAG, String.format("notifyActivityLaunching: active:%b, intent:%s",
+                                      isAnyTransitionActive(),
+                                      intent));
+        }
+
         if (!isAnyTransitionActive()) {
-            if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunching");
+
             mCurrentTransitionStartTime = SystemClock.uptimeMillis();
             mLastTransitionStartTime = mCurrentTransitionStartTime;
+
+            launchObserverNotifyIntentStarted(intent);
         }
     }
 
@@ -350,7 +372,9 @@
                 + " processRunning=" + processRunning
                 + " processSwitch=" + processSwitch);
 
-        final int windowingMode = launchedActivity != null
+        // If we are already in an existing transition, only update the activity name, but not the
+        // other attributes.
+        final @WindowingMode int windowingMode = launchedActivity != null
                 ? launchedActivity.getWindowingMode()
                 : WINDOWING_MODE_UNDEFINED;
         final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
@@ -359,15 +383,17 @@
             return;
         }
 
-        if (launchedActivity != null && launchedActivity.nowVisible) {
+        if (launchedActivity != null && launchedActivity.mDrawn) {
             // Launched activity is already visible. We cannot measure windows drawn delay.
-            reset(true /* abort */, info);
+            reset(true /* abort */, info, "launched activity already visible");
             return;
         }
 
         if (launchedActivity != null && info != null) {
             // If we are already in an existing transition, only update the activity name, but not
             // the other attributes.
+
+            // Coalesce multiple (trampoline) activities from a single sequence together.
             info.launchedActivity = launchedActivity;
             return;
         }
@@ -377,7 +403,7 @@
         if ((!isLoggableResultCode(resultCode) || launchedActivity == null || !processSwitch
                 || windowingMode == WINDOWING_MODE_UNDEFINED) && !otherWindowModesLaunching) {
             // Failed to launch or it was not a process switch, so we don't care about the timing.
-            reset(true /* abort */, info);
+            reset(true /* abort */, info, "failed to launch or not a process switch");
             return;
         } else if (otherWindowModesLaunching) {
             // Don't log this windowing mode but continue with the other windowing modes.
@@ -386,6 +412,8 @@
 
         if (DEBUG_METRICS) Slog.i(TAG, "notifyActivityLaunched successful");
 
+        // A new launch sequence [with the windowingMode] has begun.
+        // Start tracking it.
         final WindowingModeTransitionInfo newInfo = new WindowingModeTransitionInfo();
         newInfo.launchedActivity = launchedActivity;
         newInfo.currentTransitionProcessRunning = processRunning;
@@ -394,6 +422,7 @@
         mLastWindowingModeTransitionInfo.put(windowingMode, newInfo);
         mCurrentTransitionDeviceUptime = (int) (SystemClock.uptimeMillis() / 1000);
         startTraces(newInfo);
+        launchObserverNotifyActivityLaunched(newInfo);
     }
 
     /**
@@ -407,7 +436,8 @@
     /**
      * Notifies the tracker that all windows of the app have been drawn.
      */
-    WindowingModeTransitionInfoSnapshot notifyWindowsDrawn(int windowingMode, long timestamp) {
+    WindowingModeTransitionInfoSnapshot notifyWindowsDrawn(@WindowingMode int windowingMode,
+                                                           long timestamp) {
         if (DEBUG_METRICS) Slog.i(TAG, "notifyWindowsDrawn windowingMode=" + windowingMode);
 
         final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
@@ -419,7 +449,7 @@
         final WindowingModeTransitionInfoSnapshot infoSnapshot =
                 new WindowingModeTransitionInfoSnapshot(info);
         if (allWindowsDrawn() && mLoggedTransitionStarting) {
-            reset(false /* abort */, info);
+            reset(false /* abort */, info, "notifyWindowsDrawn - all windows drawn");
         }
         return infoSnapshot;
     }
@@ -427,7 +457,7 @@
     /**
      * Notifies the tracker that the starting window was drawn.
      */
-    void notifyStartingWindowDrawn(int windowingMode, long timestamp) {
+    void notifyStartingWindowDrawn(@WindowingMode int windowingMode, long timestamp) {
         final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
         if (info == null || info.loggedStartingWindowDrawn) {
             return;
@@ -444,22 +474,30 @@
      */
     void notifyTransitionStarting(SparseIntArray windowingModeToReason, long timestamp) {
         if (!isAnyTransitionActive() || mLoggedTransitionStarting) {
+            // Ignore calls to this made after a reset and prior to notifyActivityLaunching.
+
+            // Ignore any subsequent notifyTransitionStarting until the next reset.
             return;
         }
         if (DEBUG_METRICS) Slog.i(TAG, "notifyTransitionStarting");
         mCurrentTransitionDelayMs = calculateDelay(timestamp);
         mLoggedTransitionStarting = true;
+
+        WindowingModeTransitionInfo foundInfo = null;
         for (int index = windowingModeToReason.size() - 1; index >= 0; index--) {
-            final int windowingMode = windowingModeToReason.keyAt(index);
+            final @WindowingMode int windowingMode = windowingModeToReason.keyAt(index);
             final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(
                     windowingMode);
             if (info == null) {
                 continue;
             }
             info.reason = windowingModeToReason.valueAt(index);
+            foundInfo = info;
         }
         if (allWindowsDrawn()) {
-            reset(false /* abort */, null /* WindowingModeTransitionInfo */);
+            // abort metrics collection if we cannot find a matching transition.
+            final boolean abortMetrics = foundInfo == null;
+            reset(abortMetrics, foundInfo, "notifyTransitionStarting - all windows drawn");
         }
     }
 
@@ -498,7 +536,7 @@
                 logAppTransitionCancel(info);
                 mWindowingModeTransitionInfo.remove(r.getWindowingMode());
                 if (mWindowingModeTransitionInfo.size() == 0) {
-                    reset(true /* abort */, info);
+                    reset(true /* abort */, info, "notifyVisibilityChanged to invisible");
                 }
             }
         }
@@ -534,12 +572,25 @@
                 && mWindowingModeTransitionInfo.size() > 0;
     }
 
-    private void reset(boolean abort, WindowingModeTransitionInfo info) {
-        if (DEBUG_METRICS) Slog.i(TAG, "reset abort=" + abort);
+    private void reset(boolean abort, WindowingModeTransitionInfo info, String cause) {
+        if (DEBUG_METRICS) Slog.i(TAG, "reset abort=" + abort + ",cause=" + cause);
         if (!abort && isAnyTransitionActive()) {
             logAppTransitionMultiEvents();
         }
         stopLaunchTrace(info);
+
+        // Ignore reset-after reset.
+        if (isAnyTransitionActive()) {
+            // LaunchObserver callbacks.
+            if (abort) {
+                launchObserverNotifyActivityLaunchCancelled(info);
+            } else {
+                launchObserverNotifyActivityLaunchFinished(info);
+            }
+        } else {
+            launchObserverNotifyIntentFailed();
+        }
+
         mCurrentTransitionStartTime = INVALID_START_TIME;
         mCurrentTransitionDelayMs = INVALID_DELAY;
         mLoggedTransitionStarting = false;
@@ -572,6 +623,13 @@
                 info.launchedActivity.packageName,
                 convertAppStartTransitionType(type),
                 info.launchedActivity.info.name);
+        if (DEBUG_METRICS) {
+            Slog.i(TAG, String.format("APP_START_CANCELED(%s, %s, %s, %s)",
+                    info.launchedActivity.appInfo.uid,
+                    info.launchedActivity.packageName,
+                    convertAppStartTransitionType(type),
+                    info.launchedActivity.info.name));
+        }
     }
 
     private void logAppTransitionMultiEvents() {
@@ -656,6 +714,17 @@
                 launchToken,
                 packageOptimizationInfo.getCompilationReason(),
                 packageOptimizationInfo.getCompilationFilter());
+
+        if (DEBUG_METRICS) {
+            Slog.i(TAG, String.format("APP_START_OCCURRED(%s, %s, %s, %s, %s)",
+                    info.applicationInfo.uid,
+                    info.packageName,
+                    convertAppStartTransitionType(info.type),
+                    info.launchedActivityName,
+                    info.launchedActivityLaunchedFromPackage));
+        }
+
+
         logAppStartMemoryStateCapture(info);
     }
 
@@ -923,4 +992,76 @@
             info.launchTraceActive = false;
         }
     }
+
+    /** Notify the {@link ActivityMetricsLaunchObserver} that a new launch sequence has begun. */
+    private void launchObserverNotifyIntentStarted(Intent intent) {
+        if (mLaunchObserver != null) {
+            // Beginning a launch is timing sensitive and so should be observed as soon as possible.
+            mLaunchObserver.onIntentStarted(intent);
+        }
+    }
+
+    /**
+     * Notify the {@link ActivityMetricsLaunchObserver} that the previous launch sequence has
+     * aborted due to intent failure (e.g. intent resolve failed or security error, etc) or
+     * intent being delivered to the top running activity.
+     */
+    private void launchObserverNotifyIntentFailed() {
+        if (mLaunchObserver != null) {
+            mLaunchObserver.onIntentFailed();
+        }
+    }
+
+    /**
+     * Notify the {@link ActivityMetricsLaunchObserver} that the current launch sequence's activity
+     * has started.
+     */
+    private void launchObserverNotifyActivityLaunched(WindowingModeTransitionInfo info) {
+        @ActivityMetricsLaunchObserver.Temperature int temperature =
+                convertTransitionTypeToLaunchObserverTemperature(getTransitionType(info));
+
+        if (mLaunchObserver != null) {
+            // Beginning a launch is timing sensitive and so should be observed as soon as possible.
+            mLaunchObserver.onActivityLaunched(info.launchedActivity,
+                                               temperature);
+        }
+    }
+
+    /**
+     * Notify the {@link ActivityMetricsLaunchObserver} that the current launch sequence is
+     * cancelled.
+     */
+    private void launchObserverNotifyActivityLaunchCancelled(WindowingModeTransitionInfo info) {
+        final ActivityRecord launchedActivity = info != null ? info.launchedActivity : null;
+
+        if (mLaunchObserver != null) {
+            mLaunchObserver.onActivityLaunchCancelled(launchedActivity);
+        }
+    }
+
+    /**
+     * Notify the {@link ActivityMetricsLaunchObserver} that the current launch sequence's activity
+     * has fully finished (successfully).
+     */
+    private void launchObserverNotifyActivityLaunchFinished(WindowingModeTransitionInfo info) {
+        final ActivityRecord launchedActivity = info.launchedActivity;
+
+        if (mLaunchObserver != null) {
+            mLaunchObserver.onActivityLaunchFinished(launchedActivity);
+        }
+    }
+
+    private static @ActivityMetricsLaunchObserver.Temperature int
+            convertTransitionTypeToLaunchObserverTemperature(int transitionType) {
+        switch (transitionType) {
+            case TYPE_TRANSITION_WARM_LAUNCH:
+                return ActivityMetricsLaunchObserver.TEMPERATURE_WARM;
+            case TYPE_TRANSITION_HOT_LAUNCH:
+                return ActivityMetricsLaunchObserver.TEMPERATURE_HOT;
+            case TYPE_TRANSITION_COLD_LAUNCH:
+                return ActivityMetricsLaunchObserver.TEMPERATURE_COLD;
+            default:
+                return -1;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 8223693..c43e64e 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -20,6 +20,7 @@
 import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
 import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
 import static android.app.ActivityTaskManager.INVALID_STACK_ID;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
 import static android.app.WaitResult.INVALID_DELAY;
@@ -75,6 +76,25 @@
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
 
+import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
+import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
+import static com.android.server.am.ActivityRecordProto.PROC_ID;
+import static com.android.server.am.ActivityRecordProto.STATE;
+import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
+import static com.android.server.am.ActivityRecordProto.VISIBLE;
+import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
+import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
+import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
+import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
+import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
+import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
+import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
+import static com.android.server.wm.ActivityStack.LAUNCH_TICK;
+import static com.android.server.wm.ActivityStack.LAUNCH_TICK_MSG;
+import static com.android.server.wm.ActivityStack.PAUSE_TIMEOUT_MSG;
+import static com.android.server.wm.ActivityStack.STOP_TIMEOUT_MSG;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
@@ -89,34 +109,14 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
-import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
-import static com.android.server.am.ActivityRecordProto.PROC_ID;
-import static com.android.server.am.ActivityRecordProto.STATE;
-import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
-import static com.android.server.am.ActivityRecordProto.VISIBLE;
-import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
-import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
-import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
-import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
-import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
-import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.wm.ActivityStack.LAUNCH_TICK;
-import static com.android.server.wm.ActivityStack.LAUNCH_TICK_MSG;
-import static com.android.server.wm.ActivityStack.PAUSE_TIMEOUT_MSG;
-import static com.android.server.wm.ActivityStack.STOP_TIMEOUT_MSG;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
-import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
-import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
-import static com.android.server.wm.TaskPersister.DEBUG;
-import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static com.android.server.wm.IdentifierProto.HASH_CODE;
 import static com.android.server.wm.IdentifierProto.TITLE;
 import static com.android.server.wm.IdentifierProto.USER_ID;
+import static com.android.server.wm.TaskPersister.DEBUG;
+import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
 
 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
 import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -179,9 +179,9 @@
 import com.android.server.AttributeCache.Entry;
 import com.android.server.am.AppTimeTracker;
 import com.android.server.am.PendingIntentRecord;
+import com.android.server.uri.UriPermissionOwner;
 import com.android.server.wm.ActivityMetricsLogger.WindowingModeTransitionInfoSnapshot;
 import com.android.server.wm.ActivityStack.ActivityState;
-import com.android.server.uri.UriPermissionOwner;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -303,6 +303,7 @@
                                         // process that it is hidden.
     boolean sleeping;       // have we told the activity to sleep?
     boolean nowVisible;     // is this activity's window visible?
+    boolean mDrawn;          // is this activity's window drawn?
     boolean mClientVisibilityDeferred;// was the visibility change message to client deferred?
     boolean idle;           // has the activity gone idle?
     boolean hasBeenLaunched;// has this activity ever been launched?
@@ -869,6 +870,7 @@
         inHistory = false;
         visible = false;
         nowVisible = false;
+        mDrawn = false;
         idle = false;
         hasBeenLaunched = false;
         mStackSupervisor = supervisor;
@@ -1009,8 +1011,8 @@
         updateOverrideConfiguration();
 
         mWindowContainerController = new AppWindowContainerController(taskController, appToken,
-                this, Integer.MAX_VALUE /* add on top */, info.screenOrientation, fullscreen,
-                (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges,
+                realActivity, this, Integer.MAX_VALUE /* add on top */, info.screenOrientation,
+                fullscreen, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges,
                 task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(),
                 appInfo.targetSdkVersion, mRotationAnimationHint,
                 ActivityTaskManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L);
@@ -1944,8 +1946,12 @@
     }
 
     @Override
-    public void onWindowsDrawn(long timestamp) {
+    public void onWindowsDrawn(boolean drawn, long timestamp) {
         synchronized (service.mGlobalLock) {
+            mDrawn = drawn;
+            if (!drawn) {
+                return;
+            }
             final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
                     .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp);
             final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index a8b4a9d..7fcee3db 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -46,6 +46,13 @@
 import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
 import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
 
+import static com.android.server.am.ActivityStackProto.BOUNDS;
+import static com.android.server.am.ActivityStackProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityStackProto.DISPLAY_ID;
+import static com.android.server.am.ActivityStackProto.FULLSCREEN;
+import static com.android.server.am.ActivityStackProto.ID;
+import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
+import static com.android.server.am.ActivityStackProto.TASKS;
 import static com.android.server.wm.ActivityDisplay.POSITION_BOTTOM;
 import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
@@ -56,13 +63,6 @@
 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.am.ActivityStackProto.BOUNDS;
-import static com.android.server.am.ActivityStackProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.ActivityStackProto.DISPLAY_ID;
-import static com.android.server.am.ActivityStackProto.FULLSCREEN;
-import static com.android.server.am.ActivityStackProto.ID;
-import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
-import static com.android.server.am.ActivityStackProto.TASKS;
 import static com.android.server.wm.ActivityStackSupervisor.FindTaskResult;
 import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
 import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -513,14 +513,23 @@
     public void onConfigurationChanged(Configuration newParentConfig) {
         final int prevWindowingMode = getWindowingMode();
         final boolean prevIsAlwaysOnTop = isAlwaysOnTop();
-        super.onConfigurationChanged(newParentConfig);
         final ActivityDisplay display = getDisplay();
+
+        getBounds(mTmpRect2);
+        final boolean hasNewBounds = display != null && getWindowContainerController() != null
+                && getWindowContainerController().updateBoundsForConfigChange(
+                        newParentConfig, getConfiguration(), mTmpRect2);
+
+        super.onConfigurationChanged(newParentConfig);
         if (display == null) {
           return;
         }
         if (prevWindowingMode != getWindowingMode()) {
             display.onStackWindowingModeChanged(this);
         }
+        if (hasNewBounds) {
+            resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */);
+        }
         if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
             // Since always on top is only on when the stack is freeform or pinned, the state
             // can be toggled when the windowing mode changes. We must make sure the stack is
@@ -729,7 +738,7 @@
     }
 
     /** Adds the stack to specified display and calls WindowManager to do the same. */
-    void reparent(ActivityDisplay activityDisplay, boolean onTop) {
+    void reparent(ActivityDisplay activityDisplay, boolean onTop, boolean displayRemoved) {
         // TODO: We should probably resolve the windowing mode for the stack on the new display here
         // so that it end up in a compatible mode in the new display. e.g. split-screen secondary.
         removeFromDisplay();
@@ -738,6 +747,13 @@
         mTmpRect2.setEmpty();
         mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop);
         postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
+        if (!displayRemoved) {
+            postReparent();
+        }
+    }
+
+    /** Resume next focusable stack after reparenting to another display. */
+    void postReparent() {
         adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */);
         mStackSupervisor.resumeFocusedStacksTopActivitiesLocked();
         // Update visibility of activities before notifying WM. This way it won't try to resize
@@ -752,6 +768,12 @@
      * @param bounds Updated bounds.
      */
     private void postAddToDisplay(ActivityDisplay activityDisplay, Rect bounds, boolean onTop) {
+        if (mDisplayId != activityDisplay.mDisplayId) {
+            // rotations are relative to the display, so pretend like our current rotation is
+            // the same as the new display so we don't try to rotate bounds.
+            getConfiguration().windowConfiguration.setRotation(
+                    activityDisplay.getWindowConfiguration().getRotation());
+        }
         mDisplayId = activityDisplay.mDisplayId;
         setBounds(bounds);
         onParentChanged();
@@ -810,10 +832,6 @@
         outBounds.setEmpty();
     }
 
-    void getBoundsForNewConfiguration(Rect outBounds) {
-        mWindowContainerController.getBoundsForNewConfiguration(outBounds);
-    }
-
     void positionChildWindowContainerAtTop(TaskRecord child) {
         mWindowContainerController.positionChildAtTop(child.getWindowContainerController(),
                 true /* includingParents */);
@@ -1151,7 +1169,8 @@
     }
 
     final boolean isAttached() {
-        return getParent() != null;
+        final ActivityDisplay display = getDisplay();
+        return display != null && !display.isRemoved();
     }
 
     /**
@@ -2679,136 +2698,129 @@
                     || (lastFocusedStack.mLastPausedActivity != null
                     && !lastFocusedStack.mLastPausedActivity.fullscreen));
 
-            // The contained logic must be synchronized, since we are both changing the visibility
-            // and updating the {@link Configuration}. {@link ActivityRecord#setVisibility} will
-            // ultimately cause the client code to schedule a layout. Since layouts retrieve the
-            // current {@link Configuration}, we must ensure that the below code updates it before
-            // the layout can occur.
-            synchronized(mWindowManager.getWindowManagerLock()) {
-                // This activity is now becoming visible.
-                if (!next.visible || next.stopped || lastActivityTranslucent) {
+            // This activity is now becoming visible.
+            if (!next.visible || next.stopped || lastActivityTranslucent) {
+                next.setVisibility(true);
+            }
+
+            // schedule launch ticks to collect information about slow apps.
+            next.startLaunchTickingLocked();
+
+            ActivityRecord lastResumedActivity =
+                    lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity;
+            final ActivityState lastState = next.getState();
+
+            mService.updateCpuStats();
+
+            if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
+                    + " (in existing)");
+
+            next.setState(RESUMED, "resumeTopActivityInnerLocked");
+
+            next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
+                    true /* updateLru */, true /* activityChange */, true /* updateOomAdj */);
+            updateLRUListLocked(next);
+
+            // Have the window manager re-evaluate the orientation of
+            // the screen based on the new activity order.
+            boolean notUpdated = true;
+
+            if (isFocusedStackOnDisplay()) {
+                // We have special rotation behavior when here is some active activity that
+                // requests specific orientation or Keyguard is locked. Make sure all activity
+                // visibilities are set correctly as well as the transition is updated if needed
+                // to get the correct rotation behavior. Otherwise the following call to update
+                // the orientation may cause incorrect configurations delivered to client as a
+                // result of invisible window resize.
+                // TODO: Remove this once visibilities are set correctly immediately when
+                // starting an activity.
+                notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
+                        true /* markFrozenIfConfigChanged */, false /* deferResume */);
+            }
+
+            if (notUpdated) {
+                // The configuration update wasn't able to keep the existing
+                // instance of the activity, and instead started a new one.
+                // We should be all done, but let's just make sure our activity
+                // is still at the top and schedule another run if something
+                // weird happened.
+                ActivityRecord nextNext = topRunningActivityLocked();
+                if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
+                        "Activity config changed during resume: " + next
+                                + ", new next: " + nextNext);
+                if (nextNext != next) {
+                    // Do over!
+                    mStackSupervisor.scheduleResumeTopActivities();
+                }
+                if (!next.visible || next.stopped) {
                     next.setVisibility(true);
                 }
+                next.completeResumeLocked();
+                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
+                return true;
+            }
 
-                // schedule launch ticks to collect information about slow apps.
-                next.startLaunchTickingLocked();
-
-                ActivityRecord lastResumedActivity =
-                        lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity;
-                final ActivityState lastState = next.getState();
-
-                mService.updateCpuStats();
-
-                if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
-                        + " (in existing)");
-
-                next.setState(RESUMED, "resumeTopActivityInnerLocked");
-
-                next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
-                        true /* updateLru */, true /* activityChange */, true /* updateOomAdj */);
-                updateLRUListLocked(next);
-
-                // Have the window manager re-evaluate the orientation of
-                // the screen based on the new activity order.
-                boolean notUpdated = true;
-
-                if (isFocusedStackOnDisplay()) {
-                    // We have special rotation behavior when here is some active activity that
-                    // requests specific orientation or Keyguard is locked. Make sure all activity
-                    // visibilities are set correctly as well as the transition is updated if needed
-                    // to get the correct rotation behavior. Otherwise the following call to update
-                    // the orientation may cause incorrect configurations delivered to client as a
-                    // result of invisible window resize.
-                    // TODO: Remove this once visibilities are set correctly immediately when
-                    // starting an activity.
-                    notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
-                            true /* markFrozenIfConfigChanged */, false /* deferResume */);
+            try {
+                final ClientTransaction transaction =
+                        ClientTransaction.obtain(next.app.getThread(), next.appToken);
+                // Deliver all pending results.
+                ArrayList<ResultInfo> a = next.results;
+                if (a != null) {
+                    final int N = a.size();
+                    if (!next.finishing && N > 0) {
+                        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
+                                "Delivering results to " + next + ": " + a);
+                        transaction.addCallback(ActivityResultItem.obtain(a));
+                    }
                 }
 
-                if (notUpdated) {
-                    // The configuration update wasn't able to keep the existing
-                    // instance of the activity, and instead started a new one.
-                    // We should be all done, but let's just make sure our activity
-                    // is still at the top and schedule another run if something
-                    // weird happened.
-                    ActivityRecord nextNext = topRunningActivityLocked();
-                    if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
-                            "Activity config changed during resume: " + next
-                                    + ", new next: " + nextNext);
-                    if (nextNext != next) {
-                        // Do over!
-                        mStackSupervisor.scheduleResumeTopActivities();
-                    }
-                    if (!next.visible || next.stopped) {
-                        next.setVisibility(true);
-                    }
-                    next.completeResumeLocked();
-                    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
-                    return true;
+                if (next.newIntents != null) {
+                    transaction.addCallback(NewIntentItem.obtain(next.newIntents,
+                            false /* andPause */));
                 }
 
-                try {
-                    final ClientTransaction transaction =
-                            ClientTransaction.obtain(next.app.getThread(), next.appToken);
-                    // Deliver all pending results.
-                    ArrayList<ResultInfo> a = next.results;
-                    if (a != null) {
-                        final int N = a.size();
-                        if (!next.finishing && N > 0) {
-                            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
-                                    "Delivering results to " + next + ": " + a);
-                            transaction.addCallback(ActivityResultItem.obtain(a));
-                        }
-                    }
+                // Well the app will no longer be stopped.
+                // Clear app token stopped state in window manager if needed.
+                next.notifyAppResumed(next.stopped);
 
-                    if (next.newIntents != null) {
-                        transaction.addCallback(NewIntentItem.obtain(next.newIntents,
-                                false /* andPause */));
-                    }
+                EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
+                        System.identityHashCode(next), next.getTask().taskId,
+                        next.shortComponentName);
 
-                    // Well the app will no longer be stopped.
-                    // Clear app token stopped state in window manager if needed.
-                    next.notifyAppResumed(next.stopped);
+                next.sleeping = false;
+                mService.getAppWarningsLocked().onResumeActivity(next);
+                next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState);
+                next.clearOptionsLocked();
+                transaction.setLifecycleStateRequest(
+                        ResumeActivityItem.obtain(next.app.getReportedProcState(),
+                                getDisplay().getWindowContainerController()
+                                        .isNextTransitionForward()));
+                mService.getLifecycleManager().scheduleTransaction(transaction);
 
-                    EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
-                            System.identityHashCode(next), next.getTask().taskId,
-                            next.shortComponentName);
+                if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
+                        + next);
+            } catch (Exception e) {
+                // Whoops, need to restart this activity!
+                if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
+                        + lastState + ": " + next);
+                next.setState(lastState, "resumeTopActivityInnerLocked");
 
-                    next.sleeping = false;
-                    mService.getAppWarningsLocked().onResumeActivity(next);
-                    next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState);
-                    next.clearOptionsLocked();
-                    transaction.setLifecycleStateRequest(
-                            ResumeActivityItem.obtain(next.app.getReportedProcState(),
-                                    getDisplay().getWindowContainerController()
-                                            .isNextTransitionForward()));
-                    mService.getLifecycleManager().scheduleTransaction(transaction);
-
-                    if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
-                            + next);
-                } catch (Exception e) {
-                    // Whoops, need to restart this activity!
-                    if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
-                            + lastState + ": " + next);
-                    next.setState(lastState, "resumeTopActivityInnerLocked");
-
-                    // lastResumedActivity being non-null implies there is a lastStack present.
-                    if (lastResumedActivity != null) {
-                        lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
-                    }
-
-                    Slog.i(TAG, "Restarting because process died: " + next);
-                    if (!next.hasBeenLaunched) {
-                        next.hasBeenLaunched = true;
-                    } else  if (SHOW_APP_STARTING_PREVIEW && lastFocusedStack != null
-                            && lastFocusedStack.isTopStackOnDisplay()) {
-                        next.showStartingWindow(null /* prev */, false /* newTask */,
-                                false /* taskSwitch */);
-                    }
-                    mStackSupervisor.startSpecificActivityLocked(next, true, false);
-                    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
-                    return true;
+                // lastResumedActivity being non-null implies there is a lastStack present.
+                if (lastResumedActivity != null) {
+                    lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
                 }
+
+                Slog.i(TAG, "Restarting because process died: " + next);
+                if (!next.hasBeenLaunched) {
+                    next.hasBeenLaunched = true;
+                } else  if (SHOW_APP_STARTING_PREVIEW && lastFocusedStack != null
+                        && lastFocusedStack.isTopStackOnDisplay()) {
+                    next.showStartingWindow(null /* prev */, false /* newTask */,
+                            false /* taskSwitch */);
+                }
+                mStackSupervisor.startSpecificActivityLocked(next, true, false);
+                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
+                return true;
             }
 
             // From this point on, if something goes wrong there is no way
@@ -4841,35 +4853,33 @@
         mTmpBounds.clear();
         mTmpInsetBounds.clear();
 
-        synchronized (mWindowManager.getWindowManagerLock()) {
-            for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
-                final TaskRecord task = mTaskHistory.get(i);
-                if (task.isResizeable()) {
-                    if (inFreeformWindowingMode()) {
-                        // TODO(b/71028874): Can be removed since each freeform task is its own
-                        //                   stack.
-                        // For freeform stack we don't adjust the size of the tasks to match that
-                        // of the stack, but we do try to make sure the tasks are still contained
-                        // with the bounds of the stack.
-                        if (task.getOverrideBounds() != null) {
-                            mTmpRect2.set(task.getOverrideBounds());
-                            fitWithinBounds(mTmpRect2, bounds);
-                            task.updateOverrideConfiguration(mTmpRect2);
-                        }
-                    } else {
-                        task.updateOverrideConfiguration(taskBounds, insetBounds);
+        for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
+            final TaskRecord task = mTaskHistory.get(i);
+            if (task.isResizeable()) {
+                if (inFreeformWindowingMode()) {
+                    // TODO(b/71028874): Can be removed since each freeform task is its own
+                    //                   stack.
+                    // For freeform stack we don't adjust the size of the tasks to match that
+                    // of the stack, but we do try to make sure the tasks are still contained
+                    // with the bounds of the stack.
+                    if (task.getOverrideBounds() != null) {
+                        mTmpRect2.set(task.getOverrideBounds());
+                        fitWithinBounds(mTmpRect2, bounds);
+                        task.updateOverrideConfiguration(mTmpRect2);
                     }
-                }
-
-                mTmpBounds.put(task.taskId, task.getOverrideBounds());
-                if (tempTaskInsetBounds != null) {
-                    mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds);
+                } else {
+                    task.updateOverrideConfiguration(taskBounds, insetBounds);
                 }
             }
 
-            mWindowContainerController.resize(bounds, mTmpBounds, mTmpInsetBounds);
-            setBounds(bounds);
+            mTmpBounds.put(task.taskId, task.getOverrideBounds());
+            if (tempTaskInsetBounds != null) {
+                mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds);
+            }
         }
+
+        mWindowContainerController.resize(bounds, mTmpBounds, mTmpInsetBounds);
+        setBounds(bounds);
     }
 
     void onPipAnimationEndResize() {
@@ -5174,12 +5184,14 @@
 
     /**
      * Removes the input task from this stack.
+     *
      * @param task to remove.
      * @param reason for removal.
      * @param mode task removal mode. Either {@link #REMOVE_TASK_MODE_DESTROYING},
      *             {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}.
      */
     void removeTask(TaskRecord task, String reason, int mode) {
+        // TODO(b/119259346): Move some logic below to TaskRecord. See bug for more context.
         for (ActivityRecord record : task.mActivities) {
             onActivityRemovedFromStack(record);
         }
@@ -5194,6 +5206,9 @@
         updateTaskMovement(task, true);
 
         if (mode == REMOVE_TASK_MODE_DESTROYING && task.mActivities.isEmpty()) {
+            // This task is going away, so save the last state if necessary.
+            task.saveLaunchingStateIfNeeded();
+
             // TODO: VI what about activity?
             final boolean isVoiceSession = task.voiceSession != null;
             if (isVoiceSession) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 77b331e..082f521 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -59,6 +59,13 @@
 import static android.view.Display.TYPE_VIRTUAL;
 import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
 
+import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
+import static com.android.server.am.ActivityStackSupervisorProto.DISPLAYS;
+import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
+import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT;
+import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
+import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES;
+import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
@@ -67,13 +74,6 @@
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
 import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
-import static com.android.server.am.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
-import static com.android.server.am.ActivityStackSupervisorProto.DISPLAYS;
-import static com.android.server.am.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
-import static com.android.server.am.ActivityStackSupervisorProto.IS_HOME_RECENTS_COMPONENT;
-import static com.android.server.am.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
-import static com.android.server.am.ActivityStackSupervisorProto.PENDING_ACTIVITIES;
-import static com.android.server.am.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_IDLE;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
@@ -121,6 +121,7 @@
 import android.app.ProfilerInfo;
 import android.app.ResultInfo;
 import android.app.WaitResult;
+import android.app.WindowConfiguration;
 import android.app.WindowConfiguration.ActivityType;
 import android.app.WindowConfiguration.WindowingMode;
 import android.app.servertransaction.ActivityLifecycleItem;
@@ -145,6 +146,7 @@
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.power.V1_0.PowerHint;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.FactoryTest;
@@ -174,6 +176,7 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.view.Display;
+import android.view.DisplayInfo;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -327,6 +330,9 @@
     WindowManagerService mWindowManager;
     DisplayManager mDisplayManager;
 
+     /** Common synchronization logic used to save things to disks. */
+    PersisterQueue mPersisterQueue;
+    LaunchParamsPersister mLaunchParamsPersister;
     private LaunchParamsController mLaunchParamsController;
 
     /**
@@ -631,10 +637,16 @@
         mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext, mHandler.getLooper());
         mKeyguardController = new KeyguardController(mService, this);
 
-        mLaunchParamsController = new LaunchParamsController(mService);
+        mPersisterQueue = new PersisterQueue();
+        mLaunchParamsPersister = new LaunchParamsPersister(mPersisterQueue, this);
+        mLaunchParamsController = new LaunchParamsController(mService, mLaunchParamsPersister);
         mLaunchParamsController.registerDefaultModifiers(this);
     }
 
+    void onSystemReady() {
+        mPersisterQueue.startPersisting();
+        mLaunchParamsPersister.onSystemReady();
+    }
 
     public ActivityMetricsLogger getActivityMetricsLogger() {
         return mActivityMetricsLogger;
@@ -789,7 +801,15 @@
         return startHomeOnDisplay(mCurrentUser, myReason, displayId);
     }
 
-    boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId) {
+    /**
+     * Check if home activity start should be allowed on a display.
+     * @param homeInfo {@code ActivityInfo} of the home activity that is going to be launched.
+     * @param displayId The id of the target display.
+     * @param allowInstrumenting Whether launching home should be allowed if being instrumented.
+     * @return {@code true} if allow to launch, {@code false} otherwise.
+     */
+    boolean canStartHomeOnDisplay(ActivityInfo homeInfo, int displayId,
+            boolean allowInstrumenting) {
         if (mService.mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                 && mService.mTopAction == null) {
             // We are running in factory test mode, but unable to find the factory test app, so
@@ -799,7 +819,7 @@
 
         final WindowProcessController app =
                 mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid);
-        if (app != null && app.isInstrumenting()) {
+        if (!allowInstrumenting && app != null && app.isInstrumenting()) {
             // Don't do this if the home app is currently being instrumented.
             return false;
         }
@@ -817,9 +837,13 @@
         }
 
         final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK
-                && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE;
+                && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE
+                && homeInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
         if (!supportMultipleInstance) {
-            // Can't launch home on other displays if it requested to be single instance.
+            // Can't launch home on other displays if it requested to be single instance. Also we
+            // don't allow home applications that target before Q to have multiple home activity
+            // instances because they may not be expected to have multiple home scenario and
+            // haven't explicitly request for single instance.
             return false;
         }
 
@@ -1049,20 +1073,26 @@
 
     boolean allResumedActivitiesIdle() {
         for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+            // TODO(b/117135575): Check resumed activities on all visible stacks.
             final ActivityDisplay display = mActivityDisplays.get(displayNdx);
-            for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
-                // We cannot only check the top stack on each display since there might have
-                // always-on-top stacks (e.g. pinned stack).
-                final ActivityStack stack = display.getChildAt(stackNdx);
-                if (stack.numActivities() == 0) {
-                    continue;
+            if (display.isSleeping()) {
+                // No resumed activities while display is sleeping.
+                continue;
+            }
+
+            // If the focused stack is not null or not empty, there should have some activities
+            // resuming or resumed. Make sure these activities are idle.
+            final ActivityStack stack = display.getFocusedStack();
+            if (stack == null || stack.numActivities() == 0) {
+                continue;
+            }
+            final ActivityRecord resumedActivity = stack.getResumedActivity();
+            if (resumedActivity == null || !resumedActivity.idle) {
+                if (DEBUG_STATES) {
+                    Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
+                            + stack.mStackId + " " + resumedActivity + " not idle");
                 }
-                final ActivityRecord resumedActivity = stack.getResumedActivity();
-                if (resumedActivity != null && !resumedActivity.idle) {
-                    if (DEBUG_STATES) Slog.d(TAG_STATES, "allResumedActivitiesIdle: stack="
-                             + stack.mStackId + " " + resumedActivity + " not idle");
-                    return false;
-                }
+                return false;
             }
         }
         // Send launch end powerhint when idle
@@ -1266,15 +1296,24 @@
             if (!aInfo.processName.equals("system")) {
                 if ((startFlags & (START_FLAG_DEBUG | START_FLAG_NATIVE_DEBUGGING
                         | START_FLAG_TRACK_ALLOCATION)) != 0 || profilerInfo != null) {
-                    /**
-                     * Assume safe to call into AMS synchronously because the call that set these
-                     * flags should have originated from AMS which will already have its lock held.
-                     * @see ActivityManagerService#startActivityAndWait(IApplicationThread, String,
-                     * Intent, String, IBinder, String, int, int, ProfilerInfo, Bundle, int)
-                     * TODO(b/80414790): Investigate a better way of untangling this.
-                     */
-                    mService.mAmInternal.setDebugFlagsForStartingActivity(
-                            aInfo, startFlags, profilerInfo);
+
+                     // Mimic an AMS synchronous call by passing a message to AMS and wait for AMS
+                     // to notify us that the task has completed.
+                     // TODO(b/80414790) look into further untangling for the situation where the
+                     // caller is on the same thread as the handler we are posting to.
+                    synchronized (mService.mGlobalLock) {
+                        // Post message to AMS.
+                        final Message msg = PooledLambda.obtainMessage(
+                                ActivityManagerInternal::setDebugFlagsForStartingActivity,
+                                mService.mAmInternal, aInfo, startFlags, profilerInfo,
+                                mService.mGlobalLock);
+                        mService.mH.sendMessage(msg);
+                        try {
+                            mService.mGlobalLock.wait();
+                        } catch (InterruptedException ignore) {
+
+                        }
+                    }
                 }
             }
             final String intentLaunchToken = intent.getLaunchToken();
@@ -1623,6 +1662,13 @@
             // restart the application.
         }
 
+        // Suppress transition until the new activity becomes ready, otherwise the keyguard can
+        // appear for a short amount of time before the new process with the new activity had the
+        // ability to set its showWhenLocked flags.
+        if (getKeyguardController().isKeyguardLocked()) {
+            r.notifyUnknownVisibilityLaunched();
+        }
+
         // Post message to start process to avoid possible deadlock of calling into AMS with the
         // ATMS lock held.
         final Message msg = PooledLambda.obtainMessage(
@@ -1976,8 +2022,9 @@
 
             //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
 
-            // Make sure we can finish booting when all resumed activities are idle.
-            if ((!mService.isBooted() && allResumedActivitiesIdle()) || fromTimeout) {
+            // Check if able to finish booting when device is booting and all resumed activities
+            // are idle.
+            if ((mService.isBooting() && allResumedActivitiesIdle()) || fromTimeout) {
                 booting = checkFinishBootingLocked();
             }
 
@@ -2050,7 +2097,7 @@
             }
         }
 
-        mService.mAmInternal.trimApplications();
+        mService.mH.post(() -> mService.mAmInternal.trimApplications());
         //dump();
         //mWindowManager.dump();
 
@@ -2359,7 +2406,7 @@
 
     <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
             @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop) {
-        return getLaunchStack(r, options, candidateTask, onTop, INVALID_DISPLAY);
+        return getLaunchStack(r, options, candidateTask, onTop, null /* launchParams */);
     }
 
     /**
@@ -2368,12 +2415,13 @@
      * @param r The activity we are trying to launch. Can be null.
      * @param options The activity options used to the launch. Can be null.
      * @param candidateTask The possible task the activity might be launched in. Can be null.
+     * @params launchParams The resolved launch params to use.
      *
      * @return The stack to use for the launch or INVALID_STACK_ID.
      */
     <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
             @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop,
-            int candidateDisplayId) {
+            @Nullable LaunchParamsController.LaunchParams launchParams) {
         int taskId = INVALID_TASK_ID;
         int displayId = INVALID_DISPLAY;
         //Rect bounds = null;
@@ -2381,9 +2429,6 @@
         // We give preference to the launch preference in activity options.
         if (options != null) {
             taskId = options.getLaunchTaskId();
-            displayId = options.getLaunchDisplayId();
-            // TODO: Need to work this into the equation...
-            //bounds = options.getLaunchBounds();
         }
 
         // First preference for stack goes to the task Id set in the activity options. Use the stack
@@ -2400,16 +2445,16 @@
         }
 
         final int activityType = resolveActivityType(r, options, candidateTask);
-        T stack = null;
+        T stack;
 
-        // Next preference for stack goes to the display Id set in the activity options or the
-        // candidate display.
-        if (displayId == INVALID_DISPLAY) {
-            displayId = candidateDisplayId;
+        // Next preference for stack goes to the display Id set the candidate display.
+        if (launchParams != null) {
+            displayId = launchParams.mPreferredDisplayId;
         }
         if (displayId != INVALID_DISPLAY && canLaunchOnDisplay(r, displayId)) {
             if (r != null) {
-                stack = (T) getValidLaunchStackOnDisplay(displayId, r, candidateTask, options);
+                stack = (T) getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
+                        launchParams);
                 if (stack != null) {
                     return stack;
                 }
@@ -2436,8 +2481,12 @@
         if (stack != null) {
             display = stack.getDisplay();
             if (display != null && canLaunchOnDisplay(r, display.mDisplayId)) {
-                final int windowingMode =
-                        display.resolveWindowingMode(r, options, candidateTask, activityType);
+                int windowingMode = launchParams != null ? launchParams.mWindowingMode
+                        : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+                if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
+                    windowingMode = display.resolveWindowingMode(r, options, candidateTask,
+                            activityType);
+                }
                 if (stack.isCompatible(windowingMode, activityType)) {
                     return stack;
                 }
@@ -2477,8 +2526,9 @@
      * @param candidateTask The possible task the activity might be put in.
      * @return Existing stack if there is a valid one, new dynamic stack if it is valid or null.
      */
-    ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
-            @Nullable TaskRecord candidateTask, @Nullable ActivityOptions options) {
+    private ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
+            @Nullable TaskRecord candidateTask, @Nullable ActivityOptions options,
+            @Nullable LaunchParamsController.LaunchParams launchParams) {
         final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
         if (activityDisplay == null) {
             throw new IllegalArgumentException(
@@ -2506,8 +2556,18 @@
 
         // If there is no valid stack on the external display - check if new dynamic stack will do.
         if (displayId != DEFAULT_DISPLAY) {
+            final int windowingMode;
+            if (launchParams != null) {
+                // When launch params is not null, we always defer to its windowing mode. Sometimes
+                // it could be unspecified, which indicates it should inherit windowing mode from
+                // display.
+                windowingMode = launchParams.mWindowingMode;
+            } else {
+                windowingMode = options != null ? options.getLaunchWindowingMode()
+                        : r.getWindowingMode();
+            }
             return activityDisplay.createStack(
-                    options != null ? options.getLaunchWindowingMode() : r.getWindowingMode(),
+                    windowingMode,
                     options != null ? options.getLaunchActivityType() : r.getActivityType(),
                     true /*onTop*/);
         }
@@ -2517,8 +2577,10 @@
     }
 
     ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r,
-            @Nullable ActivityOptions options) {
-        return getValidLaunchStackOnDisplay(displayId, r, null /* candidateTask */, options);
+            @Nullable ActivityOptions options,
+            @Nullable LaunchParamsController.LaunchParams launchParams) {
+        return getValidLaunchStackOnDisplay(displayId, r, null /* candidateTask */, options,
+                launchParams);
     }
 
     // TODO: Can probably be consolidated into getLaunchStack()...
@@ -2598,7 +2660,7 @@
                 continue;
             }
             final ActivityStack stack = getValidLaunchStackOnDisplay(display.mDisplayId, r,
-                    null /* options */);
+                    null /* options */, null /* launchParams */);
             if (stack != null) {
                 return stack;
             }
@@ -2611,8 +2673,7 @@
     }
 
     ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) {
-        getActivityDisplay(DEFAULT_DISPLAY).getHomeActivityForUser(userId);
-        return null;
+        return getActivityDisplay(DEFAULT_DISPLAY).getHomeActivityForUser(userId);
     }
 
     void resizeStackLocked(ActivityStack stack, Rect bounds, Rect tempTaskBounds,
@@ -3172,7 +3233,7 @@
                     + " to its current displayId=" + displayId);
         }
 
-        stack.reparent(activityDisplay, onTop);
+        stack.reparent(activityDisplay, onTop, false /* displayRemoved */);
         // TODO(multi-display): resize stacks properly if moved from split-screen.
     }
 
@@ -4136,7 +4197,12 @@
         if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
         synchronized (mService.mGlobalLock) {
             getActivityDisplayOrCreateLocked(displayId);
-            startHomeOnDisplay(mCurrentUser, "displayAdded", displayId);
+            // Do not start home before booting, or it may accidentally finish booting before it
+            // starts. Instead, we expect home activities to be launched when the system is ready
+            // (ActivityManagerService#systemReady).
+            if (mService.isBooted() || mService.isBooting()) {
+                startHomeOnDisplay(mCurrentUser, "displayAdded", displayId);
+            }
         }
     }
 
@@ -4214,6 +4280,25 @@
         return activityDisplay;
     }
 
+    /**
+     * Get an existing instance of {@link ActivityDisplay} that has the given uniqueId. Unique ID is
+     * defined in {@link DisplayInfo#uniqueId}.
+     *
+     * @param uniqueId the unique ID of the display
+     * @return the {@link ActivityDisplay} or {@code null} if nothing is found.
+     */
+    ActivityDisplay getActivityDisplay(String uniqueId) {
+        for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
+            final ActivityDisplay display = mActivityDisplays.get(i);
+            final boolean isValid = display.mDisplay.isValid();
+            if (isValid && display.mDisplay.getUniqueId().equals(uniqueId)) {
+                return display;
+            }
+        }
+
+        return null;
+    }
+
     boolean startHomeOnAllDisplays(int userId, String reason) {
         boolean homeStarted = false;
         for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
@@ -4234,7 +4319,7 @@
             return false;
         }
 
-        if (!canStartHomeOnDisplay(aInfo, displayId)) {
+        if (!canStartHomeOnDisplay(aInfo, displayId, false /* allowInstrumenting */)) {
             return false;
         }
 
@@ -4562,14 +4647,14 @@
     /**
      * Begin deferring resume to avoid duplicate resumes in one pass.
      */
-    private void beginDeferResume() {
+    void beginDeferResume() {
         mDeferResumeCount++;
     }
 
     /**
      * End deferring resume and determine if resume can be called.
      */
-    private void endDeferResume() {
+    void endDeferResume() {
         mDeferResumeCount--;
     }
 
@@ -4745,7 +4830,7 @@
                 final ActivityRecord targetActivity = task.getTopActivity();
 
                 sendPowerHintForLaunchStartIfNeeded(true /* forceSend */, targetActivity);
-                mActivityMetricsLogger.notifyActivityLaunching();
+                mActivityMetricsLogger.notifyActivityLaunching(task.intent);
                 try {
                     mService.moveTaskToFrontLocked(task.taskId, 0, options,
                             true /* fromRecents */);
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index e43a79a..d4c1bca 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -53,6 +53,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 
+import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
 import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
 import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
@@ -72,7 +73,6 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
-import static com.android.server.am.EventLogTags.AM_NEW_INTENT;
 import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
 import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
 
@@ -114,9 +114,9 @@
 import com.android.internal.app.IVoiceInteractor;
 import com.android.server.am.EventLogTags;
 import com.android.server.am.PendingIntentRecord;
+import com.android.server.pm.InstantAppResolver;
 import com.android.server.wm.ActivityStackSupervisor.PendingActivityLaunch;
 import com.android.server.wm.LaunchParamsController.LaunchParams;
-import com.android.server.pm.InstantAppResolver;
 
 import java.io.PrintWriter;
 import java.text.DateFormat;
@@ -996,7 +996,7 @@
         if (intent != null && intent.hasFileDescriptors()) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
         }
-        mSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
+        mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
         boolean componentSpecified = intent.getComponent() != null;
 
         final int realCallingPid = Binder.getCallingPid();
@@ -1284,8 +1284,8 @@
         // Do not start home activity if it cannot be launched on preferred display. We are not
         // doing this in ActivityStackSupervisor#canPlaceEntityOnDisplay because it might
         // fallback to launch on other displays.
-        if (r.isActivityTypeHome()
-                && !mSupervisor.canStartHomeOnDisplay(r.info, mPreferredDisplayId)) {
+        if (r.isActivityTypeHome() && !mSupervisor.canStartHomeOnDisplay(r.info,
+                mPreferredDisplayId, true /* allowInstrumenting */)) {
             Slog.w(TAG, "Cannot launch home on display " + mPreferredDisplayId);
             return START_CANCELED;
         }
@@ -2145,7 +2145,7 @@
             if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
                 // Can't use target display, lets find a stack on the source display.
                 mTargetStack = mSupervisor.getValidLaunchStackOnDisplay(
-                        sourceStack.mDisplayId, mStartActivity, mOptions);
+                        sourceStack.mDisplayId, mStartActivity, mOptions, mLaunchParams);
             }
             if (mTargetStack == null) {
                 // There are no suitable stacks on the target and source display(s). Look on all
@@ -2368,7 +2368,8 @@
 
         if (mPreferredDisplayId != DEFAULT_DISPLAY) {
             // Try to put the activity in a stack on a secondary display.
-            stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r, aOptions);
+            stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r, aOptions,
+                    mLaunchParams);
             if (stack == null) {
                 // If source display is not suitable - look for topmost valid stack in the system.
                 if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
@@ -2432,9 +2433,12 @@
                  || mPreferredDisplayId != DEFAULT_DISPLAY) {
             // We don't pass in the default display id into the get launch stack call so it can do a
             // full resolution.
-            final int candidateDisplay =
+            mLaunchParams.mPreferredDisplayId =
                     mPreferredDisplayId != DEFAULT_DISPLAY ? mPreferredDisplayId : INVALID_DISPLAY;
-            return mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP, candidateDisplay);
+            final ActivityStack stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP,
+                    mLaunchParams);
+            mLaunchParams.mPreferredDisplayId = mPreferredDisplayId;
+            return stack;
         }
         // Otherwise handle adjacent launch.
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index dcc7bc5..d665592 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -22,6 +22,7 @@
 import android.app.AppProtoEnums;
 import android.app.IActivityManager;
 import android.app.IApplicationThread;
+import android.app.ProfilerInfo;
 import android.content.ComponentName;
 import android.content.IIntentSender;
 import android.content.Intent;
@@ -468,4 +469,8 @@
     public abstract void clearLockedTasks(String reason);
     public abstract void updateUserConfiguration();
     public abstract boolean canShowErrorDialogs();
+
+    public abstract void setProfileApp(String profileApp);
+    public abstract void setProfileProc(WindowProcessController wpc);
+    public abstract void setProfilerInfo(ProfilerInfo profilerInfo);
 }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 3ede8bc8..1d00075 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -56,13 +56,13 @@
 import static android.os.Process.FIRST_APPLICATION_UID;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
-import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
 import static android.provider.Settings.Global.HIDE_ERROR_DIALOGS;
 import static android.provider.Settings.System.FONT_SCALE;
 import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
+import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.TRANSIT_NONE;
@@ -114,17 +114,17 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
-import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
-import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
-import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
-import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
 import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
+import static com.android.server.wm.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
+import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
 import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
 import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
+import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
+import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
+import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -190,7 +190,6 @@
 import android.os.IBinder;
 import android.os.IUserManager;
 import android.os.LocaleList;
-import android.os.Looper;
 import android.os.Message;
 import android.os.PersistableBundle;
 import android.os.PowerManager;
@@ -247,9 +246,11 @@
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.AppOpsService;
 import com.android.server.AttributeCache;
+import com.android.server.DisplayThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.SystemServiceManager;
+import com.android.server.UiThread;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.ActivityManagerServiceDumpActivitiesProto;
@@ -278,6 +279,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
@@ -347,7 +349,7 @@
     IntentFirewall mIntentFirewall;
 
     /* Global service lock used by the package the owns this service. */
-    Object mGlobalLock;
+    final WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock();
     ActivityStackSupervisor mStackSupervisor;
     WindowManagerService mWindowManager;
     private UserManagerService mUserManager;
@@ -395,6 +397,30 @@
     // How long to wait in getAutofillAssistStructure() for the activity to respond with the result.
     private static final int PENDING_AUTOFILL_ASSIST_STRUCTURE_TIMEOUT = 2000;
 
+    // Permission tokens are used to temporarily granted a trusted app the ability to call
+    // #startActivityAsCaller.  A client is expected to dump its token after this time has elapsed,
+    // showing any appropriate error messages to the user.
+    private static final long START_AS_CALLER_TOKEN_TIMEOUT =
+            10 * MINUTE_IN_MILLIS;
+
+    // How long before the service actually expires a token.  This is slightly longer than
+    // START_AS_CALLER_TOKEN_TIMEOUT, to provide a buffer so clients will rarely encounter the
+    // expiration exception.
+    private static final long START_AS_CALLER_TOKEN_TIMEOUT_IMPL =
+            START_AS_CALLER_TOKEN_TIMEOUT + 2 * 1000;
+
+    // How long the service will remember expired tokens, for the purpose of providing error
+    // messaging when a client uses an expired token.
+    private static final long START_AS_CALLER_TOKEN_EXPIRED_TIMEOUT =
+            START_AS_CALLER_TOKEN_TIMEOUT_IMPL + 20 * MINUTE_IN_MILLIS;
+
+    // Activity tokens of system activities that are delegating their call to
+    // #startActivityByCaller, keyed by the permissionToken granted to the delegate.
+    final HashMap<IBinder, IBinder> mStartActivitySources = new HashMap<>();
+
+    // Permission tokens that have expired, but we remember for error reporting.
+    final ArrayList<IBinder> mExpiredStartAsCallerTokens = new ArrayList<>();
+
     private final ArrayList<PendingAssistExtras> mPendingAssistExtras = new ArrayList<>();
 
     // Keeps track of the active voice interaction service component, notified from
@@ -466,6 +492,11 @@
     String mTopAction = Intent.ACTION_MAIN;
     String mTopData;
 
+    /** Profiling app information. */
+    String mProfileApp = null;
+    WindowProcessController mProfileProc = null;
+    ProfilerInfo mProfilerInfo = null;
+
     /**
      * Dump of the activity state at the time of the last ANR. Cleared after
      * {@link WindowManagerService#LAST_ANR_LIFETIME_DURATION_MSECS}
@@ -622,6 +653,7 @@
             mAssistUtils = new AssistUtils(mContext);
             mVrController.onSystemReady();
             mRecentTasks.onSystemReadyLocked();
+            mStackSupervisor.onSystemReady();
         }
     }
 
@@ -652,8 +684,6 @@
                 ActivityTaskManager.supportsSplitScreenMultiWindow(mContext);
         final boolean supportsMultiDisplay = mContext.getPackageManager()
                 .hasSystemFeature(FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS);
-        final boolean alwaysFinishActivities =
-                Settings.Global.getInt(resolver, ALWAYS_FINISH_ACTIVITIES, 0) != 0;
         final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
         final boolean forceResizable = Settings.Global.getInt(
                 resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
@@ -716,11 +746,13 @@
         }
     }
 
-    // TODO: Will be converted to WM lock once transition is complete.
-    public void setActivityManagerService(Object globalLock, Looper looper,
-            IntentFirewall intentFirewall, PendingIntentController intentController) {
-        mGlobalLock = globalLock;
-        mH = new H(looper);
+    public WindowManagerGlobalLock getGlobalLock() {
+        return mGlobalLock;
+    }
+
+    public void setActivityManagerService(IntentFirewall intentFirewall,
+            PendingIntentController intentController) {
+        mH = new H();
         mUiHandler = new UiHandler();
         mIntentFirewall = intentFirewall;
         final File systemDir = SystemServiceManager.ensureSystemDir();
@@ -879,6 +911,20 @@
             mService.start();
         }
 
+        @Override
+        public void onUnlockUser(int userId) {
+            synchronized (mService.getGlobalLock()) {
+                mService.mStackSupervisor.mLaunchParamsPersister.onUnlockUser(userId);
+            }
+        }
+
+        @Override
+        public void onCleanupUser(int userId) {
+            synchronized (mService.getGlobalLock()) {
+                mService.mStackSupervisor.mLaunchParamsPersister.onCleanupUser(userId);
+            }
+        }
+
         public ActivityTaskManagerService getService() {
             return mService;
         }
@@ -1138,16 +1184,43 @@
         }
     }
 
+
+    @Override
+    public IBinder requestStartActivityPermissionToken(IBinder delegatorToken) {
+        int callingUid = Binder.getCallingUid();
+        if (UserHandle.getAppId(callingUid) != SYSTEM_UID) {
+            throw new SecurityException("Only the system process can request a permission token, "
+                    + "received request from uid: " + callingUid);
+        }
+        IBinder permissionToken = new Binder();
+        synchronized (mGlobalLock) {
+            mStartActivitySources.put(permissionToken, delegatorToken);
+        }
+
+        Message expireMsg = PooledLambda.obtainMessage(
+                ActivityTaskManagerService::expireStartAsCallerTokenMsg, this, permissionToken);
+        mUiHandler.sendMessageDelayed(expireMsg, START_AS_CALLER_TOKEN_TIMEOUT_IMPL);
+
+        Message forgetMsg = PooledLambda.obtainMessage(
+                ActivityTaskManagerService::forgetStartAsCallerTokenMsg, this, permissionToken);
+        mUiHandler.sendMessageDelayed(forgetMsg, START_AS_CALLER_TOKEN_EXPIRED_TIMEOUT);
+
+        return permissionToken;
+    }
+
     @Override
     public final int startActivityAsCaller(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
-            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, boolean ignoreTargetSecurity,
-            int userId) {
-
+            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, IBinder permissionToken,
+            boolean ignoreTargetSecurity, int userId) {
         // This is very dangerous -- it allows you to perform a start activity (including
-        // permission grants) as any app that may launch one of your own activities.  So
-        // we will only allow this to be done from activities that are part of the core framework,
-        // and then only when they are running as the system.
+        // permission grants) as any app that may launch one of your own activities.  So we only
+        // allow this in two cases:
+        // 1)  The caller is an activity that is part of the core framework, and then only when it
+        //     is running as the system.
+        // 2)  The caller provides a valid permissionToken.  Permission tokens are one-time use and
+        //     can only be requested by a system activity, which may then delegate this call to
+        //     another app.
         final ActivityRecord sourceRecord;
         final int targetUid;
         final String targetPackage;
@@ -1156,17 +1229,46 @@
             if (resultTo == null) {
                 throw new SecurityException("Must be called from an activity");
             }
-            sourceRecord = mStackSupervisor.isInAnyStackLocked(resultTo);
-            if (sourceRecord == null) {
-                throw new SecurityException("Called with bad activity token: " + resultTo);
+            final IBinder sourceToken;
+            if (permissionToken != null) {
+                // To even attempt to use a permissionToken, an app must also have this signature
+                // permission.
+                mAmInternal.enforceCallingPermission(
+                        android.Manifest.permission.START_ACTIVITY_AS_CALLER,
+                        "startActivityAsCaller");
+                // If called with a permissionToken, we want the sourceRecord from the delegator
+                // activity that requested this token.
+                sourceToken = mStartActivitySources.remove(permissionToken);
+                if (sourceToken == null) {
+                    // Invalid permissionToken, check if it recently expired.
+                    if (mExpiredStartAsCallerTokens.contains(permissionToken)) {
+                        throw new SecurityException("Called with expired permission token: "
+                                + permissionToken);
+                    } else {
+                        throw new SecurityException("Called with invalid permission token: "
+                                + permissionToken);
+                    }
+                }
+            } else {
+                // This method was called directly by the source.
+                sourceToken = resultTo;
             }
-            if (!sourceRecord.info.packageName.equals("android")) {
-                throw new SecurityException(
-                        "Must be called from an activity that is declared in the android package");
+
+            sourceRecord = mStackSupervisor.isInAnyStackLocked(sourceToken);
+            if (sourceRecord == null) {
+                throw new SecurityException("Called with bad activity token: " + sourceToken);
             }
             if (sourceRecord.app == null) {
                 throw new SecurityException("Called without a process attached to activity");
             }
+
+            // Whether called directly or from a delegate, the source activity must be from the
+            // android package.
+            if (!sourceRecord.info.packageName.equals("android")) {
+                throw new SecurityException("Must be called from an activity that is "
+                        + "declared in the android package");
+            }
+
             if (UserHandle.getAppId(sourceRecord.app.mUid) != SYSTEM_UID) {
                 // This is still okay, as long as this activity is running under the
                 // uid of the original calling activity.
@@ -2658,6 +2760,9 @@
                 pae.extras.putParcelable(Intent.EXTRA_REFERRER, referrer);
             }
             if (structure != null) {
+                // Pre-fill the task/activity component for all assist data receivers
+                structure.setTaskId(pae.activity.getTask().taskId);
+                structure.setActivityComponent(pae.activity.realActivity);
                 structure.setHomeActivity(pae.isHome);
             }
             pae.haveResult = true;
@@ -2885,7 +2990,7 @@
 
     @Override
     public void setLockScreenShown(boolean keyguardShowing, boolean aodShowing,
-            int secondaryDisplayShowing) {
+            int[] secondaryDisplaysShowing) {
         if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires permission "
@@ -2903,7 +3008,7 @@
             }
             try {
                 mKeyguardController.setKeyguardShown(keyguardShowing, aodShowing,
-                        secondaryDisplayShowing);
+                        secondaryDisplaysShowing);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -4873,21 +4978,6 @@
                 mH.sendMessage(msg);
             }
         }
-
-        // Update the configuration with WM first and check if any of the stacks need to be resized
-        // due to the configuration change. If so, resize the stacks now and do any relaunches if
-        // necessary. This way we don't need to relaunch again afterwards in
-        // ensureActivityConfiguration().
-        if (mWindowManager != null) {
-            final int[] resizedStacks =
-                    mWindowManager.setNewDisplayOverrideConfiguration(mTempConfig, displayId);
-            if (resizedStacks != null) {
-                for (int stackId : resizedStacks) {
-                    resizeStackWithBoundsFromWindowManager(stackId, deferResume);
-                }
-            }
-        }
-
         return changes;
     }
 
@@ -4911,6 +5001,15 @@
         }
     }
 
+    private void expireStartAsCallerTokenMsg(IBinder permissionToken) {
+        mStartActivitySources.remove(permissionToken);
+        mExpiredStartAsCallerTokens.add(permissionToken);
+    }
+
+    private void forgetStartAsCallerTokenMsg(IBinder permissionToken) {
+        mExpiredStartAsCallerTokens.remove(permissionToken);
+    }
+
     boolean isActivityStartsLoggingEnabled() {
         return mAmInternal.isActivityStartsLoggingEnabled();
     }
@@ -5277,28 +5376,6 @@
         return "focused app: " + packageName;
     }
 
-    /** Helper method that requests bounds from WM and applies them to stack. */
-    private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) {
-        final Rect newStackBounds = new Rect();
-        final ActivityStack stack = mStackSupervisor.getStack(stackId);
-
-        // TODO(b/71548119): Revert CL introducing below once cause of mismatch is found.
-        if (stack == null) {
-            final StringWriter writer = new StringWriter();
-            final PrintWriter printWriter = new PrintWriter(writer);
-            mStackSupervisor.dumpDisplays(printWriter);
-            printWriter.flush();
-
-            Log.wtf(TAG, "stack not found:" + stackId + " displays:" + writer);
-        }
-
-        stack.getBoundsForNewConfiguration(newStackBounds);
-        mStackSupervisor.resizeStackLocked(
-                stack, !newStackBounds.isEmpty() ? newStackBounds : null /* bounds */,
-                null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
-                false /* preserveWindows */, false /* allowResizeInDockedMode */, deferResume);
-    }
-
     /** Applies latest configuration and/or visibility updates if needed. */
     private boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
         boolean kept = true;
@@ -5484,11 +5561,13 @@
 
     final class H extends Handler {
         static final int REPORT_TIME_TRACKER_MSG = 1;
+
+
         static final int FIRST_ACTIVITY_STACK_MSG = 100;
         static final int FIRST_SUPERVISOR_STACK_MSG = 200;
 
-        public H(Looper looper) {
-            super(looper, null, true);
+        public H() {
+            super(DisplayThread.get().getLooper());
         }
 
         @Override
@@ -5506,7 +5585,7 @@
         static final int DISMISS_DIALOG_UI_MSG = 1;
 
         public UiHandler() {
-            super(com.android.server.UiThread.get().getLooper(), null, true);
+            super(UiThread.get().getLooper(), null, true);
         }
 
         @Override
@@ -5657,8 +5736,12 @@
 
                 // We might change the visibilities here, so prepare an empty app transition which
                 // might be overridden later if we actually change visibilities.
-                final DisplayWindowController dwc = mStackSupervisor.getActivityDisplay(displayId)
-                        .getWindowContainerController();
+                final ActivityDisplay activityDisplay =
+                        mStackSupervisor.getActivityDisplay(displayId);
+                if (activityDisplay == null) {
+                    return;
+                }
+                final DisplayWindowController dwc = activityDisplay.getWindowContainerController();
                 final boolean wasTransitionSet = dwc.getPendingAppTransition() != TRANSIT_NONE;
                 if (!wasTransitionSet) {
                     dwc.prepareAppTransition(TRANSIT_NONE, false /* alwaysKeepCurrent */);
@@ -6296,8 +6379,11 @@
                             FLAG_ACTIVITY_TASK_ON_HOME);
                     ActivityOptions activityOptions = options != null
                             ? new ActivityOptions(options) : ActivityOptions.makeBasic();
-                    activityOptions.setLaunchTaskId(
-                            mStackSupervisor.getDefaultDisplayHomeActivity().getTask().taskId);
+                    final ActivityRecord homeActivity =
+                            mStackSupervisor.getDefaultDisplayHomeActivity();
+                    if (homeActivity != null) {
+                        activityOptions.setLaunchTaskId(homeActivity.getTask().taskId);
+                    }
                     mContext.startActivityAsUser(intent, activityOptions.toBundle(),
                             UserHandle.CURRENT);
                 } finally {
@@ -6762,5 +6848,26 @@
                         && mAmInternal.getCurrentUser().isDemo());
             }
         }
+
+        @Override
+        public void setProfileApp(String profileApp) {
+            synchronized (mGlobalLock) {
+                mProfileApp = profileApp;
+            }
+        }
+
+        @Override
+        public void setProfileProc(WindowProcessController wpc) {
+            synchronized (mGlobalLock) {
+                mProfileProc = wpc;
+            }
+        }
+
+        @Override
+        public void setProfilerInfo(ProfilerInfo profilerInfo) {
+            synchronized (mGlobalLock) {
+                mProfilerInfo = profilerInfo;
+            }
+        }
     }
-}
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 584c1e4..bd1460a 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -18,6 +18,7 @@
 
 import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
 import static android.app.ActivityOptions.ANIM_CUSTOM;
+import static android.app.ActivityOptions.ANIM_NONE;
 import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
 import static android.app.ActivityOptions.ANIM_REMOTE_ANIMATION;
 import static android.app.ActivityOptions.ANIM_SCALE_UP;
@@ -27,9 +28,9 @@
 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-
 import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
 import static android.view.WindowManager.TRANSIT_UNSET;
+
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -41,6 +42,7 @@
 import android.app.ActivityManager.TaskSnapshot;
 import android.app.ActivityOptions;
 import android.content.Intent;
+import android.content.ComponentName;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.GraphicBuffer;
@@ -80,6 +82,7 @@
     private final class H extends Handler {
         public static final int NOTIFY_WINDOWS_DRAWN = 1;
         public static final int NOTIFY_STARTING_WINDOW_DRAWN = 2;
+        public static final int NOTIFY_WINDOWS_NOTDRAWN = 3;
 
         public H(Looper looper) {
             super(looper);
@@ -94,16 +97,24 @@
                     }
                     if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
                             + AppWindowContainerController.this.mToken);
-                    mListener.onWindowsDrawn(msg.getWhen());
+                    mListener.onWindowsDrawn(true /* drawn */, msg.getWhen());
                     break;
                 case NOTIFY_STARTING_WINDOW_DRAWN:
                     if (mListener == null) {
                         return;
                     }
-                    if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
+                    if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting starting window drawn in "
                             + AppWindowContainerController.this.mToken);
                     mListener.onStartingWindowDrawn(msg.getWhen());
                     break;
+                case NOTIFY_WINDOWS_NOTDRAWN:
+                    if (mListener == null) {
+                        return;
+                    }
+                    if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting not drawn in "
+                            + AppWindowContainerController.this.mToken);
+                    mListener.onWindowsDrawn(false /* drawn */, msg.getWhen());
+                    break;
                 default:
                     break;
             }
@@ -199,20 +210,21 @@
     };
 
     public AppWindowContainerController(TaskWindowContainerController taskController,
-            IApplicationToken token, AppWindowContainerListener listener, int index,
-            int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
+            IApplicationToken token, ComponentName activityComponent,
+            AppWindowContainerListener listener, int index, int requestedOrientation,
+            boolean fullscreen, boolean showForAllUsers, int configChanges,
             boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
             int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos) {
-        this(taskController, token, listener, index, requestedOrientation, fullscreen,
-                showForAllUsers,
-                configChanges, voiceInteraction, launchTaskBehind, alwaysFocusable,
-                targetSdkVersion, rotationAnimationHint, inputDispatchingTimeoutNanos,
-                WindowManagerService.getInstance());
+        this(taskController, token, activityComponent, listener, index, requestedOrientation,
+                fullscreen, showForAllUsers, configChanges, voiceInteraction, launchTaskBehind,
+                alwaysFocusable, targetSdkVersion, rotationAnimationHint,
+                inputDispatchingTimeoutNanos, WindowManagerService.getInstance());
     }
 
     public AppWindowContainerController(TaskWindowContainerController taskController,
-            IApplicationToken token, AppWindowContainerListener listener, int index,
-            int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges,
+            IApplicationToken token, ComponentName activityComponent,
+            AppWindowContainerListener listener, int index, int requestedOrientation,
+            boolean fullscreen, boolean showForAllUsers, int configChanges,
             boolean voiceInteraction, boolean launchTaskBehind, boolean alwaysFocusable,
             int targetSdkVersion, int rotationAnimationHint, long inputDispatchingTimeoutNanos,
             WindowManagerService service) {
@@ -233,10 +245,10 @@
                         + " controller=" + taskController);
             }
 
-            atoken = createAppWindow(mService, token, voiceInteraction, task.getDisplayContent(),
-                    inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion,
-                    requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind,
-                    alwaysFocusable, this);
+            atoken = createAppWindow(mService, token, activityComponent, voiceInteraction,
+                    task.getDisplayContent(), inputDispatchingTimeoutNanos, fullscreen,
+                    showForAllUsers, targetSdkVersion, requestedOrientation, rotationAnimationHint,
+                    configChanges, launchTaskBehind, alwaysFocusable, this);
             if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addAppToken: " + atoken
                     + " controller=" + taskController + " at " + index);
             task.addChild(atoken, index);
@@ -245,11 +257,12 @@
 
     @VisibleForTesting
     AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
-            boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
-            boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
-            int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
-            boolean alwaysFocusable, AppWindowContainerController controller) {
-        return new AppWindowToken(service, token, voiceInteraction, dc,
+            ComponentName component, boolean voiceInteraction, DisplayContent dc,
+            long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
+            int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
+            boolean launchTaskBehind, boolean alwaysFocusable,
+            AppWindowContainerController controller) {
+        return new AppWindowToken(service, token, component, voiceInteraction, dc,
                 inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
                 rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
                 controller);
@@ -758,6 +771,10 @@
         mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_DRAWN));
     }
 
+    void reportWindowsNotDrawn() {
+        mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_NOTDRAWN));
+    }
+
     void reportWindowsVisible() {
         mHandler.post(mOnWindowsVisible);
     }
@@ -862,6 +879,8 @@
                     displayContent.mAppTransition.overridePendingAppTransitionRemote(
                             pendingOptions.getRemoteAnimationAdapter());
                     break;
+                case ANIM_NONE:
+                    break;
                 default:
                     Slog.e(TAG_WM, "applyOptionsLocked: Unknown animationType=" + animationType);
                     break;
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerListener.java b/services/core/java/com/android/server/wm/AppWindowContainerListener.java
index 8a39a74..ad27669 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerListener.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerListener.java
@@ -18,8 +18,8 @@
 
 /** Interface used by the creator of the controller to listen to changes with the container. */
 public interface AppWindowContainerListener extends WindowContainerListener {
-    /** Called when the windows associated app window container are drawn. */
-    void onWindowsDrawn(long timestamp);
+    /** Called when the windows associated app window container drawn state changes. */
+    void onWindowsDrawn(boolean drawn, long timestamp);
     /** Called when the windows associated app window container are visible. */
     void onWindowsVisible();
     /** Called when the windows associated app window container are no longer visible. */
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 9baafcb..92944a0 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -81,6 +81,7 @@
 
 import android.annotation.CallSuper;
 import android.app.Activity;
+import android.content.ComponentName;
 import android.content.res.Configuration;
 import android.graphics.GraphicBuffer;
 import android.graphics.Point;
@@ -94,6 +95,7 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.DisplayInfo;
 import android.view.IApplicationToken;
+import android.view.InputApplicationHandle;
 import android.view.RemoteAnimationDefinition;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
@@ -104,7 +106,6 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
-import com.android.server.input.InputApplicationHandle;
 import com.android.server.policy.WindowManagerPolicy.StartingSurface;
 import com.android.server.wm.WindowManagerService.H;
 
@@ -130,7 +131,7 @@
 
     // Non-null only for application tokens.
     final IApplicationToken appToken;
-
+    final ComponentName mActivityComponent;
     final boolean mVoiceInteraction;
 
     /** @see WindowContainer#fillsParent() */
@@ -272,12 +273,13 @@
     /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
     boolean mNeedsAnimationBoundsLayer;
 
-    AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
-            DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen,
-            boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint,
-            int configChanges, boolean launchTaskBehind, boolean alwaysFocusable,
+    AppWindowToken(WindowManagerService service, IApplicationToken token,
+            ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
+            long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
+            int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
+            boolean launchTaskBehind, boolean alwaysFocusable,
             AppWindowContainerController controller) {
-        this(service, token, voiceInteraction, dc, fullscreen);
+        this(service, token, activityComponent, voiceInteraction, dc, fullscreen);
         setController(controller);
         mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
         mShowForAllUsers = showForAllUsers;
@@ -293,11 +295,13 @@
         hiddenRequested = true;
     }
 
-    AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction,
-            DisplayContent dc, boolean fillsParent) {
+    AppWindowToken(WindowManagerService service, IApplicationToken token,
+            ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
+            boolean fillsParent) {
         super(service, token != null ? token.asBinder() : null, TYPE_APPLICATION, true, dc,
                 false /* ownerCanManageAppTokens */);
         appToken = token;
+        mActivityComponent = activityComponent;
         mVoiceInteraction = voiceInteraction;
         mFillsParent = fillsParent;
         mInputApplicationHandle = new InputApplicationHandle(this);
@@ -362,6 +366,10 @@
                 if (controller != null) {
                     controller.reportWindowsDrawn();
                 }
+            } else {
+                if (controller != null) {
+                    controller.reportWindowsNotDrawn();
+                }
             }
             reportedDrawn = nowDrawn;
         }
@@ -1745,6 +1753,7 @@
                 .setName(getSurfaceControl() + " - animation-bounds")
                 .setSize(getSurfaceWidth(), getSurfaceHeight());
         final SurfaceControl boundsLayer = builder.build();
+        t.setWindowCrop(boundsLayer, getSurfaceWidth(), getSurfaceHeight());
         t.show(boundsLayer);
         return boundsLayer;
     }
@@ -2010,9 +2019,7 @@
         clearThumbnail();
         setClientHidden(isHidden() && hiddenRequested);
 
-        if (mService.mInputMethodTarget != null && mService.mInputMethodTarget.mAppToken == this) {
-            getDisplayContent().computeImeTarget(true /* updateImeTarget */);
-        }
+        getDisplayContent().computeImeTargetIfNeeded(this);
 
         if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
                 + ": reportedVisible=" + reportedVisible
@@ -2155,6 +2162,7 @@
         if (appToken != null) {
             pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
         }
+        pw.println(prefix + "component=" + mActivityComponent.flattenToShortString());
         pw.print(prefix); pw.print("task="); pw.println(getTask());
         pw.print(prefix); pw.print(" mFillsParent="); pw.print(mFillsParent);
                 pw.print(" mOrientation="); pw.println(mOrientation);
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index e358ad5..9633864 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -52,7 +52,7 @@
                     .setColorLayer(true)
                     .setParent(null) // TODO: Work-around for b/69259549
                     .build();
-
+            transaction.setWindowCrop(surface, w, h);
             transaction.setLayerStack(surface, dc.getDisplayId());
             transaction.setAlpha(surface, 1);
             transaction.setLayer(surface, layer);
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 65c8e96..cc14afc 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -126,9 +126,10 @@
         DimState(SurfaceControl dimLayer) {
             mDimLayer = dimLayer;
             mDimming = true;
-            mSurfaceAnimator = new SurfaceAnimator(new DimAnimatable(dimLayer), () -> {
+            final DimAnimatable dimAnimatable = new DimAnimatable(dimLayer);
+            mSurfaceAnimator = new SurfaceAnimator(dimAnimatable, () -> {
                 if (!mDimming) {
-                    mDimLayer.destroy();
+                    dimAnimatable.getPendingTransaction().destroy(mDimLayer);
                 }
             }, mHost.mService);
         }
@@ -309,6 +310,7 @@
             // TODO: Once we use geometry from hierarchy this falls away.
             t.setSize(mDimState.mDimLayer, bounds.width(), bounds.height());
             t.setPosition(mDimState.mDimLayer, bounds.left, bounds.top);
+            t.setWindowCrop(mDimState.mDimLayer, bounds.width(), bounds.height());
             if (!mDimState.isVisible) {
                 mDimState.isVisible = true;
                 t.show(mDimState.mDimLayer);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 348b2af..a3e8029 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -100,7 +100,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.WindowManagerService.CUSTOM_SCREEN_ROTATION;
-import static com.android.server.wm.WindowManagerService.H.REPORT_FOCUS_CHANGE;
 import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
 import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
 import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
@@ -157,8 +156,8 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
 import android.view.SurfaceSession;
-import android.view.WindowManagerPolicyConstants.PointerEventListener;
 import android.view.WindowManager;
+import android.view.WindowManagerPolicyConstants.PointerEventListener;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
@@ -496,6 +495,15 @@
      */
     WindowState mInputMethodWindow;
 
+    /**
+     * This just indicates the window the input method is on top of, not
+     * necessarily the window its input is going to.
+     */
+    WindowState mInputMethodTarget;
+
+    /** If true hold off on modifying the animation layer of mInputMethodTarget */
+    boolean mInputMethodTargetWaitingAnim;
+
     private final PointerEventDispatcher mPointerEventDispatcher;
 
     private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
@@ -699,7 +707,7 @@
 
     private final Consumer<WindowState> mApplyPostLayoutPolicy =
             w -> mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
-                    mService.mInputMethodTarget);
+                    mInputMethodTarget);
 
     private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
         final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
@@ -1153,14 +1161,19 @@
     }
 
     /**
-     * Update rotation of the display with an option to force the update.
+     * Update rotation of the DisplayContent with an option to force the update. This updates
+     * the container's perception of rotation and, depending on the top activities, will freeze
+     * the screen or start seamless rotation. The display itself gets rotated in
+     * {@link #applyRotationLocked} during {@link WindowManagerService#sendNewConfiguration}.
+     *
      * @param forceUpdate Force the rotation update. Sometimes in WM we might skip updating
      *                    orientation because we're waiting for some rotation to finish or display
      *                    to unfreeze, which results in configuration of the previously visible
      *                    activity being applied to a newly visible one. Forcing the rotation
      *                    update allows to workaround this issue.
      * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
-     *         {@link WindowManagerService#sendNewConfiguration(int)} TO UNFREEZE THE SCREEN.
+     *         {@link WindowManagerService#sendNewConfiguration(int)} TO COMPLETE THE ROTATION AND
+     *         UNFREEZE THE SCREEN.
      */
     boolean updateRotationUnchecked(boolean forceUpdate) {
         ScreenRotationAnimation screenRotationAnimation;
@@ -1258,7 +1271,7 @@
             mService.mWaitingForConfig = true;
         }
 
-        setRotation(rotation);
+        mRotation = rotation;
         mAltOrientation = altOrientation;
 
         mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
@@ -1272,18 +1285,29 @@
         if (!rotateSeamlessly) {
             mService.startFreezingDisplayLocked(anim[0], anim[1], this);
             // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
-            screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked(
-                    mDisplayId);
         } else {
             // The screen rotation animation uses a screenshot to freeze the screen
             // while windows resize underneath.
             // When we are rotating seamlessly, we allow the elements to transition
             // to their rotated state independently and without a freeze required.
-            screenRotationAnimation = null;
-
             mService.startSeamlessRotation();
         }
 
+        return true;
+    }
+
+    /**
+     * Applies the rotation transaction. This must be called after {@link #updateRotationUnchecked}
+     * (if it returned {@code true}) to actually finish the rotation.
+     *
+     * @param oldRotation the rotation we are coming from.
+     * @param rotation the rotation to apply.
+     */
+    void applyRotationLocked(final int oldRotation, final int rotation) {
+        mDisplayRotation.setRotation(rotation);
+        final boolean rotateSeamlessly = mService.isRotatingSeamlessly();
+        ScreenRotationAnimation screenRotationAnimation = rotateSeamlessly
+                ? null : mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
         // We need to update our screen size information to match the new rotation. If the rotation
         // has actually changed then this method will return true and, according to the comment at
         // the top of the method, the caller is obligated to call computeNewConfigurationLocked().
@@ -1344,8 +1368,6 @@
                 && isDefaultDisplay) {
             mService.mAccessibilityController.onRotationChangedLocked(this);
         }
-
-        return true;
     }
 
     void configureDisplayPolicy() {
@@ -1455,7 +1477,6 @@
                     mCompatDisplayMetrics);
         }
 
-        updateBounds();
         return mDisplayInfo;
     }
 
@@ -1489,11 +1510,14 @@
      */
     void computeScreenConfiguration(Configuration config) {
         final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode);
+        calculateBounds(displayInfo, mTmpBounds);
+        config.windowConfiguration.setBounds(mTmpBounds);
 
         final int dw = displayInfo.logicalWidth;
         final int dh = displayInfo.logicalHeight;
         config.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
         config.windowConfiguration.setWindowingMode(getWindowingMode());
+        config.windowConfiguration.setRotation(displayInfo.rotation);
 
         final float density = mDisplayMetrics.density;
         config.screenWidthDp =
@@ -1525,7 +1549,7 @@
         config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
         config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
         config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, config.uiMode, dw,
-                dh, mDisplayId);
+                dh, displayInfo.displayCutout, mDisplayId);
         config.densityDpi = displayInfo.logicalDensityDpi;
 
         config.colorMode =
@@ -1602,7 +1626,7 @@
     }
 
     private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh,
-            int displayId) {
+            DisplayCutout displayCutout, int displayId) {
         mTmpDisplayMetrics.setTo(mDisplayMetrics);
         final DisplayMetrics tmpDm = mTmpDisplayMetrics;
         final int unrotDw, unrotDh;
@@ -1614,22 +1638,22 @@
             unrotDh = dh;
         }
         int sw = reduceCompatConfigWidthSize(0, Surface.ROTATION_0, uiMode, tmpDm, unrotDw, unrotDh,
-                displayId);
+                displayCutout, displayId);
         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_90, uiMode, tmpDm, unrotDh, unrotDw,
-                displayId);
+                displayCutout, displayId);
         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_180, uiMode, tmpDm, unrotDw, unrotDh,
-                displayId);
+                displayCutout, displayId);
         sw = reduceCompatConfigWidthSize(sw, Surface.ROTATION_270, uiMode, tmpDm, unrotDh, unrotDw,
-                displayId);
+                displayCutout, displayId);
         return sw;
     }
 
     private int reduceCompatConfigWidthSize(int curSize, int rotation, int uiMode,
-            DisplayMetrics dm, int dw, int dh, int displayId) {
+            DisplayMetrics dm, int dw, int dh, DisplayCutout displayCutout, int displayId) {
         dm.noncompatWidthPixels = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode,
-                displayId, mDisplayInfo.displayCutout);
+                displayId, displayCutout);
         dm.noncompatHeightPixels = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation,
-                uiMode, displayId, mDisplayInfo.displayCutout);
+                uiMode, displayId, displayCutout);
         float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
         int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
         if (curSize == 0 || size < curSize) {
@@ -1667,24 +1691,24 @@
                 unrotDw);
         int sl = Configuration.resetScreenLayout(outConfig.screenLayout);
         sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh, uiMode,
-                displayId);
+                displayInfo.displayCutout, displayId);
         sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw, uiMode,
-                displayId);
+                displayInfo.displayCutout, displayId);
         sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh, uiMode,
-                displayId);
+                displayInfo.displayCutout, displayId);
         sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw, uiMode,
-                displayId);
+                displayInfo.displayCutout, displayId);
         outConfig.smallestScreenWidthDp = (int)(displayInfo.smallestNominalAppWidth / density);
         outConfig.screenLayout = sl;
     }
 
     private int reduceConfigLayout(int curLayout, int rotation, float density, int dw, int dh,
-            int uiMode, int displayId) {
+            int uiMode, DisplayCutout displayCutout, int displayId) {
         // Get the app screen size at this rotation.
         int w = mService.mPolicy.getNonDecorDisplayWidth(dw, dh, rotation, uiMode, displayId,
-                mDisplayInfo.displayCutout);
+                displayCutout);
         int h = mService.mPolicy.getNonDecorDisplayHeight(dw, dh, rotation, uiMode, displayId,
-                mDisplayInfo.displayCutout);
+                displayCutout);
 
         // Compute the screen layout size class for this rotation.
         int longSize = w;
@@ -1858,11 +1882,26 @@
     public void onConfigurationChanged(Configuration newParentConfig) {
         super.onConfigurationChanged(newParentConfig);
 
+        // If there was no pinned stack, we still need to notify the controller of the display info
+        // update as a result of the config change.
+        if (mPinnedStackControllerLocked != null && !hasPinnedStack()) {
+            mPinnedStackControllerLocked.onDisplayInfoChanged(getDisplayInfo());
+        }
+
         // The display size information is heavily dependent on the resources in the current
         // configuration, so we need to reconfigure it every time the configuration changes.
         // See {@link #configureDisplayPolicy}...sigh...
         mService.reconfigureDisplayLocked(this);
 
+    }
+
+    /**
+     * Updates the resources used by docked/pinned controllers. This needs to be called at the
+     * beginning of a configuration update cascade since the metrics from these resources are used
+     * for bounds calculations. Since ActivityDisplay initiates the configuration update, this
+     * should be called from there instead of DisplayContent's onConfigurationChanged.
+     */
+    void preOnConfigurationChanged() {
         final DockedStackDividerController dividerController = getDockedDividerController();
 
         if (dividerController != null) {
@@ -1876,26 +1915,6 @@
         }
     }
 
-    /**
-     * Callback used to trigger bounds update after configuration change and get ids of stacks whose
-     * bounds were updated.
-     */
-    void updateStackBoundsAfterConfigChange(@NonNull List<TaskStack> changedStackList) {
-        for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
-            final TaskStack stack = mTaskStackContainers.getChildAt(i);
-            if (stack.updateBoundsAfterConfigChange()) {
-                changedStackList.add(stack);
-            }
-        }
-
-        // If there was no pinned stack, we still need to notify the controller of the display info
-        // update as a result of the config change.  We do this here to consolidate the flow between
-        // changes when there is and is not a stack.
-        if (!hasPinnedStack()) {
-            mPinnedStackControllerLocked.onDisplayInfoChanged();
-        }
-    }
-
     @Override
     boolean fillsParent() {
         return true;
@@ -1917,7 +1936,7 @@
      * rather than directly above their target.
      */
     private boolean skipTraverseChild(WindowContainer child) {
-        if (child == mImeWindowsContainers && mService.mInputMethodTarget != null
+        if (child == mImeWindowsContainers && mInputMethodTarget != null
                 && !hasSplitScreenPrimaryStack()) {
             return true;
         }
@@ -2000,9 +2019,7 @@
         mDisplay.getDisplayInfo(mDisplayInfo);
         mDisplay.getMetrics(mDisplayMetrics);
 
-        for (int i = mTaskStackContainers.getChildCount() - 1; i >= 0; --i) {
-            mTaskStackContainers.getChildAt(i).updateDisplayInfo(null);
-        }
+        onDisplayChanged(this);
     }
 
     void initializeDisplayBaseInfo() {
@@ -2121,7 +2138,7 @@
         if (density == mInitialDisplayDensity) {
             density = 0;
         }
-        mService.mDisplaySettings.setForcedDensity(this, density, userId);
+        mService.mDisplayWindowSettings.setForcedDensity(this, density, userId);
     }
 
     /** @param mode {@link #FORCE_SCALING_MODE_AUTO} or {@link #FORCE_SCALING_MODE_DISABLED}. */
@@ -2134,7 +2151,7 @@
         Slog.i(TAG_WM, "Using display scaling mode: " + (mDisplayScalingDisabled ? "off" : "auto"));
         mService.reconfigureDisplayLocked(this);
 
-        mService.mDisplaySettings.setForcedScalingMode(this, mode);
+        mService.mDisplayWindowSettings.setForcedScalingMode(this, mode);
     }
 
     /** If the given width and height equal to initial size, the setting will be cleared. */
@@ -2156,7 +2173,7 @@
         if (clear) {
             width = height = 0;
         }
-        mService.mDisplaySettings.setForcedSize(this, width, height);
+        mService.mDisplayWindowSettings.setForcedSize(this, width, height);
     }
 
     void getStableRect(Rect out) {
@@ -2494,11 +2511,15 @@
 
     void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
         getBounds(mTmpRect, newRotation);
+        rotateBounds(mTmpRect, oldRotation, newRotation, bounds);
+    }
 
+    void rotateBounds(Rect parentBounds, int oldRotation, int newRotation, Rect bounds) {
         // Compute a transform matrix to undo the coordinate space transformation,
         // and present the window at the same physical position it previously occupied.
         final int deltaRotation = deltaRotation(newRotation, oldRotation);
-        createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix);
+        createRotationMatrix(
+                deltaRotation, parentBounds.width(), parentBounds.height(), mTmpMatrix);
 
         mTmpRectF.set(bounds);
         mTmpMatrix.mapRect(mTmpRectF);
@@ -2787,13 +2808,12 @@
         if (mCurrentFocus == newFocus) {
             return false;
         }
-        mService.mH.obtainMessage(REPORT_FOCUS_CHANGE, this).sendToTarget();
         boolean imWindowChanged = false;
         // TODO (b/111080190): Multi-Session IME
         if (!focusFound) {
             final WindowState imWindow = mInputMethodWindow;
             if (imWindow != null) {
-                final WindowState prevTarget = mService.mInputMethodTarget;
+                final WindowState prevTarget = mInputMethodTarget;
 
                 final WindowState newTarget = computeImeTarget(true /* updateImeTarget*/);
                 imWindowChanged = prevTarget != newTarget;
@@ -2985,13 +3005,13 @@
             // There isn't an IME so there shouldn't be a target...That was easy!
             if (updateImeTarget) {
                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
-                        + mService.mInputMethodTarget + " to null since mInputMethodWindow is null");
-                setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim);
+                        + mInputMethodTarget + " to null since mInputMethodWindow is null");
+                setInputMethodTarget(null, mInputMethodTargetWaitingAnim);
             }
             return null;
         }
 
-        final WindowState curTarget = mService.mInputMethodTarget;
+        final WindowState curTarget = mInputMethodTarget;
         if (!canUpdateImeTarget()) {
             if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target");
             return curTarget;
@@ -3018,7 +3038,7 @@
         }
 
         if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
-                "Proposed new IME target: " + target);
+                "Proposed new IME target: " + target + " for display: " + getDisplayId());
 
         // Now, a special case -- if the last target's window is in the process of exiting, but
         // not removed, and the new target is home, keep on the last target to avoid flicker.
@@ -3039,7 +3059,7 @@
                 if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
                         + " to null." + (SHOW_STACK_CRAWLS ? " Callers="
                         + Debug.getCallers(4) : ""));
-                setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim);
+                setInputMethodTarget(null, mInputMethodTargetWaitingAnim);
             }
 
             return null;
@@ -3078,14 +3098,23 @@
         return target;
     }
 
+    /**
+     * Calling {@link #computeImeTarget(boolean)} to update the input method target window in
+     * the candidate app window token if needed.
+     */
+    void computeImeTargetIfNeeded(AppWindowToken candidate) {
+        if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == candidate) {
+            computeImeTarget(true /* updateImeTarget */);
+        }
+    }
+
     private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) {
-        if (target == mService.mInputMethodTarget
-                && mService.mInputMethodTargetWaitingAnim == targetWaitingAnim) {
+        if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) {
             return;
         }
 
-        mService.mInputMethodTarget = target;
-        mService.mInputMethodTargetWaitingAnim = targetWaitingAnim;
+        mInputMethodTarget = target;
+        mInputMethodTargetWaitingAnim = targetWaitingAnim;
         assignWindowLayers(false /* setLayoutNeeded */);
     }
 
@@ -3426,27 +3455,27 @@
     }
 
     private void updateBounds() {
-        calculateBounds(mTmpBounds);
+        calculateBounds(mDisplayInfo, mTmpBounds);
         setBounds(mTmpBounds);
     }
 
     // Determines the current display bounds based on the current state
-    private void calculateBounds(Rect out) {
+    private void calculateBounds(DisplayInfo displayInfo, Rect out) {
         // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
-        final int orientation = mDisplayInfo.rotation;
-        boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
+        final int rotation = displayInfo.rotation;
+        boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
         final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
         final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
-        int width = mDisplayInfo.logicalWidth;
+        int width = displayInfo.logicalWidth;
         int left = (physWidth - width) / 2;
-        int height = mDisplayInfo.logicalHeight;
+        int height = displayInfo.logicalHeight;
         int top = (physHeight - height) / 2;
         out.set(left, top, left + width, top + height);
     }
 
     @Override
     public void getBounds(Rect out) {
-        calculateBounds(out);
+        calculateBounds(mDisplayInfo, out);
     }
 
     private void getBounds(Rect out, int orientation) {
@@ -4474,7 +4503,7 @@
         mTaskStackContainers.assignLayer(t, 1);
         mAboveAppWindowsContainers.assignLayer(t, 2);
 
-        WindowState imeTarget = mService.mInputMethodTarget;
+        final WindowState imeTarget = mInputMethodTarget;
         boolean needAssignIme = true;
 
         // In the case where we have an IME target that is not in split-screen
@@ -4651,4 +4680,16 @@
 
         pendingLayoutChanges |= changes;
     }
+
+    /**
+     * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+     */
+    boolean supportsSystemDecorations() {
+        // TODO(b/114338689): Read the setting from DisplaySettings.
+        return mDisplay.supportsSystemDecorations()
+                // TODO (b/111363427): Remove this and set the new FLAG_SHOULD_SHOW_LAUNCHER flag
+                // (b/114338689) whenever vr 2d display id is set.
+                || mDisplayId == mService.mVr2dDisplayId
+                || mService.mForceDesktopModeOnExternalDisplays;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 9f98dc5..6ab7090 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -265,7 +265,8 @@
             mUserRotation = userRotation;
             changed = true;
         }
-        mService.mDisplaySettings.setUserRotation(mDisplayContent, userRotationMode, userRotation);
+        mService.mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
+                userRotation);
         if (changed) {
             mService.updateRotation(true /* alwaysSendConfiguration */,
                     false /* forceRelayout */);
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
index f772216..864f7e1 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -88,9 +88,34 @@
 
     @Override
     public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
-        // TODO: The container receives override configuration changes through other means. enabling
-        // callbacks through the controller causes layout issues. Investigate consolidating
-        // override configuration propagation to just here.
+        synchronized (mGlobalLock) {
+            if (mContainer != null) {
+                mContainer.mService.setNewDisplayOverrideConfiguration(overrideConfiguration,
+                        mContainer);
+            }
+        }
+    }
+
+    /**
+     * Updates the docked/pinned controller resources to the current system context.
+     */
+    public void preOnConfigurationChanged() {
+        synchronized (mGlobalLock) {
+            if (mContainer != null) {
+                mContainer.preOnConfigurationChanged();
+            }
+        }
+    }
+
+  /**
+   * @see DisplayContent#applyRotationLocked(int, int)
+   */
+    public void applyRotation(int oldRotation, int newRotation) {
+        synchronized (mGlobalLock) {
+            if (mContainer != null) {
+                mContainer.applyRotationLocked(oldRotation, newRotation);
+            }
+        }
     }
 
     public int getDisplayId() {
@@ -314,6 +339,17 @@
                 || transit == TRANSIT_TASK_TO_FRONT;
     }
 
+    /**
+     * Checks if system decorations should be shown on this display.
+     *
+     * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+     */
+    public boolean supportsSystemDecorations() {
+        synchronized (mGlobalLock) {
+            return mContainer.supportsSystemDecorations();
+        }
+    }
+
     @Override
     public String toString() {
         return "{DisplayWindowController displayId=" + mDisplayId + "}";
diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
similarity index 69%
rename from services/core/java/com/android/server/wm/DisplaySettings.java
rename to services/core/java/com/android/server/wm/DisplayWindowSettings.java
index 44956ab..f7dfd3f 100644
--- a/services/core/java/com/android/server/wm/DisplaySettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -16,6 +16,10 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY;
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
+
 import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO;
 import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -52,8 +56,8 @@
 /**
  * Current persistent settings about a display
  */
-class DisplaySettings {
-    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplaySettings" : TAG_WM;
+class DisplayWindowSettings {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayWindowSettings" : TAG_WM;
 
     private final WindowManagerService mService;
     private final AtomicFile mFile;
@@ -72,9 +76,13 @@
         private int mForcedHeight;
         private int mForcedDensity;
         private int mForcedScalingMode = FORCE_SCALING_MODE_AUTO;
+        private int mRemoveContentMode = REMOVE_CONTENT_MODE_UNDEFINED;
+        private boolean mShouldShowWithInsecureKeyguard = false;
+        private boolean mShouldShowSystemDecors = false;
+        private boolean mShouldShowIme = false;
 
-        private Entry(String _name) {
-            mName = _name;
+        private Entry(String name) {
+            mName = name;
         }
 
         /** @return {@code true} if all values are default. */
@@ -85,16 +93,20 @@
                     && mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
                     && mUserRotation == Surface.ROTATION_0
                     && mForcedWidth == 0 && mForcedHeight == 0 && mForcedDensity == 0
-                    && mForcedScalingMode == FORCE_SCALING_MODE_AUTO;
+                    && mForcedScalingMode == FORCE_SCALING_MODE_AUTO
+                    && mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED
+                    && !mShouldShowWithInsecureKeyguard
+                    && !mShouldShowSystemDecors
+                    && !mShouldShowIme;
         }
     }
 
-    DisplaySettings(WindowManagerService service) {
+    DisplayWindowSettings(WindowManagerService service) {
         this(service, new File(Environment.getDataDirectory(), "system"));
     }
 
     @VisibleForTesting
-    DisplaySettings(WindowManagerService service, File folder) {
+    DisplayWindowSettings(WindowManagerService service, File folder) {
         mService = service;
         mFile = new AtomicFile(new File(folder, "display_settings.xml"), "wm-displays");
         readSettings();
@@ -185,19 +197,124 @@
         }
         // No record is present so use default windowing mode policy.
         if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
-            if (displayId == Display.DEFAULT_DISPLAY) {
-                windowingMode = (mService.mIsPc && mService.mSupportsFreeformWindowManagement)
-                        ? WindowConfiguration.WINDOWING_MODE_FREEFORM
-                        : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-            } else {
-                windowingMode = mService.mSupportsFreeformWindowManagement
-                        ? WindowConfiguration.WINDOWING_MODE_FREEFORM
-                        : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-            }
+            final boolean forceDesktopMode = mService.mForceDesktopModeOnExternalDisplays
+                    && displayId != Display.DEFAULT_DISPLAY;
+            windowingMode = mService.mSupportsFreeformWindowManagement
+                    && (mService.mIsPc || forceDesktopMode)
+                    ? WindowConfiguration.WINDOWING_MODE_FREEFORM
+                    : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
         }
         return windowingMode;
     }
 
+    int getWindowingModeLocked(DisplayContent dc) {
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getEntry(displayInfo);
+        return getWindowingModeLocked(entry, dc.getDisplayId());
+    }
+
+    void setWindowingModeLocked(DisplayContent dc, int mode) {
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mWindowingMode = mode;
+        dc.setWindowingMode(mode);
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
+    int getRemoveContentModeLocked(DisplayContent dc) {
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getEntry(displayInfo);
+        if (entry == null || entry.mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED) {
+            if (dc.isPrivate()) {
+                // For private displays by default content is destroyed on removal.
+                return REMOVE_CONTENT_MODE_DESTROY;
+            }
+            // For other displays by default content is moved to primary on removal.
+            return REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
+        }
+        return entry.mRemoveContentMode;
+    }
+
+    void setRemoveContentModeLocked(DisplayContent dc, int mode) {
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mRemoveContentMode = mode;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
+    boolean shouldShowWithInsecureKeyguardLocked(DisplayContent dc) {
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getEntry(displayInfo);
+        if (entry == null) {
+            return false;
+        }
+        return entry.mShouldShowWithInsecureKeyguard;
+    }
+
+    void setShouldShowWithInsecureKeyguardLocked(DisplayContent dc, boolean shouldShow) {
+        if (!dc.isPrivate() && shouldShow) {
+            Slog.e(TAG, "Public display can't be allowed to show content when locked");
+            return;
+        }
+
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mShouldShowWithInsecureKeyguard = shouldShow;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
+    boolean shouldShowSystemDecorsLocked(DisplayContent dc) {
+        if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
+            // For default display should show system decors.
+            return true;
+        }
+
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getEntry(displayInfo);
+        if (entry == null) {
+            return false;
+        }
+        return entry.mShouldShowSystemDecors;
+    }
+
+    void setShouldShowSystemDecorsLocked(DisplayContent dc, boolean shouldShow) {
+        if (dc.getDisplayId() == Display.DEFAULT_DISPLAY && !shouldShow) {
+            Slog.e(TAG, "Default display should show system decors");
+            return;
+        }
+
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mShouldShowSystemDecors = shouldShow;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
+    boolean shouldShowImeLocked(DisplayContent dc) {
+        if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
+            // For default display should shows IME.
+            return true;
+        }
+
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getEntry(displayInfo);
+        if (entry == null) {
+            return false;
+        }
+        return entry.mShouldShowIme;
+    }
+
+    void setShouldShowImeLocked(DisplayContent dc, boolean shouldShow) {
+        if (dc.getDisplayId() == Display.DEFAULT_DISPLAY && !shouldShow) {
+            Slog.e(TAG, "Default display should show IME");
+            return;
+        }
+
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mShouldShowIme = shouldShow;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
     void applySettingsToDisplayLocked(DisplayContent dc) {
         final DisplayInfo displayInfo = dc.getDisplayInfo();
         final Entry entry = getEntry(displayInfo);
@@ -295,13 +412,26 @@
 
     private int getIntAttribute(XmlPullParser parser, String name, int defaultValue) {
         try {
-            String str = parser.getAttributeValue(null, name);
+            final String str = parser.getAttributeValue(null, name);
             return str != null ? Integer.parseInt(str) : defaultValue;
         } catch (NumberFormatException e) {
             return defaultValue;
         }
     }
 
+    private boolean getBooleanAttribute(XmlPullParser parser, String name) {
+        return getBooleanAttribute(parser, name, false /* defaultValue */);
+    }
+
+    private boolean getBooleanAttribute(XmlPullParser parser, String name, boolean defaultValue) {
+        try {
+            final String str = parser.getAttributeValue(null, name);
+            return str != null ? Boolean.parseBoolean(str) : defaultValue;
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
+
     private void readDisplay(XmlPullParser parser) throws NumberFormatException,
             XmlPullParserException, IOException {
         String name = parser.getAttributeValue(null, "name");
@@ -322,6 +452,12 @@
             entry.mForcedDensity = getIntAttribute(parser, "forcedDensity");
             entry.mForcedScalingMode = getIntAttribute(parser, "forcedScalingMode",
                     FORCE_SCALING_MODE_AUTO);
+            entry.mRemoveContentMode = getIntAttribute(parser, "removeContentMode",
+                    REMOVE_CONTENT_MODE_UNDEFINED);
+            entry.mShouldShowWithInsecureKeyguard = getBooleanAttribute(parser,
+                    "shouldShowWithInsecureKeyguard");
+            entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors");
+            entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme");
             mEntries.put(name, entry);
         }
         XmlUtils.skipCurrentTag(parser);
@@ -390,6 +526,21 @@
                     out.attribute(null, "forcedScalingMode",
                             Integer.toString(entry.mForcedScalingMode));
                 }
+                if (entry.mRemoveContentMode != REMOVE_CONTENT_MODE_UNDEFINED) {
+                    out.attribute(null, "removeContentMode",
+                            Integer.toString(entry.mRemoveContentMode));
+                }
+                if (entry.mShouldShowWithInsecureKeyguard) {
+                    out.attribute(null, "shouldShowWithInsecureKeyguard",
+                            Boolean.toString(entry.mShouldShowWithInsecureKeyguard));
+                }
+                if (entry.mShouldShowSystemDecors) {
+                    out.attribute(null, "shouldShowSystemDecors",
+                            Boolean.toString(entry.mShouldShowSystemDecors));
+                }
+                if (entry.mShouldShowIme) {
+                    out.attribute(null, "shouldShowIme", Boolean.toString(entry.mShouldShowIme));
+                }
                 out.endTag(null, "display");
             }
 
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 985ce06..6daf2f5 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -171,7 +171,7 @@
             final int orientation = mTmpRect2.width() <= mTmpRect2.height()
                     ? ORIENTATION_PORTRAIT
                     : ORIENTATION_LANDSCAPE;
-            final int dockSide = getDockSide(mTmpRect, mTmpRect2, orientation);
+            final int dockSide = getDockSide(mTmpRect, mTmpRect2, orientation, rotation);
             final int position = DockedDividerUtils.calculatePositionForBounds(mTmpRect, dockSide,
                     getContentWidth());
 
@@ -202,7 +202,7 @@
      * @param orientation the origination of device
      * @return current docked side
      */
-    int getDockSide(Rect bounds, Rect displayRect, int orientation) {
+    int getDockSide(Rect bounds, Rect displayRect, int orientation, int rotation) {
         if (orientation == Configuration.ORIENTATION_PORTRAIT) {
             // Portrait mode, docked either at the top or the bottom.
             final int diff = (displayRect.bottom - bounds.bottom) - (bounds.top - displayRect.top);
@@ -211,7 +211,8 @@
             } else if (diff < 0) {
                 return DOCKED_BOTTOM;
             }
-            return canPrimaryStackDockTo(DOCKED_TOP) ? DOCKED_TOP : DOCKED_BOTTOM;
+            return canPrimaryStackDockTo(DOCKED_TOP, displayRect, rotation)
+                    ? DOCKED_TOP : DOCKED_BOTTOM;
         } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
             // Landscape mode, docked either on the left or on the right.
             final int diff = (displayRect.right - bounds.right) - (bounds.left - displayRect.left);
@@ -220,7 +221,8 @@
             } else if (diff < 0) {
                 return DOCKED_RIGHT;
             }
-            return canPrimaryStackDockTo(DOCKED_LEFT) ? DOCKED_LEFT : DOCKED_RIGHT;
+            return canPrimaryStackDockTo(DOCKED_LEFT, displayRect, rotation)
+                    ? DOCKED_LEFT : DOCKED_RIGHT;
         }
         return DOCKED_INVALID;
     }
@@ -463,10 +465,9 @@
      * @param dockSide the side to see if it is valid
      * @return true if the side provided is valid
      */
-    boolean canPrimaryStackDockTo(int dockSide) {
-        final DisplayInfo di = mDisplayContent.getDisplayInfo();
-        return mService.mPolicy.isDockSideAllowed(dockSide, mOriginalDockedSide, di.logicalWidth,
-                di.logicalHeight, di.rotation);
+    boolean canPrimaryStackDockTo(int dockSide, Rect parentRect, int rotation) {
+        return mService.mPolicy.isDockSideAllowed(dockSide, mOriginalDockedSide,
+                parentRect.width(), parentRect.height(), rotation);
     }
 
     void notifyDockedStackExistsChanged(boolean exists) {
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index ce8c979..7ed078a 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -36,7 +36,7 @@
 import android.view.View;
 
 import com.android.internal.util.Preconditions;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputWindowHandle;
 import com.android.server.wm.WindowManagerInternal.IDragDropCallback;
 import java.util.concurrent.atomic.AtomicReference;
 
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 5483602..a379266 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -57,8 +57,8 @@
 
 import com.android.internal.view.IDragAndDropPermissions;
 import com.android.server.LocalServices;
-import com.android.server.input.InputApplicationHandle;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputApplicationHandle;
+import android.view.InputWindowHandle;
 
 import java.util.ArrayList;
 
@@ -223,7 +223,7 @@
             mDragApplicationHandle.dispatchingTimeoutNanos =
                     WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null, null,
+            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
                     display.getDisplayId());
             mDragWindowHandle.name = "drag";
             mDragWindowHandle.inputChannel = mServerChannel;
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 585a4f5..49bedc9 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -23,8 +23,8 @@
 import android.view.InputChannel;
 import android.view.WindowManager;
 
-import com.android.server.input.InputApplicationHandle;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputApplicationHandle;
+import android.view.InputWindowHandle;
 
 import java.io.PrintWriter;
 
@@ -63,7 +63,7 @@
         mApplicationHandle.dispatchingTimeoutNanos =
                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-        mWindowHandle = new InputWindowHandle(mApplicationHandle, null, null, displayId);
+        mWindowHandle = new InputWindowHandle(mApplicationHandle, null, displayId);
         mWindowHandle.name = name;
         mWindowHandle.inputChannel = mServerChannel;
         mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index f823caa..92ea1a9 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -8,16 +8,19 @@
 
 import android.app.ActivityManager;
 import android.os.Debug;
+import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
 import android.view.KeyEvent;
 import android.view.WindowManager;
 
-import com.android.server.input.InputApplicationHandle;
+import android.view.InputApplicationHandle;
 import com.android.server.input.InputManagerService;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputWindowHandle;
+import android.view.InputChannel;
 
 import java.io.PrintWriter;
+import java.util.HashMap;
 
 final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks {
     private final WindowManagerService mService;
@@ -48,13 +51,13 @@
      * Called by the InputManager.
      */
     @Override
-    public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
-        if (inputWindowHandle == null) {
+    public void notifyInputChannelBroken(IBinder token) {
+        if (token == null) {
             return;
         }
 
         synchronized (mService.mGlobalLock) {
-            WindowState windowState = (WindowState) inputWindowHandle.windowState;
+            WindowState windowState = mService.windowForClientLocked(null, token, false);
             if (windowState != null) {
                 Slog.i(TAG_WM, "WINDOW DIED " + windowState);
                 windowState.removeIfPossible();
@@ -70,13 +73,13 @@
      */
     @Override
     public long notifyANR(InputApplicationHandle inputApplicationHandle,
-            InputWindowHandle inputWindowHandle, String reason) {
+            IBinder token, String reason) {
         AppWindowToken appWindowToken = null;
         WindowState windowState = null;
         boolean aboveSystem = false;
         synchronized (mService.mGlobalLock) {
-            if (inputWindowHandle != null) {
-                windowState = (WindowState) inputWindowHandle.windowState;
+            if (token != null) {
+                windowState = mService.windowForClientLocked(null, token, false);
                 if (windowState != null) {
                     appWindowToken = windowState.mAppToken;
                 }
@@ -188,8 +191,8 @@
      */
     @Override
     public long interceptKeyBeforeDispatching(
-            InputWindowHandle focus, KeyEvent event, int policyFlags) {
-        WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
+            IBinder focus, KeyEvent event, int policyFlags) {
+        WindowState windowState = mService.windowForClientLocked(null, focus, false);
         return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
     }
 
@@ -199,8 +202,8 @@
      */
     @Override
     public KeyEvent dispatchUnhandledKey(
-            InputWindowHandle focus, KeyEvent event, int policyFlags) {
-        WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
+            IBinder focus, KeyEvent event, int policyFlags) {
+        WindowState windowState = mService.windowForClientLocked(null, focus, false);
         return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
     }
 
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 0e4ab53..61bc4e4 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -42,9 +42,12 @@
 import android.util.Slog;
 import android.view.InputChannel;
 import android.view.InputEventReceiver;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+import android.view.InputApplicationHandle;
+import android.view.InputWindowHandle;
 
-import com.android.server.input.InputApplicationHandle;
-import com.android.server.input.InputWindowHandle;
+import com.android.server.input.InputManagerService;
 import com.android.server.policy.WindowManagerPolicy;
 
 import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 3560635..c91af73 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -18,7 +18,6 @@
 
 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
@@ -30,13 +29,13 @@
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
 
-import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES;
 import static com.android.server.am.KeyguardControllerProto.KEYGUARD_SHOWING;
 import static com.android.server.am.KeyguardOccludedProto.DISPLAY_ID;
 import static com.android.server.am.KeyguardOccludedProto.KEYGUARD_OCCLUDED;
+import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -50,6 +49,7 @@
 import com.android.server.wm.ActivityTaskManagerInternal.SleepToken;
 
 import java.io.PrintWriter;
+import java.util.Arrays;
 
 /**
  * Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are
@@ -67,10 +67,9 @@
     private boolean mAodShowing;
     private boolean mKeyguardGoingAway;
     private boolean mDismissalRequested;
+    private int[] mSecondaryDisplayIdsShowing;
     private int mBeforeUnoccludeTransit;
     private int mVisibilityTransactionDepth;
-    // TODO(b/111955725): Support multiple external displays
-    private int mSecondaryDisplayShowing = INVALID_DISPLAY;
     private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
     private final ActivityTaskManagerService mService;
 
@@ -90,7 +89,9 @@
      */
     boolean isKeyguardOrAodShowing(int displayId) {
         return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
-                && !isDisplayOccluded(displayId);
+                && (displayId == DEFAULT_DISPLAY
+                        ? !isDisplayOccluded(DEFAULT_DISPLAY)
+                        : isShowingOnSecondaryDisplay(displayId));
     }
 
     /**
@@ -98,7 +99,10 @@
      *         display, false otherwise
      */
     boolean isKeyguardShowing(int displayId) {
-        return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId);
+        return mKeyguardShowing && !mKeyguardGoingAway
+                && (displayId == DEFAULT_DISPLAY
+                        ? !isDisplayOccluded(DEFAULT_DISPLAY)
+                        : isShowingOnSecondaryDisplay(displayId));
     }
 
     /**
@@ -120,16 +124,17 @@
      * Update the Keyguard showing state.
      */
     void setKeyguardShown(boolean keyguardShowing, boolean aodShowing,
-            int secondaryDisplayShowing) {
+            int[] secondaryDisplaysShowing) {
         boolean showingChanged = keyguardShowing != mKeyguardShowing || aodShowing != mAodShowing;
         // If keyguard is going away, but SystemUI aborted the transition, need to reset state.
         showingChanged |= mKeyguardGoingAway && keyguardShowing;
-        if (!showingChanged && secondaryDisplayShowing == mSecondaryDisplayShowing) {
+        if (!showingChanged && Arrays.equals(secondaryDisplaysShowing,
+                mSecondaryDisplayIdsShowing)) {
             return;
         }
         mKeyguardShowing = keyguardShowing;
         mAodShowing = aodShowing;
-        mSecondaryDisplayShowing = secondaryDisplayShowing;
+        mSecondaryDisplayIdsShowing = secondaryDisplaysShowing;
         mWindowManager.setAodShowing(aodShowing);
         if (showingChanged) {
             dismissDockedStackIfNeeded();
@@ -145,6 +150,14 @@
         updateKeyguardSleepToken();
     }
 
+    private boolean isShowingOnSecondaryDisplay(int displayId) {
+        if (mSecondaryDisplayIdsShowing == null) return false;
+        for (int showingId : mSecondaryDisplayIdsShowing) {
+            if (displayId == showingId) return true;
+        }
+        return false;
+    }
+
     /**
      * Called when Keyguard is going away.
      *
@@ -386,16 +399,18 @@
     }
 
     private KeyguardDisplayState getDisplay(int displayId) {
-        if (mDisplayStates.get(displayId) == null) {
-            mDisplayStates.append(displayId,
-                    new KeyguardDisplayState(mService, displayId));
+        KeyguardDisplayState state = mDisplayStates.get(displayId);
+        if (state == null) {
+            state = new KeyguardDisplayState(mService, displayId);
+            mDisplayStates.append(displayId, state);
         }
-        return mDisplayStates.get(displayId);
+        return state;
     }
 
     void onDisplayRemoved(int displayId) {
-        if (mDisplayStates.get(displayId) != null) {
-            mDisplayStates.get(displayId).onRemoved();
+        final KeyguardDisplayState state = mDisplayStates.get(displayId);
+        if (state != null) {
+            state.onRemoved();
             mDisplayStates.remove(displayId);
         }
     }
@@ -456,7 +471,8 @@
                 mOccluded |= controller.mWindowManager.isShowingDream();
             }
 
-            // TODO(b/113840485): Handle app transition for individual display.
+            // TODO(b/113840485): Handle app transition for individual display, and apply occluded
+            // state change to secondary displays.
             // For now, only default display can change occluded.
             if (lastOccluded != mOccluded && mDisplayId == DEFAULT_DISPLAY) {
                 controller.handleOccludedChanged();
diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java
index 252f47c..0947577 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsController.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsController.java
@@ -40,6 +40,7 @@
  */
 class LaunchParamsController {
     private final ActivityTaskManagerService mService;
+    private final LaunchParamsPersister mPersister;
     private final List<LaunchParamsModifier> mModifiers = new ArrayList<>();
 
     // Temporary {@link LaunchParams} for internal calculations. This is kept separate from
@@ -49,8 +50,9 @@
     private final LaunchParams mTmpCurrent = new LaunchParams();
     private final LaunchParams mTmpResult = new LaunchParams();
 
-    LaunchParamsController(ActivityTaskManagerService service) {
-       mService = service;
+    LaunchParamsController(ActivityTaskManagerService service, LaunchParamsPersister persister) {
+        mService = service;
+        mPersister = persister;
     }
 
     /**
@@ -75,6 +77,10 @@
                    ActivityRecord source, ActivityOptions options, LaunchParams result) {
         result.reset();
 
+        if (task != null || activity != null) {
+            mPersister.getLaunchParams(task, activity, result);
+        }
+
         // We start at the last registered {@link LaunchParamsModifier} as this represents
         // The modifier closest to the product level. Moving back through the list moves closer to
         // the platform logic.
@@ -139,12 +145,20 @@
                 task.getStack().setWindowingMode(mTmpParams.mWindowingMode);
             }
 
-            if (!mTmpParams.mBounds.isEmpty()) {
-                task.updateOverrideConfiguration(mTmpParams.mBounds);
-                return true;
-            } else {
+            if (mTmpParams.mBounds.isEmpty()) {
                 return false;
             }
+
+            if (task.getStack().inFreeformWindowingMode()) {
+                // Only set bounds if it's in freeform mode.
+                task.updateOverrideConfiguration(mTmpParams.mBounds);
+                return true;
+            }
+
+            // Setting last non-fullscreen bounds to the bounds so next time the task enters
+            // freeform windowing mode it can be in this bounds.
+            task.setLastNonFullscreenBounds(mTmpParams.mBounds);
+            return false;
         } finally {
             mService.mWindowManager.continueSurfaceLayout();
         }
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
new file mode 100644
index 0000000..72d5143
--- /dev/null
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) 2018 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.wm;
+
+import android.content.ComponentName;
+import android.content.pm.PackageList;
+import android.content.pm.PackageManagerInternal;
+import android.graphics.Rect;
+import android.os.Environment;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.Xml;
+import android.view.DisplayInfo;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.server.LocalServices;
+import com.android.server.wm.LaunchParamsController.LaunchParams;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.IntFunction;
+
+/**
+ * Persister that saves launch parameters in memory and in storage. It saves the last seen state of
+ * tasks key-ed on task's user ID and the activity used to launch the task ({@link
+ * TaskRecord#realActivity}) and that's used to determine the launch params when the activity is
+ * being launched again in {@link LaunchParamsController}.
+ *
+ * Need to hold {@link ActivityTaskManagerService#getGlobalLock()} to access this class.
+ */
+class LaunchParamsPersister {
+    private static final String TAG = "LaunchParamsPersister";
+    private static final String LAUNCH_PARAMS_DIRNAME = "launch_params";
+    private static final String LAUNCH_PARAMS_FILE_SUFFIX = ".xml";
+
+    // Chars below are used to escape the backslash in component name to underscore.
+    private static final char ORIGINAL_COMPONENT_SEPARATOR = '/';
+    private static final char ESCAPED_COMPONENT_SEPARATOR = '_';
+
+    private static final String TAG_LAUNCH_PARAMS = "launch_params";
+
+    private final PersisterQueue mPersisterQueue;
+    private final ActivityStackSupervisor mSupervisor;
+
+    /**
+     * A function that takes in user ID and returns a folder to store information of that user. Used
+     * to differentiate storage location in test environment and production environment.
+     */
+    private final IntFunction<File> mUserFolderGetter;
+
+    private PackageList mPackageList;
+
+    /**
+     * A dual layer map that first maps user ID to a secondary map, which maps component name (the
+     * launching activity of tasks) to {@link PersistableLaunchParams} that stores launch metadata
+     * that are stable across reboots.
+     */
+    private final SparseArray<ArrayMap<ComponentName, PersistableLaunchParams>> mMap =
+            new SparseArray<>();
+
+    LaunchParamsPersister(PersisterQueue persisterQueue, ActivityStackSupervisor supervisor) {
+        this(persisterQueue, supervisor, Environment::getDataSystemCeDirectory);
+    }
+
+    @VisibleForTesting
+    LaunchParamsPersister(PersisterQueue persisterQueue, ActivityStackSupervisor supervisor,
+            IntFunction<File> userFolderGetter) {
+        mPersisterQueue = persisterQueue;
+        mSupervisor = supervisor;
+        mUserFolderGetter = userFolderGetter;
+    }
+
+    void onSystemReady() {
+        PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+        mPackageList = pmi.getPackageList(new PackageListObserver());
+    }
+
+    void onUnlockUser(int userId) {
+        loadLaunchParams(userId);
+    }
+
+    void onCleanupUser(int userId) {
+        mMap.remove(userId);
+    }
+
+    private void loadLaunchParams(int userId) {
+        final List<File> filesToDelete = new ArrayList<>();
+        final File launchParamsFolder = getLaunchParamFolder(userId);
+        if (!launchParamsFolder.isDirectory()) {
+            Slog.i(TAG, "Didn't find launch param folder for user " + userId);
+            return;
+        }
+
+        final Set<String> packages = new ArraySet<>(mPackageList.getPackageNames());
+
+        final File[] paramsFiles = launchParamsFolder.listFiles();
+        final ArrayMap<ComponentName, PersistableLaunchParams> map =
+                new ArrayMap<>(paramsFiles.length);
+        mMap.put(userId, map);
+
+        for (File paramsFile : paramsFiles) {
+            if (!paramsFile.isFile()) {
+                Slog.w(TAG, paramsFile.getAbsolutePath() + " is not a file.");
+                continue;
+            }
+            if (!paramsFile.getName().endsWith(LAUNCH_PARAMS_FILE_SUFFIX)) {
+                Slog.w(TAG, "Unexpected params file name: " + paramsFile.getName());
+                filesToDelete.add(paramsFile);
+                continue;
+            }
+            final String paramsFileName = paramsFile.getName();
+            final String componentNameString = paramsFileName.substring(
+                    0 /* beginIndex */,
+                    paramsFileName.length() - LAUNCH_PARAMS_FILE_SUFFIX.length())
+                    .replace(ESCAPED_COMPONENT_SEPARATOR, ORIGINAL_COMPONENT_SEPARATOR);
+            final ComponentName name = ComponentName.unflattenFromString(
+                    componentNameString);
+            if (name == null) {
+                Slog.w(TAG, "Unexpected file name: " + paramsFileName);
+                filesToDelete.add(paramsFile);
+                continue;
+            }
+
+            if (!packages.contains(name.getPackageName())) {
+                // Rare case. PersisterQueue doesn't have a chance to remove files for removed
+                // packages last time.
+                filesToDelete.add(paramsFile);
+                continue;
+            }
+
+            BufferedReader reader = null;
+            try {
+                reader = new BufferedReader(new FileReader(paramsFile));
+                final PersistableLaunchParams params = new PersistableLaunchParams();
+                final XmlPullParser parser = Xml.newPullParser();
+                parser.setInput(reader);
+                int event;
+                while ((event = parser.next()) != XmlPullParser.END_DOCUMENT
+                        && event != XmlPullParser.END_TAG) {
+                    if (event != XmlPullParser.START_TAG) {
+                        continue;
+                    }
+
+                    final String tagName = parser.getName();
+                    if (!TAG_LAUNCH_PARAMS.equals(tagName)) {
+                        Slog.w(TAG, "Unexpected tag name: " + tagName);
+                        continue;
+                    }
+
+                    params.restoreFromXml(parser);
+                }
+
+                map.put(name, params);
+            } catch (Exception e) {
+                Slog.w(TAG, "Failed to restore launch params for " + name, e);
+                filesToDelete.add(paramsFile);
+            } finally {
+                IoUtils.closeQuietly(reader);
+            }
+        }
+
+        if (!filesToDelete.isEmpty()) {
+            mPersisterQueue.addItem(new CleanUpComponentQueueItem(filesToDelete), true);
+        }
+    }
+
+    void saveTask(TaskRecord task) {
+        final ComponentName name = task.realActivity;
+        final int userId = task.userId;
+        PersistableLaunchParams params;
+        ArrayMap<ComponentName, PersistableLaunchParams> map = mMap.get(userId);
+        if (map == null) {
+            map = new ArrayMap<>();
+            mMap.put(userId, map);
+        }
+
+        params = map.get(name);
+        if (params == null) {
+            params = new PersistableLaunchParams();
+            map.put(name, params);
+        }
+        final boolean changed = saveTaskToLaunchParam(task, params);
+
+        if (changed) {
+            mPersisterQueue.updateLastOrAddItem(
+                    new LaunchParamsWriteQueueItem(userId, name, params),
+                    /* flush */ false);
+        }
+    }
+
+    private boolean saveTaskToLaunchParam(TaskRecord task, PersistableLaunchParams params) {
+        final ActivityStack<?> stack = task.getStack();
+        final int displayId = stack.mDisplayId;
+        final ActivityDisplay display = mSupervisor.getActivityDisplay(displayId);
+        final DisplayInfo info = new DisplayInfo();
+        display.mDisplay.getDisplayInfo(info);
+
+        boolean changed = !Objects.equals(params.mDisplayUniqueId, info.uniqueId);
+        params.mDisplayUniqueId = info.uniqueId;
+
+        changed |= params.mWindowingMode != stack.getWindowingMode();
+        params.mWindowingMode = stack.getWindowingMode();
+
+        if (task.mLastNonFullscreenBounds != null) {
+            changed |= !Objects.equals(params.mBounds, task.mLastNonFullscreenBounds);
+            params.mBounds.set(task.mLastNonFullscreenBounds);
+        } else {
+            changed |= !params.mBounds.isEmpty();
+            params.mBounds.setEmpty();
+        }
+
+        return changed;
+    }
+
+    void getLaunchParams(TaskRecord task, ActivityRecord activity, LaunchParams outParams) {
+        final ComponentName name = task != null ? task.realActivity : activity.realActivity;
+        final int userId = task != null ? task.userId : activity.userId;
+
+        outParams.reset();
+        Map<ComponentName, PersistableLaunchParams> map = mMap.get(userId);
+        if (map == null) {
+            return;
+        }
+        final PersistableLaunchParams persistableParams = map.get(name);
+
+        if (persistableParams == null) {
+            return;
+        }
+
+        final ActivityDisplay display = mSupervisor.getActivityDisplay(
+                persistableParams.mDisplayUniqueId);
+        if (display != null) {
+            outParams.mPreferredDisplayId =  display.mDisplayId;
+        }
+        outParams.mWindowingMode = persistableParams.mWindowingMode;
+        outParams.mBounds.set(persistableParams.mBounds);
+    }
+
+    private void onPackageRemoved(String packageName) {
+        final List<File> fileToDelete = new ArrayList<>();
+        for (int i = 0; i < mMap.size(); ++i) {
+            int userId = mMap.keyAt(i);
+            final File launchParamsFolder = getLaunchParamFolder(userId);
+            ArrayMap<ComponentName, PersistableLaunchParams> map = mMap.valueAt(i);
+            for (int j = map.size() - 1; j >= 0; --j) {
+                final ComponentName name = map.keyAt(j);
+                if (name.getPackageName().equals(packageName)) {
+                    map.removeAt(j);
+                    fileToDelete.add(getParamFile(launchParamsFolder, name));
+                }
+            }
+        }
+
+        synchronized (mPersisterQueue) {
+            mPersisterQueue.removeItems(
+                    item -> item.mComponentName.getPackageName().equals(packageName),
+                    LaunchParamsWriteQueueItem.class);
+
+            mPersisterQueue.addItem(new CleanUpComponentQueueItem(fileToDelete), true);
+        }
+    }
+
+    private File getParamFile(File launchParamFolder, ComponentName name) {
+        final String componentNameString = name.flattenToShortString()
+                .replace(ORIGINAL_COMPONENT_SEPARATOR, ESCAPED_COMPONENT_SEPARATOR);
+        return new File(launchParamFolder, componentNameString + LAUNCH_PARAMS_FILE_SUFFIX);
+    }
+
+    private File getLaunchParamFolder(int userId) {
+        final File userFolder = mUserFolderGetter.apply(userId);
+        return new File(userFolder, LAUNCH_PARAMS_DIRNAME);
+    }
+
+    private class PackageListObserver implements PackageManagerInternal.PackageListObserver {
+        @Override
+        public void onPackageAdded(String packageName) { }
+
+        @Override
+        public void onPackageRemoved(String packageName) {
+            LaunchParamsPersister.this.onPackageRemoved(packageName);
+        }
+    }
+
+    private class LaunchParamsWriteQueueItem
+            implements PersisterQueue.WriteQueueItem<LaunchParamsWriteQueueItem> {
+        private final int mUserId;
+        private final ComponentName mComponentName;
+
+        private PersistableLaunchParams mLaunchParams;
+
+        private LaunchParamsWriteQueueItem(int userId, ComponentName componentName,
+                PersistableLaunchParams launchParams) {
+            mUserId = userId;
+            mComponentName = componentName;
+            mLaunchParams = launchParams;
+        }
+
+        private StringWriter saveParamsToXml() {
+            final StringWriter writer = new StringWriter();
+            final XmlSerializer serializer = new FastXmlSerializer();
+
+            try {
+                serializer.setOutput(writer);
+                serializer.startDocument(/* encoding */ null, /* standalone */ true);
+                serializer.startTag(null, TAG_LAUNCH_PARAMS);
+
+                mLaunchParams.saveToXml(serializer);
+
+                serializer.endTag(null, TAG_LAUNCH_PARAMS);
+                serializer.endDocument();
+                serializer.flush();
+
+                return writer;
+            } catch (IOException e) {
+                return null;
+            }
+        }
+
+        @Override
+        public void process() {
+            final StringWriter writer = saveParamsToXml();
+
+            final File launchParamFolder = getLaunchParamFolder(mUserId);
+            if (!launchParamFolder.isDirectory() && !launchParamFolder.mkdirs()) {
+                Slog.w(TAG, "Failed to create folder for " + mUserId);
+                return;
+            }
+
+            final File launchParamFile = getParamFile(launchParamFolder, mComponentName);
+            final AtomicFile atomicFile = new AtomicFile(launchParamFile);
+
+            FileOutputStream stream = null;
+            try {
+                stream = atomicFile.startWrite();
+                stream.write(writer.toString().getBytes());
+            } catch (Exception e) {
+                Slog.e(TAG, "Failed to write param file for " + mComponentName, e);
+                if (stream != null) {
+                    atomicFile.failWrite(stream);
+                }
+                return;
+            }
+            atomicFile.finishWrite(stream);
+        }
+
+        @Override
+        public boolean matches(LaunchParamsWriteQueueItem item) {
+            return mUserId == item.mUserId && mComponentName.equals(item.mComponentName);
+        }
+
+        @Override
+        public void updateFrom(LaunchParamsWriteQueueItem item) {
+            mLaunchParams = item.mLaunchParams;
+        }
+    }
+
+    private class CleanUpComponentQueueItem implements PersisterQueue.WriteQueueItem {
+        private final List<File> mComponentFiles;
+
+        private CleanUpComponentQueueItem(List<File> componentFiles) {
+            mComponentFiles = componentFiles;
+        }
+
+        @Override
+        public void process() {
+            for (File file : mComponentFiles) {
+                if (!file.delete()) {
+                    Slog.w(TAG, "Failed to delete " + file.getAbsolutePath());
+                }
+            }
+        }
+    }
+
+    private class PersistableLaunchParams {
+        private static final String ATTR_WINDOWING_MODE = "windowing_mode";
+        private static final String ATTR_DISPLAY_UNIQUE_ID = "display_unique_id";
+        private static final String ATTR_BOUNDS = "bounds";
+
+        /** The bounds within the parent container. */
+        final Rect mBounds = new Rect();
+
+        /** The unique id of the display the {@link TaskRecord} would prefer to be on. */
+        String mDisplayUniqueId;
+
+        /** The windowing mode to be in. */
+        int mWindowingMode;
+
+        void saveToXml(XmlSerializer serializer) throws IOException {
+            serializer.attribute(null, ATTR_DISPLAY_UNIQUE_ID, mDisplayUniqueId);
+            serializer.attribute(null, ATTR_WINDOWING_MODE,
+                    Integer.toString(mWindowingMode));
+            serializer.attribute(null, ATTR_BOUNDS, mBounds.flattenToString());
+        }
+
+        void restoreFromXml(XmlPullParser parser) {
+            for (int i = 0; i < parser.getAttributeCount(); ++i) {
+                final String attrValue = parser.getAttributeValue(i);
+                switch (parser.getAttributeName(i)) {
+                    case ATTR_DISPLAY_UNIQUE_ID:
+                        mDisplayUniqueId = attrValue;
+                        break;
+                    case ATTR_WINDOWING_MODE:
+                        mWindowingMode = Integer.parseInt(attrValue);
+                        break;
+                    case ATTR_BOUNDS: {
+                        final Rect bounds = Rect.unflattenFromString(attrValue);
+                        if (bounds != null) {
+                            mBounds.set(bounds);
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder builder = new StringBuilder("PersistableLaunchParams{");
+            builder.append("windowingMode=" + mWindowingMode);
+            builder.append(" displayUniqueId=" + mDisplayUniqueId);
+            builder.append(" bounds=" + mBounds);
+            builder.append(" }");
+            return builder.toString();
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 4eb021c..b49d304 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -187,6 +187,7 @@
                 }
                 t.setPosition(mSurface, mSurfaceFrame.left, mSurfaceFrame.top);
                 t.setSize(mSurface, mSurfaceFrame.width(), mSurfaceFrame.height());
+                t.setWindowCrop(mSurface, mSurfaceFrame.width(), mSurfaceFrame.height());
                 t.show(mSurface);
             } else if (mSurface != null) {
                 t.hide(mSurface);
diff --git a/services/core/java/com/android/server/wm/PersisterQueue.java b/services/core/java/com/android/server/wm/PersisterQueue.java
index 1cfc7ac..a17ee65 100644
--- a/services/core/java/com/android/server/wm/PersisterQueue.java
+++ b/services/core/java/com/android/server/wm/PersisterQueue.java
@@ -130,6 +130,30 @@
         return null;
     }
 
+    /**
+     *
+     * @param item
+     * @param flush
+     * @param <T>
+     */
+    synchronized <T extends WriteQueueItem> void updateLastOrAddItem(T item, boolean flush) {
+        final T itemToUpdate = findLastItem(item::matches, (Class<T>) item.getClass());
+        if (itemToUpdate == null) {
+            addItem(item, flush);
+        } else {
+            itemToUpdate.updateFrom(item);
+        }
+
+        yieldIfQueueTooDeep();
+    }
+
+    /**
+     * Removes all items with which given predicate returns {@code true}.
+     *
+     * @param predicate the predicate
+     * @param clazz
+     * @param <T>
+     */
     synchronized <T extends WriteQueueItem> void removeItems(Predicate<T> predicate,
             Class<T> clazz) {
         for (int i = mWriteQueue.size() - 1; i >= 0; --i) {
@@ -230,8 +254,14 @@
         item.process();
     }
 
-    interface WriteQueueItem {
+    interface WriteQueueItem<T extends WriteQueueItem<T>> {
         void process();
+
+        default void updateFrom(T item) {}
+
+        default boolean matches(T item) {
+            return false;
+        }
     }
 
     interface Listener {
diff --git a/services/core/java/com/android/server/wm/PinnedActivityStack.java b/services/core/java/com/android/server/wm/PinnedActivityStack.java
index af18077..3ef42e7 100644
--- a/services/core/java/com/android/server/wm/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/wm/PinnedActivityStack.java
@@ -97,7 +97,10 @@
         // It is guaranteed that the activities requiring the update will be in the pinned stack at
         // this point (either reparented before the animation into PiP, or before reparenting after
         // the animation out of PiP)
-        synchronized (mService) {
+        synchronized (mService.mGlobalLock) {
+            if (!isAttached()) {
+                return;
+            }
             ArrayList<TaskRecord> tasks = getAllTasks();
             for (int i = 0; i < tasks.size(); i++ ) {
                 mStackSupervisor.updatePictureInPictureMode(tasks.get(i), targetStackBounds,
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 405aaab..d21f67d 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -314,8 +314,8 @@
      * onTaskStackBoundsChanged() to be called.  But we still should update our known display info
      * with the new state so that we can update SystemUI.
      */
-    synchronized void onDisplayInfoChanged() {
-        mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
+    synchronized void onDisplayInfoChanged(DisplayInfo displayInfo) {
+        mDisplayInfo.copyFrom(displayInfo);
         notifyMovementBoundsChanged(false /* fromImeAdjustment */, false /* fromShelfAdjustment */);
     }
 
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index c995d3f..15478b4 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -19,6 +19,7 @@
 import static android.app.ActivityManager.FLAG_AND_UNLOCKED;
 import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
 import static android.app.ActivityManager.RECENT_WITH_EXCLUDED;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -33,6 +34,7 @@
 import static android.os.Process.SYSTEM_UID;
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS_TRIM_TASKS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
@@ -40,8 +42,6 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
@@ -196,7 +196,8 @@
         final Resources res = service.mContext.getResources();
         mService = service;
         mSupervisor = mService.mStackSupervisor;
-        mTaskPersister = new TaskPersister(systemDir, stackSupervisor, service, this);
+        mTaskPersister = new TaskPersister(systemDir, stackSupervisor, service, this,
+                stackSupervisor.mPersisterQueue);
         mGlobalMaxNumTasks = ActivityTaskManager.getMaxRecentTasksStatic();
         mHasVisibleRecentTasks = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
         loadParametersFromResources(res);
@@ -432,7 +433,6 @@
     void onSystemReadyLocked() {
         loadRecentsComponent(mService.mContext.getResources());
         mTasks.clear();
-        mTaskPersister.onSystemReady();
     }
 
     Bitmap getTaskDescriptionIcon(String path) {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 7a1ebf2..067b01a 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -42,7 +42,6 @@
 import android.util.Slog;
 import android.view.IRecentsAnimationRunner;
 
-import com.android.server.wm.AssistDataReceiverProxy;
 import com.android.server.am.AssistDataRequester;
 import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
 
@@ -122,9 +121,9 @@
                     targetActivity);
         }
 
-        mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
+        mStackSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
 
-        mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, true);
+        mService.mH.post(() -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, true));
 
         mWindowManager.deferSurfaceLayout();
         try {
@@ -234,7 +233,8 @@
                 mStackSupervisor.sendPowerHintForLaunchEndIfNeeded();
             }
 
-            mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, false);
+            mService.mH.post(
+                    () -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, false));
 
             mWindowManager.inSurfaceTransaction(() -> {
                 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER,
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index c4fbee9..6627c2d 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -43,6 +43,7 @@
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 import android.util.proto.ProtoOutputStream;
+import android.view.InputWindowHandle;
 import android.view.IRecentsAnimationController;
 import android.view.IRecentsAnimationRunner;
 import android.view.RemoteAnimationTarget;
@@ -50,7 +51,6 @@
 import android.view.SurfaceControl.Transaction;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
-import com.android.server.input.InputWindowHandle;
 import com.android.server.inputmethod.InputMethodManagerInternal;
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
 import com.android.server.wm.utils.InsetUtils;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 67fe5c4..1baca32 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -54,6 +54,7 @@
 import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
 
 import android.annotation.CallSuper;
+import android.annotation.NonNull;
 import android.content.res.Configuration;
 import android.hardware.power.V1_0.PowerHint;
 import android.os.Binder;
@@ -75,12 +76,10 @@
 import android.view.SurfaceControl;
 import android.view.WindowManager;
 
-import com.android.internal.util.ArrayUtils;
 import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.List;
 import java.util.function.Consumer;
 
 /** Root {@link WindowContainer} for the device. */
@@ -115,9 +114,6 @@
     boolean mOrientationChangeComplete = true;
     boolean mWallpaperActionPending = false;
 
-    private final ArrayList<TaskStack> mTmpStackList = new ArrayList();
-    private final ArrayList<Integer> mTmpStackIds = new ArrayList<>();
-
     final WallpaperController mWallpaperController;
 
     private final Handler mHandler;
@@ -126,7 +122,7 @@
 
     // The ID of the display which is responsible for receiving display-unspecified key and pointer
     // events.
-    private int mTopFocusedDisplayId = INVALID_DISPLAY;
+    int mTopFocusedDisplayId = INVALID_DISPLAY;
 
     // Only a seperate transaction until we seperate the apply surface changes
     // transaction from the global transaction.
@@ -160,7 +156,8 @@
     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
         boolean changed = false;
         int topFocusedDisplayId = INVALID_DISPLAY;
-        for (int i = mChildren.size() - 1; i >= 0; i--) {
+
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
             final DisplayContent dc = mChildren.get(i);
             changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows,
                     topFocusedDisplayId != INVALID_DISPLAY /* focusFound */);
@@ -171,12 +168,35 @@
         if (topFocusedDisplayId == INVALID_DISPLAY) {
             topFocusedDisplayId = DEFAULT_DISPLAY;
         }
+        // TODO(b/118865114): Review if need callback top focus display change to view component.
+        // (i.e. Activity or View)
+        // Currently we only tracked topFocusedDisplayChanged for notifying InputMethodManager via
+        // ViewRootImpl.windowFocusChanged to refocus IME window when top display focus changed
+        // but window focus remain the same case.
+        // It may need to review if any use case that need to add new callback for reporting
+        // this change.
+        final boolean topFocusedDisplayChanged =
+                mTopFocusedDisplayId != topFocusedDisplayId && mode == UPDATE_FOCUS_NORMAL;
         if (mTopFocusedDisplayId != topFocusedDisplayId) {
             mTopFocusedDisplayId = topFocusedDisplayId;
-            mService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
+            mService.mInputManager.setFocusedDisplay(mTopFocusedDisplayId);
             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "New topFocusedDisplayId="
-                    + topFocusedDisplayId);
+                    + mTopFocusedDisplayId);
         }
+
+        // Report window focus or top display focus changed through REPORT_FOCUS_CHANGE.
+        forAllDisplays((dc) -> {
+            final boolean windowFocusChanged =
+                    dc.mCurrentFocus != null && dc.mCurrentFocus != dc.mLastFocus;
+            final boolean isTopFocusedDisplay =
+                    topFocusedDisplayChanged && dc.getDisplayId() == mTopFocusedDisplayId;
+            if (windowFocusChanged || isTopFocusedDisplay) {
+                final Message msg = mService.mH.obtainMessage(
+                        WindowManagerService.H.REPORT_FOCUS_CHANGE, dc);
+                msg.arg1 = topFocusedDisplayChanged ? 1 : 0;
+                mService.mH.sendMessage(msg);
+            }
+        });
         final WindowState topFocusedWindow = getTopFocusedDisplayContent().mCurrentFocus;
         mService.mInputManager.setFocusedWindow(
                 topFocusedWindow != null ? topFocusedWindow.mInputWindowHandle : null);
@@ -221,7 +241,7 @@
 
         if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
 
-        mService.mDisplaySettings.applySettingsToDisplayLocked(dc);
+        mService.mDisplayWindowSettings.applySettingsToDisplayLocked(dc);
 
         if (mService.mDisplayManagerInternal != null) {
             mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
@@ -313,57 +333,33 @@
     }
 
     /**
-     * Set new display override config and return array of ids of stacks that were changed during
-     * update. If called for the default display, global configuration will also be updated. Stacks
-     * that are marked for deferred removal are excluded from the returned array.
+     * Set new display override config. If called for the default display, global configuration
+     * will also be updated.
      */
-    int[] setDisplayOverrideConfigurationIfNeeded(Configuration newConfiguration, int displayId) {
-        final DisplayContent displayContent = getDisplayContent(displayId);
-        if (displayContent == null) {
-            throw new IllegalArgumentException("Display not found for id: " + displayId);
-        }
+    void setDisplayOverrideConfigurationIfNeeded(Configuration newConfiguration,
+            @NonNull DisplayContent displayContent) {
 
         final Configuration currentConfig = displayContent.getOverrideConfiguration();
         final boolean configChanged = currentConfig.diff(newConfiguration) != 0;
         if (!configChanged) {
-            return null;
+            return;
         }
 
         displayContent.onOverrideConfigurationChanged(newConfiguration);
 
-        mTmpStackList.clear();
-        if (displayId == DEFAULT_DISPLAY) {
+        if (displayContent.getDisplayId() == DEFAULT_DISPLAY) {
             // Override configuration of the default display duplicates global config. In this case
             // we also want to update the global config.
-            setGlobalConfigurationIfNeeded(newConfiguration, mTmpStackList);
-        } else {
-            updateStackBoundsAfterConfigChange(displayId, mTmpStackList);
+            setGlobalConfigurationIfNeeded(newConfiguration);
         }
-
-        mTmpStackIds.clear();
-        final int stackCount = mTmpStackList.size();
-
-        for (int i = 0; i < stackCount; ++i) {
-            final TaskStack stack = mTmpStackList.get(i);
-
-            // We only include stacks that are not marked for removal as they do not exist outside
-            // of WindowManager at this point.
-            if (!stack.mDeferRemoval) {
-                mTmpStackIds.add(stack.mStackId);
-            }
-        }
-
-        return mTmpStackIds.isEmpty() ? null : ArrayUtils.convertToIntArray(mTmpStackIds);
     }
 
-    private void setGlobalConfigurationIfNeeded(Configuration newConfiguration,
-            List<TaskStack> changedStacks) {
+    private void setGlobalConfigurationIfNeeded(Configuration newConfiguration) {
         final boolean configChanged = getConfiguration().diff(newConfiguration) != 0;
         if (!configChanged) {
             return;
         }
         onConfigurationChanged(newConfiguration);
-        updateStackBoundsAfterConfigChange(changedStacks);
     }
 
     @Override
@@ -374,24 +370,6 @@
         forAllDisplays(mDisplayContentConfigChangesConsumer);
     }
 
-    /**
-     * Callback used to trigger bounds update after configuration change and get ids of stacks whose
-     * bounds were updated.
-     */
-    private void updateStackBoundsAfterConfigChange(List<TaskStack> changedStacks) {
-        final int numDisplays = mChildren.size();
-        for (int i = 0; i < numDisplays; ++i) {
-            final DisplayContent dc = mChildren.get(i);
-            dc.updateStackBoundsAfterConfigChange(changedStacks);
-        }
-    }
-
-    /** Same as {@link #updateStackBoundsAfterConfigChange()} but only for a specific display. */
-    private void updateStackBoundsAfterConfigChange(int displayId, List<TaskStack> changedStacks) {
-        final DisplayContent dc = getDisplayContent(displayId);
-        dc.updateStackBoundsAfterConfigChange(changedStacks);
-    }
-
     private void prepareFreezingTaskBounds() {
         for (int i = mChildren.size() - 1; i >= 0; i--) {
             mChildren.get(i).prepareFreezingTaskBounds();
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index c920b9e..d8e1ebf 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -245,12 +245,6 @@
         }
     }
 
-    public void getBoundsForNewConfiguration(Rect outBounds) {
-        synchronized (mGlobalLock) {
-            mContainer.getBoundsForNewConfiguration(outBounds);
-        }
-    }
-
     /**
      * Adjusts the screen size in dp's for the {@param config} for the given params. The provided
      * params represent the desired state of a configuration change. Since this utility is used
@@ -378,6 +372,14 @@
         mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
     }
 
+    /** @see TaskStack.updateBoundsForConfigChange(Configuration, Configuration, Rect) */
+    public boolean updateBoundsForConfigChange(
+            Configuration parentConfig, Configuration prevConfig, Rect outBounds) {
+        synchronized (mGlobalLock) {
+            return mContainer.updateBoundsForConfigChange(parentConfig, prevConfig, outBounds);
+        }
+    }
+
     @Override
     public String toString() {
         return "{StackWindowController stackId=" + mStackId + "}";
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 3ea615a..66063c40 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -16,12 +16,12 @@
 
 package com.android.server.wm;
 
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 import static com.android.server.wm.SurfaceAnimatorProto.ANIMATION_ADAPTER;
 import static com.android.server.wm.SurfaceAnimatorProto.ANIMATION_START_DELAYED;
 import static com.android.server.wm.SurfaceAnimatorProto.LEASH;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -305,6 +305,7 @@
                 .setName(surface + " - animation-leash")
                 .setSize(width, height);
         final SurfaceControl leash = builder.build();
+        t.setWindowCrop(surface, width, height);
         if (!hidden) {
             t.show(leash);
         }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 3f394a2..c9800f8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -237,7 +237,7 @@
         super.onParentSet();
 
         // Update task bounds if needed.
-        updateDisplayInfo(getDisplayContent());
+        adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
 
         if (getWindowConfiguration().windowsAreScaleable()) {
             // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
@@ -290,12 +290,7 @@
         if (displayContent != null) {
             rotation = displayContent.getDisplayInfo().rotation;
         } else if (bounds == null) {
-            // Can't set to fullscreen if we don't have a display to get bounds from...
-            return BOUNDS_CHANGE_NONE;
-        }
-
-        if (equivalentOverrideBounds(bounds)) {
-            return BOUNDS_CHANGE_NONE;
+            return super.setBounds(bounds);
         }
 
         final int boundsChange = super.setBounds(bounds);
@@ -308,6 +303,7 @@
     @Override
     void onDisplayChanged(DisplayContent dc) {
         updateSurfaceSize(dc);
+        adjustBoundsForDisplayChangeIfNeeded(dc);
         super.onDisplayChanged(dc);
     }
 
@@ -506,7 +502,7 @@
         return mDragResizeMode;
     }
 
-    void updateDisplayInfo(final DisplayContent displayContent) {
+    private void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
         if (displayContent == null) {
             return;
         }
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index b7804e8..117984a 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -48,6 +48,7 @@
 import android.os.Build;
 import android.util.Slog;
 import android.view.Gravity;
+import android.view.View;
 
 import com.android.server.wm.LaunchParamsController.LaunchParams;
 import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
@@ -198,13 +199,13 @@
                     || displayId == currentParams.mPreferredDisplayId)) {
             if (currentParams.hasWindowingMode()) {
                 launchMode = currentParams.mWindowingMode;
-                fullyResolvedCurrentParam = (launchMode != WINDOWING_MODE_FREEFORM);
+                fullyResolvedCurrentParam = launchMode != WINDOWING_MODE_FREEFORM;
                 if (DEBUG) {
                     appendLog("inherit-" + WindowConfiguration.windowingModeToString(launchMode));
                 }
             }
 
-            if (!currentParams.mBounds.isEmpty()) {
+            if (launchMode == WINDOWING_MODE_FREEFORM && !currentParams.mBounds.isEmpty()) {
                 outParams.mBounds.set(currentParams.mBounds);
                 fullyResolvedCurrentParam = true;
                 if (DEBUG) appendLog("inherit-bounds=" + outParams.mBounds);
@@ -250,11 +251,20 @@
         // for all other windowing modes that's not freeform mode. One can read comments in
         // relevant methods to further understand this step.
         //
-        // We skip making adjustments if the params are fully resolved from previous results and
-        // trust that they are valid.
-        if (!fullyResolvedCurrentParam) {
-            final int resolvedMode = (launchMode != WINDOWING_MODE_UNDEFINED) ? launchMode
-                    : display.getWindowingMode();
+        // We skip making adjustments if the params are fully resolved from previous results.
+        final int resolvedMode = (launchMode != WINDOWING_MODE_UNDEFINED) ? launchMode
+                : display.getWindowingMode();
+        if (fullyResolvedCurrentParam) {
+            if (resolvedMode == WINDOWING_MODE_FREEFORM) {
+                // Make sure bounds are in the display if it's possibly in a different display.
+                if (currentParams.mPreferredDisplayId != displayId) {
+                    adjustBoundsToFitInDisplay(display, outParams.mBounds);
+                }
+                // Even though we want to keep original bounds, we still don't want it to stomp on
+                // an existing task.
+                adjustBoundsToAvoidConflict(display, outParams.mBounds);
+            }
+        } else {
             if (source != null && source.inFreeformWindowingMode()
                     && resolvedMode == WINDOWING_MODE_FREEFORM
                     && outParams.mBounds.isEmpty()
@@ -291,13 +301,12 @@
         }
 
         if (displayId != INVALID_DISPLAY && mSupervisor.getActivityDisplay(displayId) == null) {
-            displayId = INVALID_DISPLAY;
+            displayId = currentParams.mPreferredDisplayId;
         }
         displayId = (displayId == INVALID_DISPLAY) ? currentParams.mPreferredDisplayId : displayId;
 
-        displayId = (displayId == INVALID_DISPLAY) ? DEFAULT_DISPLAY : displayId;
-
-        return displayId;
+        return (displayId != INVALID_DISPLAY && mSupervisor.getActivityDisplay(displayId) != null)
+                ? displayId : DEFAULT_DISPLAY;
     }
 
     private boolean canApplyFreeformWindowPolicy(@NonNull ActivityDisplay display, int launchMode) {
@@ -596,7 +605,12 @@
         if (displayBounds.width() < inOutBounds.width()
                 || displayBounds.height() < inOutBounds.height()) {
             // There is no way for us to fit the bounds in the display without changing width
-            // or height. Don't even try it.
+            // or height. Just move the start to align with the display.
+            final int layoutDirection = mSupervisor.getConfiguration().getLayoutDirection();
+            final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL
+                    ? displayBounds.width() - inOutBounds.width()
+                    : 0;
+            inOutBounds.offsetTo(left, 0 /* newTop */);
             return;
         }
 
diff --git a/services/core/java/com/android/server/wm/TaskPersister.java b/services/core/java/com/android/server/wm/TaskPersister.java
index 9705d42..8120dec 100644
--- a/services/core/java/com/android/server/wm/TaskPersister.java
+++ b/services/core/java/com/android/server/wm/TaskPersister.java
@@ -83,7 +83,8 @@
     private final ArraySet<Integer> mTmpTaskIds = new ArraySet<>();
 
     TaskPersister(File systemDir, ActivityStackSupervisor stackSupervisor,
-            ActivityTaskManagerService service, RecentTasks recentTasks) {
+            ActivityTaskManagerService service, RecentTasks recentTasks,
+            PersisterQueue persisterQueue) {
 
         final File legacyImagesDir = new File(systemDir, IMAGES_DIRNAME);
         if (legacyImagesDir.exists()) {
@@ -103,7 +104,7 @@
         mStackSupervisor = stackSupervisor;
         mService = service;
         mRecentTasks = recentTasks;
-        mPersisterQueue = new PersisterQueue();
+        mPersisterQueue = persisterQueue;
         mPersisterQueue.addListener(this);
     }
 
@@ -117,10 +118,6 @@
         mPersisterQueue.addListener(this);
     }
 
-    void onSystemReady() {
-        mPersisterQueue.startPersisting();
-    }
-
     private void removeThumbnails(TaskRecord task) {
         mPersisterQueue.removeItems(
                 item -> {
@@ -219,21 +216,12 @@
     }
 
     void saveImage(Bitmap image, String filePath) {
-        synchronized (mPersisterQueue) {
-            final ImageWriteQueueItem item = mPersisterQueue.findLastItem(
-                    queueItem -> queueItem.mFilePath.equals(filePath), ImageWriteQueueItem.class);
-            if (item != null) {
-                // replace the Bitmap with the new one.
-                item.mImage = image;
-            } else {
-                mPersisterQueue.addItem(new ImageWriteQueueItem(filePath, image),
-                        /* flush */ false);
-            }
-            if (DEBUG) Slog.d(TAG, "saveImage: filePath=" + filePath + " now=" +
-                    SystemClock.uptimeMillis() + " Callers=" + Debug.getCallers(4));
+        mPersisterQueue.updateLastOrAddItem(new ImageWriteQueueItem(filePath, image),
+                /* flush */ false);
+        if (DEBUG) {
+            Slog.d(TAG, "saveImage: filePath=" + filePath + " now="
+                    + SystemClock.uptimeMillis() + " Callers=" + Debug.getCallers(4));
         }
-
-        mPersisterQueue.yieldIfQueueTooDeep();
     }
 
     Bitmap getTaskDescriptionIcon(String filePath) {
@@ -603,7 +591,8 @@
         }
     }
 
-    private static class ImageWriteQueueItem implements PersisterQueue.WriteQueueItem {
+    private static class ImageWriteQueueItem implements
+            PersisterQueue.WriteQueueItem<ImageWriteQueueItem> {
         final String mFilePath;
         Bitmap mImage;
 
@@ -633,6 +622,16 @@
         }
 
         @Override
+        public boolean matches(ImageWriteQueueItem item) {
+            return mFilePath.equals(item.mFilePath);
+        }
+
+        @Override
+        public void updateFrom(ImageWriteQueueItem item) {
+            mImage = item.mImage;
+        }
+
+        @Override
         public String toString() {
             return "ImageWriteQueueItem{path=" + mFilePath
                     + ", image=(" + mImage.getWidth() + "x" + mImage.getHeight() + ")}";
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 66ebc9b..7182ad6 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -49,8 +49,9 @@
 import android.view.WindowManager;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.input.InputApplicationHandle;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputApplicationHandle;
+import android.view.InputWindowHandle;
+import com.android.server.wm.WindowManagerService.H;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -265,7 +266,7 @@
         mDragApplicationHandle.dispatchingTimeoutNanos =
                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-        mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null, null,
+        mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
                 display.getDisplayId());
         mDragWindowHandle.name = TAG;
         mDragWindowHandle.inputChannel = mServerChannel;
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index f2d3dca..51567a0 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -29,7 +29,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.input.InputManagerService;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputWindowHandle;
 
 /**
  * Controller for task positioning by drag.
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index d697f28..bd6689f 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -46,22 +46,7 @@
 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
-import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
-import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
-import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
+
 import static com.android.server.am.TaskRecordProto.ACTIVITIES;
 import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
 import static com.android.server.am.TaskRecordProto.BOUNDS;
@@ -75,6 +60,23 @@
 import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY;
 import static com.android.server.am.TaskRecordProto.RESIZE_MODE;
 import static com.android.server.am.TaskRecordProto.STACK_ID;
+import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
+import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
+import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
+import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
+import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
+import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
 import static java.lang.Integer.MAX_VALUE;
 
 import android.annotation.IntDef;
@@ -87,6 +89,7 @@
 import android.app.ActivityTaskManager;
 import android.app.AppGlobals;
 import android.app.TaskInfo;
+import android.app.WindowConfiguration;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -550,6 +553,8 @@
             }
             mWindowContainerController.resize(kept, forced);
 
+            saveLaunchingStateIfNeeded();
+
             Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
             return kept;
         } finally {
@@ -1820,6 +1825,29 @@
             mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
         }
         // TODO: Should also take care of Pip mode changes here.
+
+        saveLaunchingStateIfNeeded();
+    }
+
+    /**
+     * Saves launching state if necessary so that we can launch the activity to its latest state.
+     * It only saves state if this task has been shown to user and it's in fullscreen or freeform
+     * mode.
+     */
+    void saveLaunchingStateIfNeeded() {
+        if (!hasBeenVisible) {
+            // Not ever visible to user.
+            return;
+        }
+
+        final int windowingMode = getWindowingMode();
+        if (windowingMode != WindowConfiguration.WINDOWING_MODE_FULLSCREEN
+                && windowingMode != WindowConfiguration.WINDOWING_MODE_FREEFORM) {
+            return;
+        }
+
+        // Saves the new state so that we can launch the activity at the same location.
+        mService.mStackSupervisor.mLaunchParamsPersister.saveTask(this);
     }
 
     /** Clears passed config and fills it with new override values. */
@@ -1960,12 +1988,12 @@
         info.stackId = getStackId();
         info.taskId = taskId;
         info.isRunning = getTopActivity() != null;
-        info.baseIntent = getBaseIntent();
+        info.baseIntent = new Intent(getBaseIntent());
         info.baseActivity = reuseActivitiesReport.base != null
                 ? reuseActivitiesReport.base.intent.getComponent()
                 : null;
         info.topActivity = reuseActivitiesReport.top != null
-                ? reuseActivitiesReport.top.intent.getComponent()
+                ? reuseActivitiesReport.top.realActivity
                 : null;
         info.origActivity = origActivity;
         info.realActivity = realActivity;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index b84d20d..7ab4d08 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -290,9 +290,10 @@
             return null;
         }
         final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE;
-        return new TaskSnapshot(buffer, appWindowToken.getConfiguration().orientation,
-                getInsets(mainWindow), isLowRamDevice /* reduced */, scaleFraction /* scale */,
-                true /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
+        return new TaskSnapshot(appWindowToken.mActivityComponent, buffer,
+                appWindowToken.getConfiguration().orientation, getInsets(mainWindow),
+                isLowRamDevice /* reduced */, scaleFraction /* scale */, true /* isRealSnapshot */,
+                task.getWindowingMode(), getSystemUiVisibility(task),
                 !appWindowToken.fillsParent() || isWindowTranslucent);
     }
 
@@ -382,7 +383,7 @@
         }
         // Note, the app theme snapshot is never translucent because we enforce a non-translucent
         // color above
-        return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
+        return new TaskSnapshot(topChild.mActivityComponent, hwBitmap.createGraphicBufferHandle(),
                 topChild.getConfiguration().orientation, mainWindow.getStableInsets(),
                 ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */,
                 false /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
index 1410c21..0e1570b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
@@ -21,6 +21,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.app.ActivityManager.TaskSnapshot;
+import android.content.ComponentName;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.BitmapFactory;
@@ -87,7 +88,9 @@
                         + bitmapFile.getPath());
                 return null;
             }
-            return new TaskSnapshot(buffer, proto.orientation,
+            ComponentName topActivityComponent = ComponentName.unflattenFromString(
+                    proto.topActivityComponent);
+            return new TaskSnapshot(topActivityComponent, buffer, proto.orientation,
                     new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom),
                     reducedResolution, reducedResolution ? REDUCED_SCALE : 1f,
                     proto.isRealSnapshot, proto.windowingMode, proto.systemUiVisibility,
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 6fd1795..24b5b61 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -16,7 +16,7 @@
 
 package com.android.server.wm;
 
-import static android.graphics.Bitmap.CompressFormat.*;
+import static android.graphics.Bitmap.CompressFormat.JPEG;
 
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -321,6 +321,7 @@
             proto.windowingMode = mSnapshot.getWindowingMode();
             proto.systemUiVisibility = mSnapshot.getSystemUiVisibility();
             proto.isTranslucent = mSnapshot.isTranslucent();
+            proto.topActivityComponent = mSnapshot.getTopActivityComponent().flattenToString();
             final byte[] bytes = TaskSnapshotProto.toByteArray(proto);
             final File file = getProtoFile(mTaskId, mUserId);
             final AtomicFile atomicFile = new AtomicFile(file);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 0d98b20..912cb7f 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -23,6 +23,9 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -61,6 +64,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
+import android.view.DisplayCutout;
 import android.view.DisplayInfo;
 import android.view.Surface;
 import android.view.SurfaceControl;
@@ -143,10 +147,6 @@
     private Rect mBoundsAnimationTarget = new Rect();
     private Rect mBoundsAnimationSourceHintBounds = new Rect();
 
-    // Temporary storage for the new bounds that should be used after the configuration change.
-    // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
-    private final Rect mBoundsAfterRotation = new Rect();
-
     Rect mPreAnimationBounds = new Rect();
 
     private Dimmer mDimmer = new Dimmer(this);
@@ -259,6 +259,7 @@
         final Rect stackBounds = getBounds();
         getPendingTransaction()
                 .setSize(mAnimationBackgroundSurface, mTmpRect.width(), mTmpRect.height())
+                .setWindowCrop(mAnimationBackgroundSurface, mTmpRect.width(), mTmpRect.height())
                 .setPosition(mAnimationBackgroundSurface, mTmpRect.left - stackBounds.left,
                         mTmpRect.top - stackBounds.top);
         scheduleAnimation();
@@ -292,8 +293,9 @@
     private int setBounds(Rect existing, Rect bounds) {
         int rotation = Surface.ROTATION_0;
         int density = DENSITY_DPI_UNDEFINED;
-        if (mDisplayContent != null) {
-            mDisplayContent.getBounds(mTmpRect);
+        WindowContainer parent = getParent();
+        if (parent != null) {
+            parent.getBounds(mTmpRect);
             rotation = mDisplayContent.getDisplayInfo().rotation;
             density = mDisplayContent.getDisplayInfo().logicalDensityDpi;
         }
@@ -417,46 +419,33 @@
         getBounds(out);
     }
 
-    void updateDisplayInfo(Rect bounds) {
-        if (mDisplayContent == null) {
-            return;
-        }
-
-        for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
-            mChildren.get(taskNdx).updateDisplayInfo(mDisplayContent);
-        }
-        if (bounds != null) {
-            setBounds(bounds);
-            return;
-        } else if (matchParentBounds()) {
-            setBounds(null);
-            return;
-        }
-
-        mTmpRect2.set(getRawBounds());
-        final int newRotation = mDisplayContent.getDisplayInfo().rotation;
-        final int newDensity = mDisplayContent.getDisplayInfo().logicalDensityDpi;
-        if (mRotation == newRotation && mDensity == newDensity) {
-            setBounds(mTmpRect2);
-        }
-
-        // If the rotation or density didn't match, we'll update it in onConfigurationChanged.
-    }
-
-    /** @return true if bounds were updated to some non-empty value. */
-    boolean updateBoundsAfterConfigChange() {
-        if (mDisplayContent == null) {
-            // If the stack is already detached we're not updating anything,
-            // as it's going away soon anyway.
-            return false;
-        }
-
-        if (inPinnedWindowingMode()) {
-            getAnimationOrCurrentBounds(mTmpRect2);
+    /**
+     * Updates the passed-in {@code inOutBounds} based on how it would change when this container's
+     * override configuration is applied to the specified {@code parentConfig} and
+     * {@code prevConfig}. This gets run *after* the override configuration is updated, so it's
+     * safe to rely on wm hierarchy state in here (though eventually this dependence should be
+     * removed).
+     *
+     * This does NOT modify this TaskStack's configuration. However, it does, for the time-being,
+     * update various controller state (pinned/docked).
+     *
+     * @param parentConfig a parent configuration to compute relative to.
+     * @param prevConfig the full configuration used to produce the incoming {@code inOutBounds}.
+     * @param inOutBounds the bounds to update (both input and output).
+     * @return true if bounds were updated to some non-empty value. */
+    boolean updateBoundsForConfigChange(
+            Configuration parentConfig, Configuration prevConfig, Rect inOutBounds) {
+        if (getOverrideWindowingMode() == WINDOWING_MODE_PINNED) {
+            if ((mBoundsAnimatingRequested || mBoundsAnimating)
+                    && !mBoundsAnimationTarget.isEmpty()) {
+                getFinalAnimationBounds(mTmpRect2);
+            } else {
+                mTmpRect2.set(prevConfig.windowConfiguration.getBounds());
+            }
             boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
                     mTmpRect2, mTmpRect3);
             if (updated) {
-                mBoundsAfterRotation.set(mTmpRect3);
+                inOutBounds.set(mTmpRect3);
 
                 // Once we've set the bounds based on the rotation of the old bounds in the new
                 // orientation, clear the animation target bounds since they are obsolete, and
@@ -464,72 +453,75 @@
                 mBoundsAnimationTarget.setEmpty();
                 mBoundsAnimationSourceHintBounds.setEmpty();
                 mCancelCurrentBoundsAnimation = true;
-                return true;
             }
+            return updated;
         }
 
-        final int newRotation = getDisplayInfo().rotation;
-        final int newDensity = getDisplayInfo().logicalDensityDpi;
+        final int newRotation = parentConfig.windowConfiguration.getRotation();
+        final int newDensity = parentConfig.densityDpi;
 
-        if (mRotation == newRotation && mDensity == newDensity) {
-            // Nothing to do here as we already update the state in updateDisplayInfo.
+        if (prevConfig.windowConfiguration.getRotation() == newRotation
+                && prevConfig.densityDpi == newDensity) {
             return false;
         }
 
         if (matchParentBounds()) {
-            // Update stack bounds again since rotation changed since updateDisplayInfo().
-            setBounds(null);
-            // Return false since we don't need the client to resize.
             return false;
         }
 
-        mTmpRect2.set(getRawBounds());
-        mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
-        if (inSplitScreenPrimaryWindowingMode()) {
-            repositionPrimarySplitScreenStackAfterRotation(mTmpRect2);
-            snapDockedStackAfterRotation(mTmpRect2);
-            final int newDockSide = getDockSide(mTmpRect2);
+        mDisplayContent.rotateBounds(parentConfig.windowConfiguration.getBounds(),
+                prevConfig.windowConfiguration.getRotation(), newRotation, inOutBounds);
+        if (getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+                || getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
+            boolean primary = getOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+            repositionSplitScreenStackAfterRotation(parentConfig, primary, inOutBounds);
+            final DisplayCutout cutout = mDisplayContent.getDisplayInfo().displayCutout;
+            snapDockedStackAfterRotation(parentConfig, cutout, inOutBounds);
+            if (primary) {
+                final int newDockSide = getDockSide(mDisplayContent, parentConfig, inOutBounds);
 
-            // Update the dock create mode and clear the dock create bounds, these
-            // might change after a rotation and the original values will be invalid.
-            mService.setDockedStackCreateStateLocked(
-                    (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
-                            ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
-                            : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
-                    null);
-            mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
+                // Update the dock create mode and clear the dock create bounds, these
+                // might change after a rotation and the original values will be invalid.
+                mService.setDockedStackCreateStateLocked(
+                        (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
+                                ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
+                                : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
+                        null);
+                mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
+            }
         }
 
-        mBoundsAfterRotation.set(mTmpRect2);
         return true;
     }
 
-    void getBoundsForNewConfiguration(Rect outBounds) {
-        outBounds.set(mBoundsAfterRotation);
-        mBoundsAfterRotation.setEmpty();
-    }
-
     /**
      * Some primary split screen sides are not allowed by the policy. This method queries the policy
      * and moves the primary stack around if needed.
      *
-     * @param inOutBounds the bounds of the primary stack to adjust
+     * @param parentConfig the configuration of the stack's parent.
+     * @param primary true if adjusting the primary docked stack, false for secondary.
+     * @param inOutBounds the bounds of the stack to adjust.
      */
-    private void repositionPrimarySplitScreenStackAfterRotation(Rect inOutBounds) {
-        int dockSide = getDockSide(inOutBounds);
-        if (mDisplayContent.getDockedDividerController().canPrimaryStackDockTo(dockSide)) {
+    void repositionSplitScreenStackAfterRotation(Configuration parentConfig, boolean primary,
+            Rect inOutBounds) {
+        final int dockSide = getDockSide(mDisplayContent, parentConfig, inOutBounds);
+        final int otherDockSide = DockedDividerUtils.invertDockSide(dockSide);
+        final int primaryDockSide = primary ? dockSide : otherDockSide;
+        if (mDisplayContent.getDockedDividerController()
+                .canPrimaryStackDockTo(primaryDockSide,
+                        parentConfig.windowConfiguration.getBounds(),
+                        parentConfig.windowConfiguration.getRotation())) {
             return;
         }
-        mDisplayContent.getBounds(mTmpRect);
-        dockSide = DockedDividerUtils.invertDockSide(dockSide);
-        switch (dockSide) {
+        final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
+        switch (otherDockSide) {
             case DOCKED_LEFT:
                 int movement = inOutBounds.left;
                 inOutBounds.left -= movement;
                 inOutBounds.right -= movement;
                 break;
             case DOCKED_RIGHT:
-                movement = mTmpRect.right - inOutBounds.right;
+                movement = parentBounds.right - inOutBounds.right;
                 inOutBounds.left += movement;
                 inOutBounds.right += movement;
                 break;
@@ -539,7 +531,7 @@
                 inOutBounds.bottom -= movement;
                 break;
             case DOCKED_BOTTOM:
-                movement = mTmpRect.bottom - inOutBounds.bottom;
+                movement = parentBounds.bottom - inOutBounds.bottom;
                 inOutBounds.top += movement;
                 inOutBounds.bottom += movement;
                 break;
@@ -549,22 +541,22 @@
     /**
      * Snaps the bounds after rotation to the closest snap target for the docked stack.
      */
-    private void snapDockedStackAfterRotation(Rect outBounds) {
+    void snapDockedStackAfterRotation(Configuration parentConfig, DisplayCutout displayCutout,
+            Rect outBounds) {
 
         // Calculate the current position.
-        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
         final int dividerSize = mDisplayContent.getDockedDividerController().getContentWidth();
-        final int dockSide = getDockSide(outBounds);
+        final int dockSide = getDockSide(parentConfig, outBounds);
         final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
                 dockSide, dividerSize);
-        final int displayWidth = displayInfo.logicalWidth;
-        final int displayHeight = displayInfo.logicalHeight;
+        final int displayWidth = parentConfig.windowConfiguration.getBounds().width();
+        final int displayHeight = parentConfig.windowConfiguration.getBounds().height();
 
         // Snap the position to a target.
-        final int rotation = displayInfo.rotation;
-        final int orientation = mDisplayContent.getConfiguration().orientation;
+        final int rotation = parentConfig.windowConfiguration.getRotation();
+        final int orientation = parentConfig.orientation;
         mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight,
-                displayInfo.displayCutout, outBounds);
+                displayCutout, outBounds);
         final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
                 mService.mContext.getResources(), displayWidth, displayHeight,
                 dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds,
@@ -573,7 +565,7 @@
 
         // Recalculate the bounds based on the position of the target.
         DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide,
-                outBounds, displayInfo.logicalWidth, displayInfo.logicalHeight,
+                outBounds, displayWidth, displayHeight,
                 dividerSize);
     }
 
@@ -798,21 +790,30 @@
             return;
         }
         transaction.setSize(mSurfaceControl, width, height);
+        transaction.setWindowCrop(mSurfaceControl, width, height);
         mLastSurfaceSize.set(width, height);
     }
 
     @Override
     void onDisplayChanged(DisplayContent dc) {
-        if (mDisplayContent != null) {
+        if (mDisplayContent != null && mDisplayContent != dc) {
             throw new IllegalStateException("onDisplayChanged: Already attached");
         }
 
+        final boolean movedToNewDisplay = mDisplayContent == null;
         mDisplayContent = dc;
 
-        updateBoundsForWindowModeChange();
-        mAnimationBackgroundSurface = makeChildSurface(null).setColorLayer(true)
-            .setName("animation background stackId=" + mStackId)
-            .build();
+        if (movedToNewDisplay) {
+            updateBoundsForWindowModeChange();
+        } else {
+            updateBoundsForDisplayChanges();
+        }
+
+        if (mAnimationBackgroundSurface == null) {
+            mAnimationBackgroundSurface = makeChildSurface(null).setColorLayer(true)
+                    .setName("animation background stackId=" + mStackId)
+                    .build();
+        }
 
         super.onDisplayChanged(dc);
     }
@@ -828,10 +829,41 @@
             }, true);
         }
 
-        updateDisplayInfo(bounds);
+        setBoundsForWindowModeChange(bounds);
         updateSurfaceBounds();
     }
 
+    private void setBoundsForWindowModeChange(Rect bounds) {
+        if (mDisplayContent == null) {
+            return;
+        }
+
+        if (bounds != null) {
+            setBounds(bounds);
+            return;
+        }
+
+        updateBoundsForDisplayChanges();
+    }
+
+    private void updateBoundsForDisplayChanges() {
+        // Avoid setting override bounds to bounds inherited from parent if there was no override
+        // bounds set.
+        if (matchParentBounds()) {
+            setBounds(null);
+            return;
+        }
+
+        mTmpRect2.set(getRawBounds());
+        final int newRotation = mDisplayContent.getDisplayInfo().rotation;
+        final int newDensity = mDisplayContent.getDisplayInfo().logicalDensityDpi;
+        if (mRotation == newRotation && mDensity == newDensity) {
+            setBounds(mTmpRect2);
+        }
+
+        // If the rotation or density didn't match, we'll update it in onConfigurationChanged.
+    }
+
     private Rect calculateBoundsForWindowModeChange() {
         final boolean inSplitScreenPrimary = inSplitScreenPrimaryWindowingMode();
         final TaskStack splitScreenStack =
@@ -1473,27 +1505,27 @@
      * information which side of the screen was the dock anchored.
      */
     int getDockSide() {
-        return getDockSide(getRawBounds());
+        return getDockSide(mDisplayContent.getConfiguration(), getRawBounds());
     }
 
     int getDockSideForDisplay(DisplayContent dc) {
-        return getDockSide(dc, getRawBounds());
+        return getDockSide(dc, dc.getConfiguration(), getRawBounds());
     }
 
-    private int getDockSide(Rect bounds) {
+    int getDockSide(Configuration parentConfig, Rect bounds) {
         if (mDisplayContent == null) {
             return DOCKED_INVALID;
         }
-        return getDockSide(mDisplayContent, bounds);
+        return getDockSide(mDisplayContent, parentConfig, bounds);
     }
 
-    private int getDockSide(DisplayContent dc, Rect bounds) {
+    private int getDockSide(DisplayContent dc, Configuration parentConfig, Rect bounds) {
         if (!inSplitScreenWindowingMode()) {
             return DOCKED_INVALID;
         }
-        dc.getBounds(mTmpRect);
-        final int orientation = dc.getConfiguration().orientation;
-        return dc.getDockedDividerController().getDockSide(bounds, mTmpRect, orientation);
+        return dc.getDockedDividerController().getDockSide(bounds,
+                parentConfig.windowConfiguration.getBounds(),
+                parentConfig.orientation, parentConfig.windowConfiguration.getRotation());
     }
 
     boolean hasTaskForUser(int userId) {
@@ -1748,6 +1780,11 @@
     @Override
     public boolean shouldDeferStartOnMoveToFullscreen() {
         synchronized (mService.mGlobalLock) {
+            if (!isAttached()) {
+                // Unnecessary to pause the animation because the stack is detached.
+                return false;
+            }
+
             // Workaround for the recents animation -- normally we need to wait for the new activity
             // to show before starting the PiP animation, but because we start and show the home
             // activity early for the recents animation prior to the PiP animation starting, there
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index abc3826..266006d 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -42,8 +42,10 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Builder;
 import android.view.SurfaceSession;
+
 import com.android.internal.util.ToBooleanFunction;
 import com.android.server.wm.SurfaceAnimator.Animatable;
+
 import java.io.PrintWriter;
 import java.util.Comparator;
 import java.util.LinkedList;
@@ -501,8 +503,10 @@
     }
 
     /**
-     * Notify that the display this container is on has changed.
-     * @param dc The new display this container is on.
+     * Notify that the display this container is on has changed. This could be either this container
+     * is moved to a new display, or some configurations on the display it is on changes.
+     *
+     * @param dc The display this container is on after changes.
      */
     void onDisplayChanged(DisplayContent dc) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a641f75..c47b22f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
+import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
 import static android.Manifest.permission.MANAGE_APP_TOKENS;
 import static android.Manifest.permission.READ_FRAME_BUFFER;
 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
@@ -29,6 +30,7 @@
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.myPid;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.DOCKED_INVALID;
@@ -61,6 +63,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
 
@@ -117,6 +120,7 @@
 import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
 import android.app.IAssistDataReceiver;
+import android.app.WindowConfiguration;
 import android.app.admin.DevicePolicyCache;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -214,6 +218,7 @@
 import android.view.WindowContentFrameStats;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
+import android.view.WindowManager.RemoveContentMode;
 import android.view.WindowManager.TransitionType;
 import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
@@ -427,7 +432,7 @@
     final AppOpsManager mAppOps;
     final PackageManagerInternal mPmInternal;
 
-    final DisplaySettings mDisplaySettings;
+    final DisplayWindowSettings mDisplayWindowSettings;
 
     /** If the system should display notifications for apps displaying an alert window. */
     boolean mShowAlertWindowNotifications = true;
@@ -441,7 +446,7 @@
     final WindowHashMap mWindowMap = new WindowHashMap();
 
     /** Global service lock used by the package the owns this service. */
-    WindowManagerGlobalLock mGlobalLock = new WindowManagerGlobalLock();
+    final WindowManagerGlobalLock mGlobalLock;
 
     /**
      * List of app window tokens that are waiting for replacing windows. If the
@@ -538,12 +543,21 @@
     int mDockedStackCreateMode = SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
     Rect mDockedStackCreateBounds;
 
-    boolean mForceResizableTasks = false;
-    boolean mSupportsPictureInPicture = false;
-    boolean mSupportsFreeformWindowManagement = false;
-    boolean mIsPc = false;
+    boolean mForceResizableTasks;
+    boolean mSupportsPictureInPicture;
+    boolean mSupportsFreeformWindowManagement;
+    boolean mIsPc;
+    /**
+     * Flag that indicates that desktop mode is forced for public secondary screens.
+     *
+     * This includes several settings:
+     * - Set freeform windowing mode on external screen if it's supported and enabled.
+     * - Enable system decorations and IME on external screen.
+     * - TODO: Show mouse pointer on external screen.
+     */
+    boolean mForceDesktopModeOnExternalDisplays;
 
-    boolean mDisableTransitionAnimation = false;
+    boolean mDisableTransitionAnimation;
 
     int getDragLayerLocked() {
         return mPolicy.getWindowLayerFromTypeLw(TYPE_DRAG) * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
@@ -609,13 +623,6 @@
      */
     final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
 
-    /** This just indicates the window the input method is on top of, not
-     * necessarily the window its input is going to. */
-    WindowState mInputMethodTarget = null;
-
-    /** If true hold off on modifying the animation layer of mInputMethodTarget */
-    boolean mInputMethodTargetWaitingAnim;
-
     boolean mHardKeyboardAvailable;
     WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
     SettingsObserver mSettingsObserver;
@@ -855,9 +862,11 @@
     }
 
     public static WindowManagerService main(final Context context, final InputManagerService im,
-            final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy) {
+            final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
+            final WindowManagerGlobalLock globalLock) {
         DisplayThread.getHandler().runWithScissors(() ->
-                sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy),
+                sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
+                        globalLock),
                 0);
         return sInstance;
     }
@@ -879,8 +888,10 @@
     }
 
     private WindowManagerService(Context context, InputManagerService inputManager,
-            boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy) {
+            boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
+            WindowManagerGlobalLock globalLock) {
         installLock(this, INDEX_WINDOW);
+        mGlobalLock = globalLock;
         mContext = context;
         mAllowBootMessages = showBootMsgs;
         mOnlyCore = onlyCore;
@@ -900,7 +911,7 @@
                 com.android.internal.R.bool.config_disableTransitionAnimation);
         mInputManager = inputManager; // Must be before createDisplayContentLocked.
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
-        mDisplaySettings = new DisplaySettings(this);
+        mDisplayWindowSettings = new DisplayWindowSettings(this);
 
         mPolicy = policy;
         mAnimator = new WindowAnimator(this);
@@ -976,17 +987,21 @@
             }
         }, UserHandle.ALL, suspendPackagesFilter, null, null);
 
+        final ContentResolver resolver = context.getContentResolver();
         // Get persisted window scale setting
-        mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
+        mWindowAnimationScaleSetting = Settings.Global.getFloat(resolver,
                 Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
-        mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
+        mTransitionAnimationScaleSetting = Settings.Global.getFloat(resolver,
                 Settings.Global.TRANSITION_ANIMATION_SCALE,
                 context.getResources().getFloat(
                         R.dimen.config_appTransitionAnimationDurationScaleDefault));
 
-        setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
+        setAnimatorDurationScale(Settings.Global.getFloat(resolver,
                 Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
 
+        mForceDesktopModeOnExternalDisplays = Settings.Global.getInt(resolver,
+                DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0;
+
         IntentFilter filter = new IntentFilter();
         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
         filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
@@ -2403,20 +2418,13 @@
         return config;
     }
 
-    @Override
-    public int[] setNewDisplayOverrideConfiguration(Configuration overrideConfig, int displayId) {
-        if (!checkCallingPermission(MANAGE_APP_TOKENS, "setNewDisplayOverrideConfiguration()")) {
-            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
+    void setNewDisplayOverrideConfiguration(Configuration overrideConfig, DisplayContent dc) {
+        if (mWaitingForConfig) {
+            mWaitingForConfig = false;
+            mLastFinishedFreezeSource = "new-config";
         }
 
-        synchronized (mGlobalLock) {
-            if (mWaitingForConfig) {
-                mWaitingForConfig = false;
-                mLastFinishedFreezeSource = "new-config";
-            }
-
-            return mRoot.setDisplayOverrideConfigurationIfNeeded(overrideConfig, displayId);
-        }
+        mRoot.setDisplayOverrideConfigurationIfNeeded(overrideConfig, dc);
     }
 
     // TODO(multi-display): remove when no default display use case.
@@ -2629,21 +2637,16 @@
     /**
      * Starts deferring layout passes. Useful when doing multiple changes but to optimize
      * performance, only one layout pass should be done. This can be called multiple times, and
-     * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout}
+     * layouting will be resumed once the last caller has called
+     * {@link #continueSurfaceLayout}.
      */
-    public void deferSurfaceLayout() {
-        synchronized (mGlobalLock) {
-            mWindowPlacerLocked.deferLayout();
-        }
+    void deferSurfaceLayout() {
+        mWindowPlacerLocked.deferLayout();
     }
 
-    /**
-     * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()}
-     */
-    public void continueSurfaceLayout() {
-        synchronized (mGlobalLock) {
-            mWindowPlacerLocked.continueLayout();
-        }
+    /** Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()} */
+    void continueSurfaceLayout() {
+        mWindowPlacerLocked.continueLayout();
     }
 
     /**
@@ -4390,6 +4393,7 @@
 
                     AccessibilityController accessibilityController = null;
 
+                    final boolean topFocusedDisplayChanged = msg.arg1 != 0;
                     synchronized (mGlobalLock) {
                         // TODO(multidisplay): Accessibility supported only of default desiplay.
                         if (mAccessibilityController != null && displayContent.isDefaultDisplay) {
@@ -4398,10 +4402,24 @@
 
                         lastFocus = displayContent.mLastFocus;
                         newFocus = displayContent.mCurrentFocus;
-                        if (lastFocus == newFocus) {
-                            // Focus is not changing, so nothing to do.
-                            return;
+                    }
+                    if (lastFocus == newFocus) {
+                        // Report focus to ViewRootImpl when top focused display changes.
+                        // Or, nothing to do for no window focus change.
+                        if (topFocusedDisplayChanged && newFocus != null) {
+                            if (DEBUG_FOCUS_LIGHT) {
+                                Slog.d(TAG, "Reporting focus: " + newFocus
+                                        + " due to top focused display change.");
+                            }
+                            // See {@link IWindow#windowFocusChanged} to know why set
+                            // reportToClient as false.
+                            newFocus.reportFocusChangedSerialized(true, mInTouchMode,
+                                    false /* reportToClient */);
+                            notifyFocusChanged();
                         }
+                        return;
+                    }
+                    synchronized (mGlobalLock) {
                         displayContent.mLastFocus = newFocus;
                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Focus moving from " + lastFocus +
                                 " to " + newFocus + " displayId=" + displayContent.getDisplayId());
@@ -4420,13 +4438,15 @@
 
                     if (newFocus != null) {
                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus);
-                        newFocus.reportFocusChangedSerialized(true, mInTouchMode);
+                        newFocus.reportFocusChangedSerialized(true, mInTouchMode,
+                                true /* reportToClient */);
                         notifyFocusChanged();
                     }
 
                     if (lastFocus != null) {
                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus);
-                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
+                        lastFocus.reportFocusChangedSerialized(false, mInTouchMode,
+                                true /* reportToClient */);
                     }
                 } break;
 
@@ -4443,7 +4463,8 @@
                     for (int i = 0; i < N; i++) {
                         if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " +
                                 losers.get(i));
-                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
+                        losers.get(i).reportFocusChangedSerialized(false, mInTouchMode,
+                                true /* reportToClient */);
                     }
                 } break;
 
@@ -5085,7 +5106,7 @@
         displayInfo.overscanRight = right;
         displayInfo.overscanBottom = bottom;
 
-        mDisplaySettings.setOverscanLocked(displayInfo, left, top, right, bottom);
+        mDisplayWindowSettings.setOverscanLocked(displayInfo, left, top, right, bottom);
 
         reconfigureDisplayLocked(displayContent);
     }
@@ -5920,9 +5941,13 @@
         pw.print("  mGlobalConfiguration="); pw.println(mRoot.getConfiguration());
         pw.print("  mHasPermanentDpad="); pw.println(mHasPermanentDpad);
         mRoot.dumpTopFocusedDisplayId(pw);
-        if (mInputMethodTarget != null) {
-            pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
-        }
+        mRoot.forAllDisplays(dc -> {
+            final WindowState inputMethodTarget = dc.mInputMethodTarget;
+            if (inputMethodTarget != null) {
+                pw.print("  mInputMethodTarget in display# "); pw.print(dc.getDisplayId());
+                pw.print(' '); pw.println(inputMethodTarget);
+            }
+        });
         pw.print("  mInTouchMode="); pw.println(mInTouchMode);
         pw.print("  mLastDisplayFreezeDuration=");
                 TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
@@ -6406,6 +6431,12 @@
         }
     }
 
+    void setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays) {
+        synchronized (mWindowMap) {
+            mForceDesktopModeOnExternalDisplays = forceDesktopModeOnExternalDisplays;
+        }
+    }
+
     public void setIsPc(boolean isPc) {
         synchronized (mGlobalLock) {
             mIsPc = isPc;
@@ -6584,10 +6615,10 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
-                final DisplayContent dc = getDisplayContentOrCreate(displayId, null);
+                final DisplayContent dc = getDisplayContentOrCreate(displayId, null /* token */);
                 if (dc == null) {
                     throw new IllegalArgumentException(
-                            "Trying to register a non existent display.");
+                            "Trying to configure a non existent display.");
                 }
                 // We usually set the override info in DisplayManager so that we get consistent
                 // values when displays are changing. However, we don't do this for displays that
@@ -6603,6 +6634,193 @@
     }
 
     @Override
+    public int getWindowingMode(int displayId) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "getWindowingMode()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to get windowing mode of a display that does not exist: "
+                        + displayId);
+                return WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+            }
+            return mDisplayWindowSettings.getWindowingModeLocked(displayContent);
+        }
+    }
+
+    @Override
+    public void setWindowingMode(int displayId, int mode) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setWindowingMode()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to set windowing mode to a display that does not exist: "
+                        + displayId);
+                return;
+            }
+
+            mDisplayWindowSettings.setWindowingModeLocked(displayContent, mode);
+
+            reconfigureDisplayLocked(displayContent);
+        }
+    }
+
+    @Override
+    public @RemoveContentMode int getRemoveContentMode(int displayId) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "getRemoveContentMode()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to get remove mode of a display that does not exist: "
+                        + displayId);
+                return REMOVE_CONTENT_MODE_UNDEFINED;
+            }
+            return mDisplayWindowSettings.getRemoveContentModeLocked(displayContent);
+        }
+    }
+
+    @Override
+    public void setRemoveContentMode(int displayId, @RemoveContentMode int mode) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setRemoveContentMode()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to set remove mode to a display that does not exist: "
+                        + displayId);
+                return;
+            }
+
+            mDisplayWindowSettings.setRemoveContentModeLocked(displayContent, mode);
+
+            reconfigureDisplayLocked(displayContent);
+        }
+    }
+
+    @Override
+    public boolean shouldShowWithInsecureKeyguard(int displayId) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "shouldShowWithInsecureKeyguard()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to get flag of a display that does not exist: "
+                        + displayId);
+                return false;
+            }
+            return mDisplayWindowSettings.shouldShowWithInsecureKeyguardLocked(displayContent);
+        }
+    }
+
+    @Override
+    public void setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW,
+                "setShouldShowWithInsecureKeyguard()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to set flag to a display that does not exist: "
+                        + displayId);
+                return;
+            }
+
+            mDisplayWindowSettings.setShouldShowWithInsecureKeyguardLocked(displayContent,
+                    shouldShow);
+
+            reconfigureDisplayLocked(displayContent);
+        }
+    }
+
+    @Override
+    public boolean shouldShowSystemDecors(int displayId) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "shouldShowSystemDecors()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to get system decors flag of a display that does "
+                        + "not exist: " + displayId);
+                return false;
+            }
+            return mDisplayWindowSettings.shouldShowSystemDecorsLocked(displayContent);
+        }
+    }
+
+    @Override
+    public void setShouldShowSystemDecors(int displayId, boolean shouldShow) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setShouldShowSystemDecors()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to set system decors flag to a display that does "
+                        + "not exist: " + displayId);
+                return;
+            }
+
+            mDisplayWindowSettings.setShouldShowSystemDecorsLocked(displayContent, shouldShow);
+
+            reconfigureDisplayLocked(displayContent);
+        }
+    }
+
+    @Override
+    public boolean shouldShowIme(int displayId) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "shouldShowIme()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to get IME flag of a display that does not exist: "
+                        + displayId);
+                return false;
+            }
+            return mDisplayWindowSettings.shouldShowImeLocked(displayContent);
+        }
+    }
+
+    @Override
+    public void setShouldShowIme(int displayId, boolean shouldShow) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setShouldShowIme()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to set IME flag to a display that does not exist: "
+                        + displayId);
+                return;
+            }
+
+            mDisplayWindowSettings.setShouldShowImeLocked(displayContent, shouldShow);
+
+            reconfigureDisplayLocked(displayContent);
+        }
+    }
+
+    @Override
     public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
             throws RemoteException {
         if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, "registerShortcutKey")) {
@@ -6902,7 +7120,7 @@
             if (DEBUG_DISPLAY) {
                 Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId);
             }
-            synchronized (WindowManagerService.this) {
+            synchronized (mGlobalLock) {
                 mVr2dDisplayId = vr2dDisplayId;
             }
         }
@@ -7027,10 +7245,6 @@
      * WARNING: This interrupts surface updates, be careful! Don't
      * execute within the transaction for longer than you would
      * execute on an animation thread.
-     * WARNING: This holds the WindowManager lock, so if exec will acquire
-     * the ActivityManager lock, you should hold it BEFORE calling this
-     * otherwise there is a risk of deadlock if another thread holding the AM
-     * lock waits on the WM lock.
      * WARNING: This method contains locks known to the State of California
      * to cause Deadlocks and other conditions.
      *
@@ -7051,19 +7265,12 @@
      * deferSurfaceLayout may be a little too broad, in particular the total
      * enclosure of startActivityUnchecked which could run for quite some time.
      */
-    public void inSurfaceTransaction(Runnable exec) {
-        // We hold the WindowManger lock to ensure relayoutWindow
-        // does not return while a Surface transaction is opening.
-        // The client depends on us to have resized the surface
-        // by that point (b/36462635)
-
-        synchronized (mGlobalLock) {
-            SurfaceControl.openTransaction();
-            try {
-                exec.run();
-            } finally {
-                SurfaceControl.closeTransaction();
-            }
+    void inSurfaceTransaction(Runnable exec) {
+        SurfaceControl.openTransaction();
+        try {
+            exec.run();
+        } finally {
+            SurfaceControl.closeTransaction();
         }
     }
 
@@ -7139,6 +7346,10 @@
         mRotatingSeamlessly = true;
     }
 
+    boolean isRotatingSeamlessly() {
+        return mRotatingSeamlessly;
+    }
+
     void finishSeamlessRotation() {
         mRotatingSeamlessly = false;
     }
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index bb17254..4c9788d 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -56,6 +56,7 @@
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.Watchdog;
 
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 
@@ -690,24 +691,52 @@
     }
 
     void addPackage(String pkg, long versionCode) {
-        // TODO(b/80414790): Calling directly into AM for now which can lead to deadlock once we are
-        // using WM lock. Need to figure-out if it is okay to do this asynchronously.
         if (mListener == null) return;
-        mListener.addPackage(pkg, versionCode);
+        // Posting on handler so WM lock isn't held when we call into AM.
+        final Message m = PooledLambda.obtainMessage(
+                WindowProcessListener::addPackage, mListener, pkg, versionCode);
+        mAtm.mH.sendMessage(m);
     }
 
     ProfilerInfo onStartActivity(int topProcessState) {
-        // TODO(b/80414790): Calling directly into AM for now which can lead to deadlock once we are
-        // using WM lock. Need to figure-out if it is okay to do this asynchronously.
-        if (mListener == null) return null;
-        return mListener.onStartActivity(topProcessState);
+        ProfilerInfo profilerInfo = null;
+        boolean setProfileProc = false;
+        if (mAtm.mProfileApp != null
+                && mAtm.mProfileApp.equals(mName)) {
+            if (mAtm.mProfileProc == null || mAtm.mProfileProc == this) {
+                setProfileProc = true;
+                final ProfilerInfo profilerInfoSvc = mAtm.mProfilerInfo;
+                if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) {
+                    if (profilerInfoSvc.profileFd != null) {
+                        try {
+                            profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup();
+                        } catch (IOException e) {
+                            profilerInfoSvc.closeFd();
+                        }
+                    }
+
+                    profilerInfo = new ProfilerInfo(profilerInfoSvc);
+                }
+            }
+        }
+
+
+        if (mListener != null) {
+            // Posting on handler so WM lock isn't held when we call into AM.
+            final Message m = PooledLambda.obtainMessage(WindowProcessListener::onStartActivity,
+                    mListener, topProcessState, setProfileProc);
+            mAtm.mH.sendMessage(m);
+        }
+
+        return profilerInfo;
     }
 
     public void appDied() {
-        // TODO(b/80414790): Calling directly into AM for now which can lead to deadlock once we are
-        // using WM lock. Need to figure-out if it is okay to do this asynchronously.
         if (mListener == null) return;
-        mListener.appDied();
+        // Posting on handler so WM lock isn't held when we call into AM.
+        final Message m = PooledLambda.obtainMessage(
+                WindowProcessListener::appDied, mListener);
+        mAtm.mH.sendMessage(m);
     }
 
     void registerDisplayConfigurationListenerLocked(ActivityDisplay activityDisplay) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessListener.java b/services/core/java/com/android/server/wm/WindowProcessListener.java
index 7f20f4b..bce5e2d 100644
--- a/services/core/java/com/android/server/wm/WindowProcessListener.java
+++ b/services/core/java/com/android/server/wm/WindowProcessListener.java
@@ -16,7 +16,6 @@
 
 package com.android.server.wm;
 
-import android.app.ProfilerInfo;
 import android.util.proto.ProtoOutputStream;
 
 /**
@@ -58,7 +57,7 @@
     void addPackage(String pkg, long versionCode);
 
     /** Called when we are in the process on starting an activity. */
-    ProfilerInfo onStartActivity(int topProcessState);
+    void onStartActivity(int topProcessState, boolean setProfileProc);
 
     /** App died :(...oh well */
     void appDied();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 99f65c3..a117cf3 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -191,7 +191,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputWindowHandle;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
 import com.android.server.wm.utils.InsetUtils;
@@ -718,7 +718,7 @@
         mLastRequestedHeight = 0;
         mLayer = 0;
         mInputWindowHandle = new InputWindowHandle(
-                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this, c,
+                mAppToken != null ? mAppToken.mInputApplicationHandle : null, c,
                     getDisplayId());
     }
 
@@ -2047,7 +2047,7 @@
             // Create dummy event receiver that simply reports all events as handled.
             mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
         }
-        mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
+        mService.mInputManager.registerInputChannel(mInputChannel, mClient.asBinder());
     }
 
     void disposeInputChannel() {
@@ -2059,6 +2059,7 @@
         // unregister server channel first otherwise it complains about broken channel
         if (mInputChannel != null) {
             mService.mInputManager.unregisterInputChannel(mInputChannel);
+
             mInputChannel.dispose();
             mInputChannel = null;
         }
@@ -2841,12 +2842,13 @@
      * Report a focus change.  Must be called with no locks held, and consistently
      * from the same serialized thread (such as dispatched from a handler).
      */
-    void reportFocusChangedSerialized(boolean focused, boolean inTouchMode) {
+    void reportFocusChangedSerialized(boolean focused, boolean inTouchMode,
+            boolean reportToClient) {
         try {
-            mClient.windowFocusChanged(focused, inTouchMode);
+            mClient.windowFocusChanged(focused, inTouchMode, reportToClient);
         } catch (RemoteException e) {
         }
-        if (mFocusCallbacks != null) {
+        if (mFocusCallbacks != null && reportToClient) {
             final int N = mFocusCallbacks.beginBroadcast();
             for (int i=0; i<N; i++) {
                 IWindowFocusObserver obs = mFocusCallbacks.getBroadcastItem(i);
@@ -4476,8 +4478,9 @@
 
     @Override
     boolean needsZBoost() {
-        if (mIsImWindow && mService.mInputMethodTarget != null) {
-            final AppWindowToken appToken = mService.mInputMethodTarget.mAppToken;
+        final WindowState inputMethodTarget = getDisplayContent().mInputMethodTarget;
+        if (mIsImWindow && inputMethodTarget != null) {
+            final AppWindowToken appToken = inputMethodTarget.mAppToken;
             if (appToken != null) {
                 return appToken.needsZBoost();
             }
@@ -4607,7 +4610,7 @@
             // Likewise if we share a token with the Input method target and are ordered
             // above it but not necessarily a child (e.g. a Dialog) then we also need
             // this promotion.
-            final WindowState imeTarget = mService.mInputMethodTarget;
+            final WindowState imeTarget = getDisplayContent().mInputMethodTarget;
             boolean inTokenWithAndAboveImeTarget = imeTarget != null && imeTarget != this
                     && imeTarget.mToken == mToken && imeTarget.compareTo(this) <= 0;
             return inTokenWithAndAboveImeTarget;
@@ -4684,7 +4687,7 @@
 
     @Override
     public boolean isInputMethodTarget() {
-        return mService.mInputMethodTarget == this;
+        return getDisplayContent().mInputMethodTarget == this;
     }
 
     long getFrameNumber() {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 15a3a1a3..04a526f 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -98,7 +98,7 @@
         "libhwbinder",
         "libutils",
         "libhwui",
-        "libbpf",
+        "libbpf_android",
         "libnetdbpf",
         "libnetdutils",
         "android.hardware.audio.common@2.0",
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 3943dba..e2db807 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -42,6 +42,8 @@
 #include <utils/Trace.h>
 #include <utils/SortedVector.h>
 
+#include <binder/IServiceManager.h>
+
 #include <input/PointerController.h>
 #include <input/SpriteController.h>
 
@@ -63,6 +65,7 @@
 #include "android_hardware_input_InputApplicationHandle.h"
 #include "android_hardware_input_InputWindowHandle.h"
 #include "android_hardware_display_DisplayViewport.h"
+#include "android_util_Binder.h"
 
 #include <vector>
 
@@ -153,15 +156,6 @@
             getInputApplicationHandleObjLocalRef(env);
 }
 
-static jobject getInputWindowHandleObjLocalRef(JNIEnv* env,
-        const sp<InputWindowHandle>& inputWindowHandle) {
-    if (inputWindowHandle == nullptr) {
-        return nullptr;
-    }
-    return static_cast<NativeInputWindowHandle*>(inputWindowHandle.get())->
-            getInputWindowHandleObjLocalRef(env);
-}
-
 static void loadSystemIconAsSpriteWithPointerIcon(JNIEnv* env, jobject contextObj, int32_t style,
         PointerIcon* outPointerIcon, SpriteIcon* outSpriteIcon) {
     status_t status = android_view_PointerIcon_loadSystemIcon(env,
@@ -216,8 +210,7 @@
 
     void setDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray);
 
-    status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
-            const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId);
+    status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel, int32_t displayId);
     status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
 
     void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, int32_t displayId);
@@ -253,17 +246,17 @@
             uint32_t policyFlags);
     virtual void notifyConfigurationChanged(nsecs_t when);
     virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-            const sp<InputWindowHandle>& inputWindowHandle,
+            const sp<IBinder>& token,
             const std::string& reason);
-    virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
+    virtual void notifyInputChannelBroken(const sp<IBinder>& token);
     virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags);
     virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig);
     virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
     virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
     virtual nsecs_t interceptKeyBeforeDispatching(
-            const sp<InputWindowHandle>& inputWindowHandle,
+            const sp<IBinder>& token,
             const KeyEvent* keyEvent, uint32_t policyFlags);
-    virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
+    virtual bool dispatchUnhandledKey(const sp<IBinder>& token,
             const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
     virtual bool checkInjectEventsPermissionNonReentrant(
@@ -442,11 +435,10 @@
 }
 
 status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
-        const sp<InputChannel>& inputChannel, const sp<InputWindowHandle>& inputWindowHandle,
-                int32_t displayId) {
+        const sp<InputChannel>& inputChannel, int32_t displayId) {
     ATRACE_CALL();
-    return mInputManager->getDispatcher()->registerInputChannel(inputChannel, inputWindowHandle,
-            displayId);
+    return mInputManager->getDispatcher()->registerInputChannel(
+            inputChannel, displayId);
 }
 
 status_t NativeInputManager::unregisterInputChannel(JNIEnv* /* env */,
@@ -657,7 +649,7 @@
 }
 
 nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
-        const sp<InputWindowHandle>& inputWindowHandle, const std::string& reason) {
+        const sp<IBinder>& token, const std::string& reason) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
     ALOGD("notifyANR");
 #endif
@@ -667,12 +659,11 @@
 
     jobject inputApplicationHandleObj =
             getInputApplicationHandleObjLocalRef(env, inputApplicationHandle);
-    jobject inputWindowHandleObj =
-            getInputWindowHandleObjLocalRef(env, inputWindowHandle);
+    jobject tokenObj = javaObjectForIBinder(env, token);
     jstring reasonObj = env->NewStringUTF(reason.c_str());
 
     jlong newTimeout = env->CallLongMethod(mServiceObj,
-                gServiceClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj,
+                gServiceClassInfo.notifyANR, inputApplicationHandleObj, tokenObj,
                 reasonObj);
     if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
         newTimeout = 0; // abort dispatch
@@ -681,12 +672,11 @@
     }
 
     env->DeleteLocalRef(reasonObj);
-    env->DeleteLocalRef(inputWindowHandleObj);
     env->DeleteLocalRef(inputApplicationHandleObj);
     return newTimeout;
 }
 
-void NativeInputManager::notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
+void NativeInputManager::notifyInputChannelBroken(const sp<IBinder>& token) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
     ALOGD("notifyInputChannelBroken");
 #endif
@@ -694,14 +684,11 @@
 
     JNIEnv* env = jniEnv();
 
-    jobject inputWindowHandleObj =
-            getInputWindowHandleObjLocalRef(env, inputWindowHandle);
-    if (inputWindowHandleObj) {
+    jobject tokenObj = javaObjectForIBinder(env, token);
+    if (tokenObj) {
         env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyInputChannelBroken,
-                inputWindowHandleObj);
+                tokenObj);
         checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
-
-        env->DeleteLocalRef(inputWindowHandleObj);
     }
 }
 
@@ -1061,7 +1048,7 @@
 }
 
 nsecs_t NativeInputManager::interceptKeyBeforeDispatching(
-        const sp<InputWindowHandle>& inputWindowHandle,
+        const sp<IBinder>& token,
         const KeyEvent* keyEvent, uint32_t policyFlags) {
     ATRACE_CALL();
     // Policy:
@@ -1072,13 +1059,14 @@
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
-        // Note: inputWindowHandle may be null.
-        jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
+        // Token may be null
+        jobject tokenObj = javaObjectForIBinder(env, token);
+
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
             jlong delayMillis = env->CallLongMethod(mServiceObj,
                     gServiceClassInfo.interceptKeyBeforeDispatching,
-                    inputWindowHandleObj, keyEventObj, policyFlags);
+                    tokenObj, keyEventObj, policyFlags);
             bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
             android_view_KeyEvent_recycle(env, keyEventObj);
             env->DeleteLocalRef(keyEventObj);
@@ -1092,12 +1080,11 @@
         } else {
             ALOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
         }
-        env->DeleteLocalRef(inputWindowHandleObj);
     }
     return result;
 }
 
-bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
+bool NativeInputManager::dispatchUnhandledKey(const sp<IBinder>& token,
         const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
     ATRACE_CALL();
     // Policy:
@@ -1106,13 +1093,13 @@
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
 
-        // Note: inputWindowHandle may be null.
-        jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
+        // Note: tokenObj may be null.
+        jobject tokenObj = javaObjectForIBinder(env, token);
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
             jobject fallbackKeyEventObj = env->CallObjectMethod(mServiceObj,
                     gServiceClassInfo.dispatchUnhandledKey,
-                    inputWindowHandleObj, keyEventObj, policyFlags);
+                    tokenObj, keyEventObj, policyFlags);
             if (checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey")) {
                 fallbackKeyEventObj = nullptr;
             }
@@ -1131,7 +1118,6 @@
         } else {
             ALOGE("Failed to obtain key event object for dispatchUnhandledKey.");
         }
-        env->DeleteLocalRef(inputWindowHandleObj);
     }
     return result;
 }
@@ -1316,7 +1302,7 @@
 }
 
 static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
-        jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jint displayId) {
+        jlong ptr, jobject inputChannelObj, jint displayId) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
@@ -1325,12 +1311,10 @@
         throwInputChannelNotInitialized(env);
         return;
     }
+    bool monitor = inputChannel->getToken() == nullptr && displayId != ADISPLAY_ID_NONE;
 
-    sp<InputWindowHandle> inputWindowHandle =
-            android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
+    status_t status = im->registerInputChannel(env, inputChannel, displayId);
 
-    status_t status = im->registerInputChannel(
-            env, inputChannel, inputWindowHandle, displayId);
     if (status) {
         std::string message;
         message += StringPrintf("Failed to register input channel.  status=%d", status);
@@ -1339,7 +1323,7 @@
     }
 
     // If inputWindowHandle is null and displayId >= 0, treat inputChannel as monitor.
-    if (inputWindowHandle != nullptr || displayId == ADISPLAY_ID_NONE) {
+    if (!monitor) {
         android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
                 handleInputChannelDisposed, im);
     }
@@ -1640,7 +1624,7 @@
     { "nativeHasKeys", "(JII[I[Z)Z",
             (void*) nativeHasKeys },
     { "nativeRegisterInputChannel",
-            "(JLandroid/view/InputChannel;Lcom/android/server/input/InputWindowHandle;I)V",
+            "(JLandroid/view/InputChannel;I)V",
             (void*) nativeRegisterInputChannel },
     { "nativeUnregisterInputChannel", "(JLandroid/view/InputChannel;)V",
             (void*) nativeUnregisterInputChannel },
@@ -1650,9 +1634,9 @@
             (void*) nativeInjectInputEvent },
     { "nativeToggleCapsLock", "(JI)V",
             (void*) nativeToggleCapsLock },
-    { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;I)V",
+    { "nativeSetInputWindows", "(J[Landroid/view/InputWindowHandle;I)V",
             (void*) nativeSetInputWindows },
-    { "nativeSetFocusedApplication", "(JILcom/android/server/input/InputApplicationHandle;)V",
+    { "nativeSetFocusedApplication", "(JILandroid/view/InputApplicationHandle;)V",
             (void*) nativeSetFocusedApplication },
     { "nativeSetFocusedDisplay", "(JI)V",
             (void*) nativeSetFocusedDisplay },
@@ -1731,11 +1715,11 @@
             "notifySwitch", "(JII)V");
 
     GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz,
-            "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V");
+            "notifyInputChannelBroken", "(Landroid/os/IBinder;)V");
 
     GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
             "notifyANR",
-            "(Lcom/android/server/input/InputApplicationHandle;Lcom/android/server/input/InputWindowHandle;Ljava/lang/String;)J");
+            "(Landroid/view/InputApplicationHandle;Landroid/os/IBinder;Ljava/lang/String;)J");
 
     GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
             "filterInputEvent", "(Landroid/view/InputEvent;I)Z");
@@ -1748,11 +1732,11 @@
 
     GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
             "interceptKeyBeforeDispatching",
-            "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)J");
+            "(Landroid/os/IBinder;Landroid/view/KeyEvent;I)J");
 
     GET_METHOD_ID(gServiceClassInfo.dispatchUnhandledKey, clazz,
             "dispatchUnhandledKey",
-            "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
+            "(Landroid/os/IBinder;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
 
     GET_METHOD_ID(gServiceClassInfo.checkInjectEventsPermission, clazz,
             "checkInjectEventsPermission", "(II)Z");
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index a4983a9..9216005 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1299,7 +1299,7 @@
     return (gnssHal != nullptr) ?  JNI_TRUE : JNI_FALSE;
 }
 
-static jboolean android_location_GnssLocationProvider_is_agps_ril_supported(
+static jboolean android_location_GnssNetworkConnectivityHandler_is_agps_ril_supported(
         JNIEnv* /* env */, jclass /* clazz */) {
     return (agnssRilIface != nullptr) ? JNI_TRUE : JNI_FALSE;
 }
@@ -1571,7 +1571,7 @@
     env->ReleasePrimitiveArrayCritical(data, bytes, JNI_ABORT);
 }
 
-static void android_location_GnssLocationProvider_agps_data_conn_open(
+static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_open(
         JNIEnv* env, jobject /* obj */, jstring apn, jint apnIpType) {
     if (agnssIface == nullptr) {
         ALOGE("no AGPS interface in agps_data_conn_open");
@@ -1591,7 +1591,7 @@
     env->ReleaseStringUTFChars(apn, apnStr);
 }
 
-static void android_location_GnssLocationProvider_agps_data_conn_closed(JNIEnv* /* env */,
+static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_closed(JNIEnv* /* env */,
                                                                        jobject /* obj */) {
     if (agnssIface == nullptr) {
         ALOGE("%s: AGPS interface not supported", __func__);
@@ -1604,7 +1604,7 @@
     }
 }
 
-static void android_location_GnssLocationProvider_agps_data_conn_failed(JNIEnv* /* env */,
+static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed(JNIEnv* /* env */,
                                                                        jobject /* obj */) {
     if (agnssIface == nullptr) {
         ALOGE("%s: AGPS interface not supported", __func__);
@@ -1718,7 +1718,7 @@
     return result;
 }
 
-static void android_location_GnssLocationProvider_update_network_state(JNIEnv* env,
+static void android_location_GnssNetworkConnectivityHandler_update_network_state(JNIEnv* env,
                                                                        jobject /* obj */,
                                                                        jboolean connected,
                                                                        jint type,
@@ -2118,8 +2118,6 @@
             android_location_GnssLocationProvider_class_init_native)},
     {"native_is_supported", "()Z", reinterpret_cast<void *>(
             android_location_GnssLocationProvider_is_supported)},
-    {"native_is_agps_ril_supported", "()Z",
-            reinterpret_cast<void *>(android_location_GnssLocationProvider_is_agps_ril_supported)},
     {"native_is_gnss_configuration_supported", "()Z",
             reinterpret_cast<void *>(
                     android_location_gpsLocationProvider_is_gnss_configuration_supported)},
@@ -2151,15 +2149,6 @@
     {"native_inject_xtra_data",
             "([BI)V",
             reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_xtra_data)},
-    {"native_agps_data_conn_open",
-            "(Ljava/lang/String;I)V",
-            reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_open)},
-    {"native_agps_data_conn_closed",
-            "()V",
-            reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_closed)},
-    {"native_agps_data_conn_failed",
-            "()V",
-            reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_data_conn_failed)},
     {"native_agps_set_id",
             "(ILjava/lang/String;)V",
             reinterpret_cast<void *>(android_location_GnssLocationProvider_agps_set_id)},
@@ -2176,9 +2165,6 @@
     {"native_get_internal_state",
             "()Ljava/lang/String;",
             reinterpret_cast<void *>(android_location_GnssLocationProvider_get_internal_state)},
-    {"native_update_network_state",
-            "(ZIZZLjava/lang/String;Ljava/lang/String;)V",
-            reinterpret_cast<void *>(android_location_GnssLocationProvider_update_network_state)},
     {"native_set_supl_es",
             "(I)Z",
             reinterpret_cast<void *>(android_location_GnssLocationProvider_set_supl_es)},
@@ -2278,6 +2264,24 @@
                     android_location_GnssNavigationMessageProvider_stop_navigation_message_collection)},
 };
 
+static const JNINativeMethod sNetworkConnectivityMethods[] = {
+     /* name, signature, funcPtr */
+    {"native_is_agps_ril_supported", "()Z",
+            reinterpret_cast<void *>(android_location_GnssNetworkConnectivityHandler_is_agps_ril_supported)},
+    {"native_update_network_state",
+            "(ZIZZLjava/lang/String;Ljava/lang/String;)V",
+            reinterpret_cast<void *>(android_location_GnssNetworkConnectivityHandler_update_network_state)},
+    {"native_agps_data_conn_open",
+            "(Ljava/lang/String;I)V",
+            reinterpret_cast<void *>(android_location_GnssNetworkConnectivityHandler_agps_data_conn_open)},
+    {"native_agps_data_conn_closed",
+            "()V",
+            reinterpret_cast<void *>(android_location_GnssNetworkConnectivityHandler_agps_data_conn_closed)},
+    {"native_agps_data_conn_failed",
+            "()V",
+            reinterpret_cast<void *>(android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed)},
+};
+
 int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
     jniRegisterNativeMethods(
             env,
@@ -2299,6 +2303,11 @@
             "com/android/server/location/GnssNavigationMessageProvider",
             sNavigationMessageMethods,
             NELEM(sNavigationMessageMethods));
+    jniRegisterNativeMethods(
+            env,
+            "com/android/server/location/GnssNetworkConnectivityHandler",
+            sNetworkConnectivityMethods,
+            NELEM(sNetworkConnectivityMethods));
     return jniRegisterNativeMethods(
             env,
             "com/android/server/location/GnssLocationProvider",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b88165e..a7542d7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -491,6 +491,11 @@
      */
     final boolean mIsWatch;
 
+    /**
+     * Whether this device has the telephony feature.
+     */
+    final boolean mHasTelephonyFeature;
+
     private final CertificateMonitor mCertificateMonitor;
     private final SecurityLogMonitor mSecurityLogMonitor;
 
@@ -2133,6 +2138,8 @@
         mHasFeature = mInjector.hasFeature();
         mIsWatch = mInjector.getPackageManager()
                 .hasSystemFeature(PackageManager.FEATURE_WATCH);
+        mHasTelephonyFeature = mInjector.getPackageManager()
+                .hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
         mBackgroundHandler = BackgroundThread.getHandler();
 
         // Needed when mHasFeature == false, because it controls the certificate warning text.
@@ -12927,7 +12934,7 @@
 
     @Override
     public int addOverrideApn(@NonNull ComponentName who, @NonNull ApnSetting apnSetting) {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
             return -1;
         }
         Preconditions.checkNotNull(who, "ComponentName is null in addOverrideApn");
@@ -12956,7 +12963,7 @@
     @Override
     public boolean updateOverrideApn(@NonNull ComponentName who, int apnId,
             @NonNull ApnSetting apnSetting) {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
             return false;
         }
         Preconditions.checkNotNull(who, "ComponentName is null in updateOverrideApn");
@@ -12978,7 +12985,7 @@
 
     @Override
     public boolean removeOverrideApn(@NonNull ComponentName who, int apnId) {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
             return false;
         }
         Preconditions.checkNotNull(who, "ComponentName is null in removeOverrideApn");
@@ -13004,7 +13011,7 @@
 
     @Override
     public List<ApnSetting> getOverrideApns(@NonNull ComponentName who) {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
             return Collections.emptyList();
         }
         Preconditions.checkNotNull(who, "ComponentName is null in getOverrideApns");
@@ -13040,7 +13047,7 @@
 
     @Override
     public void setOverrideApnsEnabled(@NonNull ComponentName who, boolean enabled) {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
             return;
         }
         Preconditions.checkNotNull(who, "ComponentName is null in setOverrideApnEnabled");
@@ -13063,7 +13070,7 @@
 
     @Override
     public boolean isOverrideApnEnabled(@NonNull ComponentName who) {
-        if (!mHasFeature) {
+        if (!mHasFeature || !mHasTelephonyFeature) {
             return false;
         }
         Preconditions.checkNotNull(who, "ComponentName is null in isOverrideApnEnabled");
diff --git a/services/intelligence/Android.bp b/services/intelligence/Android.bp
new file mode 100644
index 0000000..2df1235
--- /dev/null
+++ b/services/intelligence/Android.bp
@@ -0,0 +1,5 @@
+java_library_static {
+    name: "services.intelligence",
+    srcs: ["java/**/*.java"],
+    libs: ["services.core"],
+}
diff --git a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java b/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
new file mode 100644
index 0000000..b7d34d7
--- /dev/null
+++ b/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2018 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.intelligence;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.service.intelligence.IntelligenceService;
+import android.service.intelligence.InteractionContext;
+import android.service.intelligence.InteractionSessionId;
+import android.util.Slog;
+import android.view.intelligence.ContentCaptureEvent;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
+import com.android.server.AbstractRemoteService;
+import com.android.server.intelligence.RemoteIntelligenceService.RemoteIntelligenceServiceCallbacks;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks {
+
+    private static final String TAG = "ContentCaptureSession";
+
+    private final Object mLock;
+    private final IBinder mActivityToken;
+
+    private final IntelligencePerUserService mService;
+    private final RemoteIntelligenceService mRemoteService;
+    private final InteractionContext mInterationContext;
+    private final InteractionSessionId mId;
+
+    ContentCaptureSession(@NonNull Context context, int userId, @NonNull Object lock,
+            @NonNull IBinder activityToken, @NonNull IntelligencePerUserService service,
+            @NonNull ComponentName serviceComponentName, @NonNull ComponentName appComponentName,
+            int taskId, int displayId, @NonNull InteractionSessionId sessionId, int flags,
+            boolean bindInstantServiceAllowed, boolean verbose) {
+        mLock = lock;
+        mActivityToken = activityToken;
+        mService = service;
+        mId = Preconditions.checkNotNull(sessionId);
+        mRemoteService = new RemoteIntelligenceService(context,
+                IntelligenceService.SERVICE_INTERFACE, serviceComponentName, userId, this,
+                bindInstantServiceAllowed, verbose);
+        mInterationContext = new InteractionContext(appComponentName, taskId, displayId, flags);
+    }
+
+    /**
+     * Notifies the {@link IntelligenceService} that the service started.
+     */
+    @GuardedBy("mLock")
+    public void notifySessionStartedLocked() {
+        mRemoteService.onSessionLifecycleRequest(mInterationContext, mId);
+    }
+
+    /**
+     * Notifies the {@link IntelligenceService} of a batch of events.
+     */
+    public void sendEventsLocked(List<ContentCaptureEvent> events) {
+        mRemoteService.onContentCaptureEventsRequest(mId, events);
+    }
+
+    /**
+     * Cleans up the session and removes it from the service.
+     *
+     * @param notifyRemoteService whether it should trigger a {@link
+     * IntelligenceService#onDestroyInteractionSession(InteractionSessionId)}
+     * request.
+     */
+    @GuardedBy("mLock")
+    public void removeSelfLocked(boolean notifyRemoteService) {
+        try {
+            destroyLocked(notifyRemoteService);
+        } finally {
+            mService.removeSessionLocked(mId);
+        }
+    }
+
+    /**
+     * Cleans up the session, but not removes it from the service.
+     *
+     * @param notifyRemoteService whether it should trigger a {@link
+     * IntelligenceService#onDestroyInteractionSession(InteractionSessionId)}
+     * request.
+     */
+    @GuardedBy("mLock")
+    public void destroyLocked(boolean notifyRemoteService) {
+        if (mService.isVerbose()) {
+            Slog.v(TAG, "destroyLocked(notifyRemoteService=" + notifyRemoteService + ")");
+        }
+        // TODO(b/111276913): must call client to set session as FINISHED_BY_SERVER
+        if (notifyRemoteService) {
+            mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
+        }
+    }
+
+    @Override // from RemoteScreenObservationServiceCallbacks
+    public void onServiceDied(AbstractRemoteService service) {
+        // TODO(b/111276913): implement (remove session from PerUserSession?)
+        if (mService.isDebug()) {
+            Slog.d(TAG, "onServiceDied() for " + mId);
+        }
+        synchronized (mLock) {
+            removeSelfLocked(/* notifyRemoteService= */ false);
+        }
+    }
+
+    @Override // from RemoteScreenObservationServiceCallbacks
+    public void onFailureOrTimeout(boolean timedOut) {
+        // TODO(b/111276913): log metrics on whether timed out or not
+        if (mService.isDebug()) {
+            Slog.d(TAG, "onFailureOrTimeout(" + mId + "): timed out=" + timedOut);
+        }
+        synchronized (mLock) {
+            removeSelfLocked(/* notifyRemoteService= */ false);
+        }
+    }
+
+    @GuardedBy("mLock")
+    public void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
+        pw.print(prefix); pw.print("id: ");  mId.dump(pw); pw.println();
+        pw.print(prefix); pw.print("context: ");  mInterationContext.dump(pw); pw.println();
+        pw.print(prefix); pw.print("activity token: "); pw.println(mActivityToken);
+    }
+
+    @Override
+    public String toString() {
+        return "ContentCaptureSession[id=" + mId.getValue() + ", act=" + mActivityToken + "]";
+    }
+}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java b/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
new file mode 100644
index 0000000..fcfd246
--- /dev/null
+++ b/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2018 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.intelligence;
+
+import static android.content.Context.INTELLIGENCE_MANAGER_SERVICE;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.app.ActivityManagerInternal;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.UserManager;
+import android.service.intelligence.InteractionSessionId;
+import android.view.intelligence.ContentCaptureEvent;
+import android.view.intelligence.IIntelligenceManager;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.IResultReceiver;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.Preconditions;
+import com.android.server.AbstractMasterSystemService;
+import com.android.server.LocalServices;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * A service used to observe the contents of the screen.
+ *
+ * <p>The data collected by this service can be analyzed and combined with other sources to provide
+ * contextual data in other areas of the system such as Autofill.
+ */
+public final class IntelligenceManagerService
+        extends AbstractMasterSystemService<IntelligencePerUserService> {
+
+    private static final String TAG = "IntelligenceManagerService";
+
+    @GuardedBy("mLock")
+    private ActivityManagerInternal mAm;
+
+    private final LocalService mLocalService = new LocalService();
+
+    public IntelligenceManagerService(Context context) {
+        super(context, UserManager.DISALLOW_INTELLIGENCE_CAPTURE);
+    }
+
+    @Override // from AbstractMasterSystemService
+    protected String getServiceSettingsProperty() {
+        // TODO(b/111276913): STOPSHIP temporary settings, until it's set by resourcs + cmd
+        return "intel_service";
+    }
+
+    @Override // from AbstractMasterSystemService
+    protected IntelligencePerUserService newServiceLocked(@UserIdInt int resolvedUserId,
+            boolean disabled) {
+        return new IntelligencePerUserService(this, mLock, resolvedUserId);
+    }
+
+    @Override // from SystemService
+    public void onStart() {
+        publishBinderService(INTELLIGENCE_MANAGER_SERVICE,
+                new IntelligenceManagerServiceStub());
+        publishLocalService(IntelligenceManagerInternal.class, mLocalService);
+    }
+
+    @Override // from AbstractMasterSystemService
+    protected void onServiceRemoved(@NonNull IntelligencePerUserService service,
+            @UserIdInt int userId) {
+        service.destroyLocked();
+    }
+
+    private ActivityManagerInternal getAmInternal() {
+        synchronized (mLock) {
+            if (mAm == null) {
+                mAm = LocalServices.getService(ActivityManagerInternal.class);
+            }
+        }
+        return mAm;
+    }
+
+    final class IntelligenceManagerServiceStub extends IIntelligenceManager.Stub {
+
+        @Override
+        public void startSession(int userId, @NonNull IBinder activityToken,
+                @NonNull ComponentName componentName, @NonNull InteractionSessionId sessionId,
+                int flags, @NonNull IResultReceiver result) {
+            Preconditions.checkNotNull(activityToken);
+            Preconditions.checkNotNull(componentName);
+            Preconditions.checkNotNull(sessionId);
+
+            // TODO(b/111276913): refactor getTaskIdForActivity() to also return ComponentName,
+            // so we don't pass it on startSession (same for Autofill)
+            final int taskId = getAmInternal().getTaskIdForActivity(activityToken, false);
+
+            // TODO(b/111276913): get from AM as well
+            final int displayId = 0;
+
+            synchronized (mLock) {
+                final IntelligencePerUserService service = getServiceForUserLocked(userId);
+                service.startSessionLocked(activityToken, componentName, taskId, displayId,
+                        sessionId, flags, result);
+            }
+        }
+
+        @Override
+        public void sendEvents(int userId, @NonNull InteractionSessionId sessionId,
+                @NonNull List<ContentCaptureEvent> events) {
+            Preconditions.checkNotNull(sessionId);
+            Preconditions.checkNotNull(events);
+
+            synchronized (mLock) {
+                final IntelligencePerUserService service = getServiceForUserLocked(userId);
+                service.sendEventsLocked(sessionId, events);
+            }
+        }
+
+        @Override
+        public void finishSession(int userId, @NonNull InteractionSessionId sessionId) {
+            Preconditions.checkNotNull(sessionId);
+
+            synchronized (mLock) {
+                final IntelligencePerUserService service = getServiceForUserLocked(userId);
+                service.finishSessionLocked(sessionId);
+            }
+        }
+
+        @Override
+        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
+
+            synchronized (mLock) {
+                dumpLocked("", pw);
+            }
+        }
+    }
+
+    private final class LocalService extends IntelligenceManagerInternal {
+
+        @Override
+        public boolean isIntelligenceServiceForUser(int uid, int userId) {
+            synchronized (mLock) {
+                final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+                if (service != null) {
+                    return service.isIntelligenceServiceForUserLocked(uid);
+                }
+            }
+
+            return false;
+        }
+    }
+}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java b/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
new file mode 100644
index 0000000..471b40f
--- /dev/null
+++ b/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2018 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.intelligence;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.service.intelligence.InteractionSessionId;
+import android.util.ArrayMap;
+import android.util.Slog;
+import android.view.intelligence.ContentCaptureEvent;
+import android.view.intelligence.IntelligenceManager;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.IResultReceiver;
+import com.android.server.AbstractPerUserSystemService;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Per-user instance of {@link IntelligenceManagerService}.
+ */
+final class IntelligencePerUserService
+        extends AbstractPerUserSystemService<IntelligencePerUserService> {
+
+    private static final String TAG = "IntelligencePerUserService";
+
+    @GuardedBy("mLock")
+    private final ArrayMap<InteractionSessionId, ContentCaptureSession> mSessions =
+            new ArrayMap<>();
+
+    // TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
+
+    protected IntelligencePerUserService(
+            IntelligenceManagerService master, Object lock, int userId) {
+        super(master, lock, userId);
+    }
+
+    @Override // from PerUserSystemService
+    protected ServiceInfo newServiceInfo(@NonNull ComponentName serviceComponent)
+            throws NameNotFoundException {
+
+        ServiceInfo si;
+        try {
+            // TODO(b/111276913): must check that either the service is from a system component,
+            // or it matches a service set by shell cmd (so it can be used on CTS tests and when
+            // OEMs are implementing the real service
+            si = AppGlobals.getPackageManager().getServiceInfo(serviceComponent,
+                    PackageManager.GET_META_DATA, mUserId);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Could not get service for " + serviceComponent + ": " + e);
+            return null;
+        }
+        if (!Manifest.permission.BIND_INTELLIGENCE_SERVICE.equals(si.permission)) {
+            Slog.w(TAG, "IntelligenceService from '" + si.packageName
+                    + "' does not require permission "
+                    + Manifest.permission.BIND_INTELLIGENCE_SERVICE);
+            throw new SecurityException("Service does not require permission "
+                    + Manifest.permission.BIND_INTELLIGENCE_SERVICE);
+        }
+        return si;
+    }
+
+    // TODO(b/111276913): log metrics
+    @GuardedBy("mLock")
+    public void startSessionLocked(@NonNull IBinder activityToken,
+            @NonNull ComponentName componentName, int taskId, int displayId,
+            @NonNull InteractionSessionId sessionId, int flags,
+            @NonNull IResultReceiver resultReceiver) {
+        if (!isEnabledLocked()) {
+            sendToClient(resultReceiver, IntelligenceManager.STATE_DISABLED);
+            return;
+        }
+        final ComponentName serviceComponentName = getServiceComponentName();
+        if (serviceComponentName == null) {
+            // TODO(b/111276913): this happens when the system service is starting, we should
+            // probably handle it in a more elegant way (like waiting for boot_complete or
+            // something like that
+            if (mMaster.debug) {
+                Slog.d(TAG, "startSession(" + activityToken + "): hold your horses");
+            }
+            return;
+        }
+
+        ContentCaptureSession session = mSessions.get(sessionId);
+        if (session != null) {
+            if (mMaster.debug) {
+                Slog.d(TAG, "startSession(): reusing session " + sessionId + " for "
+                        + componentName);
+            }
+            // TODO(b/111276913): check if local ids match and decide what to do if they don't
+            // TODO(b/111276913): should we call session.notifySessionStartedLocked() again??
+            // if not, move notifySessionStartedLocked() into session constructor
+            sendToClient(resultReceiver, IntelligenceManager.STATE_ACTIVE);
+            return;
+        }
+
+        // TODO(b/117779333): get from mMaster once it's moved to superclass
+        final boolean bindInstantServiceAllowed = false;
+
+        session = new ContentCaptureSession(getContext(), mUserId, mLock, activityToken,
+                this, serviceComponentName, componentName, taskId, displayId, sessionId, flags,
+                bindInstantServiceAllowed, mMaster.verbose);
+        if (mMaster.verbose) {
+            Slog.v(TAG, "startSession(): new session for " + componentName + " and id "
+                    + sessionId);
+        }
+        mSessions.put(sessionId, session);
+        session.notifySessionStartedLocked();
+        sendToClient(resultReceiver, IntelligenceManager.STATE_ACTIVE);
+    }
+
+    // TODO(b/111276913): log metrics
+    @GuardedBy("mLock")
+    public void finishSessionLocked(@NonNull InteractionSessionId sessionId) {
+        if (!isEnabledLocked()) {
+            return;
+        }
+
+        final ContentCaptureSession session = mSessions.get(sessionId);
+        if (session == null) {
+            if (mMaster.debug) {
+                Slog.d(TAG, "finishSession(): no session with id" + sessionId);
+            }
+            return;
+        }
+        if (mMaster.verbose) {
+            Slog.v(TAG, "finishSession(): " + session);
+        }
+        session.removeSelfLocked(true);
+    }
+
+    // TODO(b/111276913): need to figure out why some events are sent before session is started;
+    // probably because IntelligenceManager is not buffering them until it gets the session back
+    @GuardedBy("mLock")
+    public void sendEventsLocked(@NonNull InteractionSessionId sessionId,
+            @NonNull List<ContentCaptureEvent> events) {
+        if (!isEnabledLocked()) {
+            return;
+        }
+        final ContentCaptureSession session = mSessions.get(sessionId);
+        if (session == null) {
+            if (mMaster.verbose) {
+                Slog.v(TAG, "sendEvents(): no session for " + sessionId);
+            }
+            return;
+        }
+        if (mMaster.verbose) {
+            Slog.v(TAG, "sendEvents(): id=" + sessionId + "; events =" + events.size());
+        }
+        session.sendEventsLocked(events);
+    }
+
+    @GuardedBy("mLock")
+    public void removeSessionLocked(@NonNull InteractionSessionId sessionId) {
+        mSessions.remove(sessionId);
+    }
+
+    @GuardedBy("mLock")
+    public boolean isIntelligenceServiceForUserLocked(int uid) {
+        return uid == getServiceUidLocked();
+    }
+
+    /**
+     * Destroys the service and all state associated with it.
+     *
+     * <p>Called when the service was disabled (for example, if the settings change).
+     */
+    @GuardedBy("mLock")
+    public void destroyLocked() {
+        if (mMaster.debug) Slog.d(TAG, "destroyLocked()");
+        final int numSessions = mSessions.size();
+        for (int i = 0; i < numSessions; i++) {
+            final ContentCaptureSession session = mSessions.valueAt(i);
+            session.destroyLocked(true);
+        }
+        mSessions.clear();
+    }
+
+    @Override
+    protected void dumpLocked(String prefix, PrintWriter pw) {
+        super.dumpLocked(prefix, pw);
+        if (mSessions.isEmpty()) {
+            pw.print(prefix); pw.println("no sessions");
+        } else {
+            final int size = mSessions.size();
+            pw.print(prefix); pw.print("number sessions: "); pw.println(size);
+            final String prefix2 = prefix + "  ";
+            for (int i = 0; i < size; i++) {
+                pw.print(prefix); pw.print("session@"); pw.println(i);
+                final ContentCaptureSession session = mSessions.valueAt(i);
+                session.dumpLocked(prefix2, pw);
+            }
+        }
+    }
+
+    private static void sendToClient(@NonNull IResultReceiver resultReceiver, int value) {
+        try {
+            resultReceiver.send(value, null);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Error async reporting result to client: " + e);
+        }
+    }
+}
diff --git a/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java b/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
new file mode 100644
index 0000000..9d241fb
--- /dev/null
+++ b/services/intelligence/java/com/android/server/intelligence/RemoteIntelligenceService.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2018 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.intelligence;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.service.intelligence.IIntelligenceService;
+import android.service.intelligence.InteractionContext;
+import android.service.intelligence.InteractionSessionId;
+import android.text.format.DateUtils;
+import android.util.Slog;
+import android.view.intelligence.ContentCaptureEvent;
+
+import com.android.server.AbstractRemoteService;
+
+import java.util.List;
+
+final class RemoteIntelligenceService extends AbstractRemoteService {
+
+    private static final String TAG = "RemoteIntelligenceService";
+
+    private static final long TIMEOUT_IDLE_BIND_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
+    private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.MINUTE_IN_MILLIS;
+
+    private final RemoteIntelligenceServiceCallbacks mCallbacks;
+    private IIntelligenceService mService;
+
+    RemoteIntelligenceService(Context context, String serviceInterface,
+            ComponentName componentName, int userId,
+            RemoteIntelligenceServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
+            boolean verbose) {
+        super(context, serviceInterface, componentName, userId, callbacks,
+                bindInstantServiceAllowed, verbose);
+        mCallbacks = callbacks;
+    }
+
+    @Override // from RemoteService
+    protected IInterface getServiceInterface(@NonNull IBinder service) {
+        mService = IIntelligenceService.Stub.asInterface(service);
+        return mService;
+    }
+
+    // TODO(b/111276913): modify super class to allow permanent binding when value is 0 or negative
+    @Override // from RemoteService
+    protected long getTimeoutIdleBindMillis() {
+        // TODO(b/111276913): read from Settings so it can be changed in the field
+        return TIMEOUT_IDLE_BIND_MILLIS;
+    }
+
+    @Override // from RemoteService
+    protected long getRemoteRequestMillis() {
+        // TODO(b/111276913): read from Settings so it can be changed in the field
+        return TIMEOUT_REMOTE_REQUEST_MILLIS;
+    }
+
+    /**
+     * Called by {@link ContentCaptureSession} to generate a call to the
+     * {@link RemoteIntelligenceService} to indicate the session was created (when {@code context}
+     * is not {@code null} or destroyed (when {@code context} is {@code null}).
+     */
+    public void onSessionLifecycleRequest(@Nullable InteractionContext context,
+            @NonNull InteractionSessionId sessionId) {
+        cancelScheduledUnbind();
+        scheduleRequest(new PendingSessionLifecycleRequest(this, context, sessionId));
+    }
+
+    /**
+     * Called by {@link ContentCaptureSession} to send a batch of events to the service.
+     */
+    public void onContentCaptureEventsRequest(@NonNull InteractionSessionId sessionId,
+            @NonNull List<ContentCaptureEvent> events) {
+        cancelScheduledUnbind();
+        scheduleRequest(new PendingOnContentCaptureEventsRequest(this, sessionId, events));
+    }
+
+
+    private abstract static class MyPendingRequest
+            extends PendingRequest<RemoteIntelligenceService> {
+        protected final InteractionSessionId mSessionId;
+
+        private MyPendingRequest(@NonNull RemoteIntelligenceService service,
+                @NonNull InteractionSessionId sessionId) {
+            super(service);
+            mSessionId = sessionId;
+        }
+
+        @Override // from PendingRequest
+        protected final void onTimeout(RemoteIntelligenceService remoteService) {
+            Slog.w(TAG, "timed out handling " + getClass().getSimpleName() + " for "
+                    + mSessionId);
+            remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ true);
+        }
+
+        @Override // from PendingRequest
+        public final void run() {
+            final RemoteIntelligenceService remoteService = getService();
+            if (remoteService != null) {
+                try {
+                    myRun(remoteService);
+                    // We don't expect the service to call us back, so we finish right away.
+                    finish();
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "exception handling " + getClass().getSimpleName() + " for "
+                            + mSessionId + ": " + e);
+                    remoteService.mCallbacks.onFailureOrTimeout(/* timedOut= */ false);
+                }
+            }
+        }
+
+        protected abstract void myRun(@NonNull RemoteIntelligenceService service)
+                throws RemoteException;
+
+    }
+
+    private static final class PendingSessionLifecycleRequest extends MyPendingRequest {
+
+        private final InteractionContext mContext;
+
+        protected PendingSessionLifecycleRequest(@NonNull RemoteIntelligenceService service,
+                @Nullable InteractionContext context, @NonNull InteractionSessionId sessionId) {
+            super(service, sessionId);
+            mContext = context;
+        }
+
+        @Override // from MyPendingRequest
+        public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
+            remoteService.mService.onSessionLifecycle(mContext, mSessionId);
+        }
+    }
+
+    private static final class PendingOnContentCaptureEventsRequest extends MyPendingRequest {
+
+        private final List<ContentCaptureEvent> mEvents;
+
+        protected PendingOnContentCaptureEventsRequest(@NonNull RemoteIntelligenceService service,
+                @NonNull InteractionSessionId sessionId,
+                @NonNull List<ContentCaptureEvent> events) {
+            super(service, sessionId);
+            mEvents = events;
+        }
+
+        @Override // from MyPendingRequest
+        public void myRun(@NonNull RemoteIntelligenceService remoteService) throws RemoteException {
+            remoteService.mService.onContentCaptureEvents(mSessionId, mEvents);
+        }
+    }
+
+    public interface RemoteIntelligenceServiceCallbacks extends VultureCallback {
+        // To keep it simple, we use the same callback for all failures / timeouts.
+        void onFailureOrTimeout(boolean timedOut);
+    }
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 49f410d..f8ac41f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -16,6 +16,12 @@
 
 package com.android.server;
 
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
+import static android.os.IServiceManager.DUMP_FLAG_PROTO;
+import static android.view.Display.DEFAULT_DISPLAY;
+
 import android.app.ActivityThread;
 import android.app.INotificationManager;
 import android.app.usage.UsageStatsManagerInternal;
@@ -29,6 +35,7 @@
 import android.content.res.Resources.Theme;
 import android.database.sqlite.SQLiteCompatibilityWalFlags;
 import android.database.sqlite.SQLiteGlobal;
+import android.hardware.display.ColorDisplayManager;
 import android.hardware.display.DisplayManagerInternal;
 import android.os.BaseBundle;
 import android.os.Binder;
@@ -56,7 +63,6 @@
 import android.view.WindowManager;
 
 import com.android.internal.R;
-import com.android.internal.app.ColorDisplayController;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.BinderInternal;
@@ -64,10 +70,12 @@
 import com.android.internal.util.EmergencyAffordanceManager;
 import com.android.internal.widget.ILockSettings;
 import com.android.server.am.ActivityManagerService;
-import com.android.server.wm.ActivityTaskManagerService;
 import com.android.server.appbinding.AppBindingService;
 import com.android.server.audio.AudioService;
 import com.android.server.biometrics.BiometricService;
+import com.android.server.biometrics.face.FaceService;
+import com.android.server.biometrics.fingerprint.FingerprintService;
+import com.android.server.biometrics.iris.IrisService;
 import com.android.server.broadcastradio.BroadcastRadioService;
 import com.android.server.camera.CameraServiceProxy;
 import com.android.server.clipboard.ClipboardService;
@@ -78,17 +86,16 @@
 import com.android.server.display.DisplayManagerService;
 import com.android.server.dreams.DreamManagerService;
 import com.android.server.emergency.EmergencyAffordanceService;
-import com.android.server.biometrics.face.FaceService;
-import com.android.server.biometrics.fingerprint.FingerprintService;
 import com.android.server.hdmi.HdmiControlService;
 import com.android.server.input.InputManagerService;
 import com.android.server.inputmethod.InputMethodManagerService;
+import com.android.server.inputmethod.MultiClientInputMethodManagerService;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.lights.LightsService;
 import com.android.server.media.MediaResourceMonitorService;
 import com.android.server.media.MediaRouterService;
-import com.android.server.media.MediaUpdateService;
 import com.android.server.media.MediaSessionService;
+import com.android.server.media.MediaUpdateService;
 import com.android.server.media.projection.MediaProjectionManagerService;
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.NetworkStatsService;
@@ -109,7 +116,9 @@
 import com.android.server.policy.PhoneWindowManager;
 import com.android.server.power.PowerManagerService;
 import com.android.server.power.ShutdownThread;
+import com.android.server.power.ThermalManagerService;
 import com.android.server.restrictions.RestrictionsManagerService;
+import com.android.server.role.RoleManagerService;
 import com.android.server.security.KeyAttestationApplicationIdProviderService;
 import com.android.server.security.KeyChainSystemService;
 import com.android.server.soundtrigger.SoundTriggerService;
@@ -127,6 +136,8 @@
 import com.android.server.usage.UsageStatsService;
 import com.android.server.vr.VrManagerService;
 import com.android.server.webkit.WebViewUpdateService;
+import com.android.server.wm.ActivityTaskManagerService;
+import com.android.server.wm.WindowManagerGlobalLock;
 import com.android.server.wm.WindowManagerService;
 
 import dalvik.system.VMRuntime;
@@ -138,13 +149,8 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Future;
 
-import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
-import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
-import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
-import static android.os.IServiceManager.DUMP_FLAG_PROTO;
-import static android.view.Display.DEFAULT_DISPLAY;
-
 public final class SystemServer {
+
     private static final String TAG = "SystemServer";
 
     // Tag for timing measurement of main thread.
@@ -229,6 +235,8 @@
             "com.android.server.wallpaper.WallpaperManagerService$Lifecycle";
     private static final String AUTO_FILL_MANAGER_SERVICE_CLASS =
             "com.android.server.autofill.AutofillManagerService";
+    private static final String INTELLIGENCE_MANAGER_SERVICE_CLASS =
+            "com.android.server.intelligence.IntelligenceManagerService";
     private static final String TIME_ZONE_RULES_MANAGER_SERVICE_CLASS =
             "com.android.server.timezone.RulesManagerService$Lifecycle";
     private static final String IOT_SERVICE_CLASS =
@@ -256,9 +264,8 @@
     private static final int sMaxBinderThreads = 31;
 
     /**
-     * Default theme used by the system context. This is used to style
-     * system-provided dialogs, such as the Power Off dialog, and other
-     * visual content.
+     * Default theme used by the system context. This is used to style system-provided dialogs, such
+     * as the Power Off dialog, and other visual content.
      */
     private static final int DEFAULT_SYSTEM_THEME =
             com.android.internal.R.style.Theme_DeviceDefault_System;
@@ -272,6 +279,7 @@
     // TODO: remove all of these references by improving dependency resolution and boot phases
     private PowerManagerService mPowerManagerService;
     private ActivityManagerService mActivityManagerService;
+    private WindowManagerGlobalLock mWindowManagerGlobalLock;
     private WebViewUpdateService mWebViewUpdateService;
     private DisplayManagerService mDisplayManagerService;
     private PackageManagerService mPackageManagerService;
@@ -298,8 +306,7 @@
     private static native void startSensorService();
 
     /**
-     * Start all HIDL services that are run inside the system server. This
-     * may take some time.
+     * Start all HIDL services that are run inside the system server. This may take some time.
      */
     private static native void startHidlServices();
 
@@ -335,7 +342,7 @@
             //
             // Default the timezone property to GMT if not set.
             //
-            String timezoneProperty =  SystemProperties.get("persist.sys.timezone");
+            String timezoneProperty = SystemProperties.get("persist.sys.timezone");
             if (timezoneProperty == null || timezoneProperty.isEmpty()) {
                 Slog.w(TAG, "Timezone not set; setting to GMT.");
                 SystemProperties.set("persist.sys.timezone", "GMT");
@@ -416,7 +423,7 @@
 
             // Prepare the main looper thread (this thread).
             android.os.Process.setThreadPriority(
-                android.os.Process.THREAD_PRIORITY_FOREGROUND);
+                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
             android.os.Process.setCanSelfBackground(false);
             Looper.prepareMainLooper();
             Looper.getMainLooper().setSlowLogThresholdMs(
@@ -521,7 +528,7 @@
                     if (filename != null && filename.startsWith("/data")) {
                         if (!new File(BLOCK_MAP_FILE).exists()) {
                             Slog.e(TAG, "Can't find block map file, uncrypt failed or " +
-                                       "unexpected runtime restart?");
+                                    "unexpected runtime restart?");
                             return;
                         }
                     }
@@ -554,11 +561,10 @@
     }
 
     /**
-     * Starts the small tangle of critical services that are needed to get
-     * the system off the ground.  These services have complex mutual dependencies
-     * which is why we initialize them all in one place here.  Unless your service
-     * is also entwined in these dependencies, it should be initialized in one of
-     * the other functions.
+     * Starts the small tangle of critical services that are needed to get the system off the
+     * ground.  These services have complex mutual dependencies which is why we initialize them all
+     * in one place here.  Unless your service is also entwined in these dependencies, it should be
+     * initialized in one of the other functions.
      */
     private void startBootstrapServices() {
         Slog.i(TAG, "Reading configuration...");
@@ -594,6 +600,7 @@
                 mSystemServiceManager, atm);
         mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
         mActivityManagerService.setInstaller(installer);
+        mWindowManagerGlobalLock = atm.getGlobalLock();
         traceEnd();
 
         // Power manager needs to be started early because other services need it.
@@ -604,6 +611,10 @@
         mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
         traceEnd();
 
+        traceBeginAndSlog("StartThermalManager");
+        mSystemServiceManager.startService(ThermalManagerService.class);
+        traceEnd();
+
         // Now that the power manager has been started, let the activity manager
         // initialize power management features.
         traceBeginAndSlog("InitPowerManagement");
@@ -770,8 +781,7 @@
     }
 
     /**
-     * Starts a miscellaneous grab bag of stuff that has yet to be refactored
-     * and organized.
+     * Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
      */
     private void startOtherServices() {
         final Context context = mSystemContext;
@@ -782,7 +792,7 @@
         NetworkStatsService networkStats = null;
         NetworkPolicyManagerService networkPolicy = null;
         ConnectivityService connectivity = null;
-        NsdService serviceDiscovery= null;
+        NsdService serviceDiscovery = null;
         WindowManagerService wm = null;
         SerialService serial = null;
         NetworkTimeUpdateService networkTimeUpdater = null;
@@ -794,6 +804,11 @@
 
         boolean disableSystemTextClassifier = SystemProperties.getBoolean(
                 "config.disable_systemtextclassifier", false);
+
+        //TODO(b/111276913): temporarily disabled until the manager is properly implemented to
+        // ignore events when disabled and buffer when enabled
+        boolean disableIntelligence = SystemProperties.getBoolean(
+                "config.disable_intelligence", true);
         boolean disableNetworkTime = SystemProperties.getBoolean("config.disable_networktime",
                 false);
         boolean disableCameraService = SystemProperties.getBoolean("config.disable_cameraservice",
@@ -806,6 +821,9 @@
         boolean isWatch = context.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_WATCH);
 
+        boolean isArc = context.getPackageManager().hasSystemFeature(
+                "org.chromium.arc");
+
         boolean enableVrService = context.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
 
@@ -916,7 +934,7 @@
             ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
             mSensorServiceStart = null;
             wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
-                    new PhoneWindowManager());
+                    new PhoneWindowManager(), mWindowManagerGlobalLock);
             ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                     DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
             ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
@@ -966,7 +984,7 @@
             } else if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                 Slog.i(TAG, "No Bluetooth Service (factory test)");
             } else if (!context.getPackageManager().hasSystemFeature
-                       (PackageManager.FEATURE_BLUETOOTH)) {
+                    (PackageManager.FEATURE_BLUETOOTH)) {
                 Slog.i(TAG, "No Bluetooth Service (Bluetooth Hardware Not Present)");
             } else {
                 traceBeginAndSlog("StartBluetoothService");
@@ -1000,7 +1018,12 @@
         // Bring up services needed for UI.
         if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
             traceBeginAndSlog("StartInputMethodManagerLifecycle");
-            mSystemServiceManager.startService(InputMethodManagerService.Lifecycle.class);
+            if (MultiClientInputMethodManagerService.isConfiguredToUse()) {
+                mSystemServiceManager.startService(
+                        MultiClientInputMethodManagerService.Lifecycle.class);
+            } else {
+                mSystemServiceManager.startService(InputMethodManagerService.Lifecycle.class);
+            }
             traceEnd();
 
             traceBeginAndSlog("StartAccessibilityManagerService");
@@ -1075,7 +1098,7 @@
             try {
                 mSystemServiceManager.startService(LOCK_SETTINGS_SERVICE_CLASS);
                 lockSettings = ILockSettings.Stub.asInterface(
-                    ServiceManager.getService("lock_settings"));
+                        ServiceManager.getService("lock_settings"));
             } catch (Throwable e) {
                 reportWtf("starting LockSettingsService service", e);
             }
@@ -1116,6 +1139,15 @@
                 traceEnd();
             }
 
+            if (!disableIntelligence) {
+                traceBeginAndSlog("StartIntelligenceService");
+                mSystemServiceManager.startService(INTELLIGENCE_MANAGER_SERVICE_CLASS);
+                traceEnd();
+            } else {
+                Slog.d(TAG, "IntelligenceService disabled");
+            }
+
+            // NOTE: ClipboardService indirectly depends on IntelligenceService
             traceBeginAndSlog("StartClipboardService");
             mSystemServiceManager.startService(ClipboardService.class);
             traceEnd();
@@ -1144,7 +1176,8 @@
 
             if (!disableSystemTextClassifier) {
                 traceBeginAndSlog("StartTextClassificationManagerService");
-                mSystemServiceManager.startService(TextClassificationManagerService.Lifecycle.class);
+                mSystemServiceManager
+                        .startService(TextClassificationManagerService.Lifecycle.class);
                 traceEnd();
             }
 
@@ -1173,41 +1206,41 @@
 
             if (!mOnlyCore) {
                 if (context.getPackageManager().hasSystemFeature(
-                            PackageManager.FEATURE_WIFI)) {
+                        PackageManager.FEATURE_WIFI)) {
                     // Wifi Service must be started first for wifi-related services.
                     traceBeginAndSlog("StartWifi");
                     mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
                     traceEnd();
                     traceBeginAndSlog("StartWifiScanning");
                     mSystemServiceManager.startService(
-                        "com.android.server.wifi.scanner.WifiScanningService");
+                            "com.android.server.wifi.scanner.WifiScanningService");
                     traceEnd();
                 }
 
                 if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_WIFI_RTT)) {
+                        PackageManager.FEATURE_WIFI_RTT)) {
                     traceBeginAndSlog("StartRttService");
                     mSystemServiceManager.startService(
-                        "com.android.server.wifi.rtt.RttService");
+                            "com.android.server.wifi.rtt.RttService");
                     traceEnd();
                 }
 
                 if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_WIFI_AWARE)) {
+                        PackageManager.FEATURE_WIFI_AWARE)) {
                     traceBeginAndSlog("StartWifiAware");
                     mSystemServiceManager.startService(WIFI_AWARE_SERVICE_CLASS);
                     traceEnd();
                 }
 
                 if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_WIFI_DIRECT)) {
+                        PackageManager.FEATURE_WIFI_DIRECT)) {
                     traceBeginAndSlog("StartWifiP2P");
                     mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
                     traceEnd();
                 }
 
                 if (context.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_LOWPAN)) {
+                        PackageManager.FEATURE_LOWPAN)) {
                     traceBeginAndSlog("StartLowpan");
                     mSystemServiceManager.startService(LOWPAN_SERVICE_CLASS);
                     traceEnd();
@@ -1215,7 +1248,7 @@
             }
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
-                mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
+                    mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
                 traceBeginAndSlog("StartEthernet");
                 mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
                 traceEnd();
@@ -1224,10 +1257,10 @@
             traceBeginAndSlog("StartConnectivityService");
             try {
                 connectivity = new ConnectivityService(
-                    context, networkManagement, networkStats, networkPolicy);
+                        context, networkManagement, networkStats, networkPolicy);
                 ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity,
-                            /* allowIsolated= */ false,
-                    DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+                        /* allowIsolated= */ false,
+                        DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
                 networkStats.bindConnectivityManager(connectivity);
                 networkPolicy.bindConnectivityManager(connectivity);
             } catch (Throwable e) {
@@ -1239,7 +1272,7 @@
             try {
                 serviceDiscovery = NsdService.create(context);
                 ServiceManager.addService(
-                    Context.NSD_SERVICE, serviceDiscovery);
+                        Context.NSD_SERVICE, serviceDiscovery);
             } catch (Throwable e) {
                 reportWtf("starting Service Discovery Service", e);
             }
@@ -1257,7 +1290,7 @@
             traceBeginAndSlog("StartUpdateLockService");
             try {
                 ServiceManager.addService(Context.UPDATE_LOCK_SERVICE,
-                    new UpdateLockService(context));
+                        new UpdateLockService(context));
             } catch (Throwable e) {
                 reportWtf("starting UpdateLockService", e);
             }
@@ -1328,7 +1361,17 @@
             }
 
             traceBeginAndSlog("StartAudioService");
-            mSystemServiceManager.startService(AudioService.Lifecycle.class);
+            if (!isArc) {
+                mSystemServiceManager.startService(AudioService.Lifecycle.class);
+            } else {
+                String className = context.getResources()
+                        .getString(R.string.config_deviceSpecificAudioService);
+                try {
+                    mSystemServiceManager.startService(className + "$Lifecycle");
+                } catch (Throwable e) {
+                    reportWtf("starting " + className, e);
+                }
+            }
             traceEnd();
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_BROADCAST_RADIO)) {
@@ -1365,9 +1408,9 @@
             }
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)
-                || mPackageManager.hasSystemFeature(
-                PackageManager.FEATURE_USB_ACCESSORY)
-                || isEmulator) {
+                    || mPackageManager.hasSystemFeature(
+                    PackageManager.FEATURE_USB_ACCESSORY)
+                    || isEmulator) {
                 // Manage USB host and device support
                 traceBeginAndSlog("StartUsbService");
                 mSystemServiceManager.startService(USB_SERVICE_CLASS);
@@ -1399,7 +1442,7 @@
             try {
                 hardwarePropertiesService = new HardwarePropertiesManagerService(context);
                 ServiceManager.addService(Context.HARDWARE_PROPERTIES_SERVICE,
-                    hardwarePropertiesService);
+                        hardwarePropertiesService);
             } catch (Throwable e) {
                 Slog.e(TAG, "Failure starting HardwarePropertiesManagerService", e);
             }
@@ -1409,8 +1452,8 @@
             mSystemServiceManager.startService(TwilightService.class);
             traceEnd();
 
-            if (ColorDisplayController.isAvailable(context)) {
-                traceBeginAndSlog("StartNightDisplay");
+            if (ColorDisplayManager.isNightDisplayAvailable(context)) {
+                traceBeginAndSlog("StartColorDisplay");
                 mSystemServiceManager.startService(ColorDisplayService.class);
                 traceEnd();
             }
@@ -1434,7 +1477,7 @@
             }
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)
-                || context.getResources().getBoolean(R.bool.config_enableAppWidgetService)) {
+                    || context.getResources().getBoolean(R.bool.config_enableAppWidgetService)) {
                 traceBeginAndSlog("StartAppWidgetService");
                 mSystemServiceManager.startService(APPWIDGET_SERVICE_CLASS);
                 traceEnd();
@@ -1520,7 +1563,7 @@
 
             traceBeginAndSlog("AddGraphicsStatsService");
             ServiceManager.addService(GraphicsStatsService.GRAPHICS_STATS_SERVICE,
-                new GraphicsStatsService(context));
+                    new GraphicsStatsService(context));
             traceEnd();
 
             if (CoverageService.ENABLED) {
@@ -1589,6 +1632,8 @@
 
             final boolean hasFeatureFace
                     = mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE);
+            final boolean hasFeatureIris
+                    = mPackageManager.hasSystemFeature(PackageManager.FEATURE_IRIS);
             final boolean hasFeatureFingerprint
                     = mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT);
 
@@ -1598,15 +1643,21 @@
                 traceEnd();
             }
 
+            if (hasFeatureIris) {
+                traceBeginAndSlog("StartIrisSensor");
+                mSystemServiceManager.startService(IrisService.class);
+                traceEnd();
+            }
+
             if (hasFeatureFingerprint) {
                 traceBeginAndSlog("StartFingerprintSensor");
                 mSystemServiceManager.startService(FingerprintService.class);
                 traceEnd();
             }
 
-            if (hasFeatureFace || hasFeatureFingerprint) {
+            if (hasFeatureFace || hasFeatureIris || hasFeatureFingerprint) {
                 // Start this service after all biometric services.
-                traceBeginAndSlog("StartBiometricPromptService");
+                traceBeginAndSlog("StartBiometricService");
                 mSystemServiceManager.startService(BiometricService.class);
                 traceEnd();
             }
@@ -1778,7 +1829,7 @@
         // propagate to it.
         final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);
         DisplayMetrics metrics = new DisplayMetrics();
-        WindowManager w = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+        WindowManager w = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         w.getDefaultDisplay().getMetrics(metrics);
         context.getResources().updateConfiguration(config, metrics);
 
@@ -1865,6 +1916,11 @@
             }
             traceEnd();
 
+            // Grants default permissions and defines roles
+            traceBeginAndSlog("StartRoleManagerService");
+            mSystemServiceManager.startService(RoleManagerService.class);
+            traceEnd();
+
             // No dependency on Webview preparation in system server. But this should
             // be completed before allowing 3rd party
             final String WEBVIEW_PREPARATION = "WebViewFactoryPreparation";
@@ -1897,7 +1953,9 @@
             traceEnd();
             traceBeginAndSlog("MakeNetworkManagementServiceReady");
             try {
-                if (networkManagementF != null) networkManagementF.systemReady();
+                if (networkManagementF != null) {
+                    networkManagementF.systemReady();
+                }
             } catch (Throwable e) {
                 reportWtf("making Network Managment Service ready", e);
             }
@@ -1909,21 +1967,27 @@
             traceEnd();
             traceBeginAndSlog("MakeIpSecServiceReady");
             try {
-                if (ipSecServiceF != null) ipSecServiceF.systemReady();
+                if (ipSecServiceF != null) {
+                    ipSecServiceF.systemReady();
+                }
             } catch (Throwable e) {
                 reportWtf("making IpSec Service ready", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeNetworkStatsServiceReady");
             try {
-                if (networkStatsF != null) networkStatsF.systemReady();
+                if (networkStatsF != null) {
+                    networkStatsF.systemReady();
+                }
             } catch (Throwable e) {
                 reportWtf("making Network Stats Service ready", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeConnectivityServiceReady");
             try {
-                if (connectivityF != null) connectivityF.systemReady();
+                if (connectivityF != null) {
+                    connectivityF.systemReady();
+                }
             } catch (Throwable e) {
                 reportWtf("making Connectivity Service ready", e);
             }
@@ -1958,21 +2022,27 @@
 
             traceBeginAndSlog("MakeLocationServiceReady");
             try {
-                if (locationF != null) locationF.systemRunning();
+                if (locationF != null) {
+                    locationF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying Location Service running", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeCountryDetectionServiceReady");
             try {
-                if (countryDetectorF != null) countryDetectorF.systemRunning();
+                if (countryDetectorF != null) {
+                    countryDetectorF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying CountryDetectorService running", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeNetworkTimeUpdateReady");
             try {
-                if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
+                if (networkTimeUpdaterF != null) {
+                    networkTimeUpdaterF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying NetworkTimeService running", e);
             }
@@ -1980,28 +2050,36 @@
             traceBeginAndSlog("MakeInputManagerServiceReady");
             try {
                 // TODO(BT) Pass parameter to input manager
-                if (inputManagerF != null) inputManagerF.systemRunning();
+                if (inputManagerF != null) {
+                    inputManagerF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying InputManagerService running", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeTelephonyRegistryReady");
             try {
-                if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
+                if (telephonyRegistryF != null) {
+                    telephonyRegistryF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying TelephonyRegistry running", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeMediaRouterServiceReady");
             try {
-                if (mediaRouterF != null) mediaRouterF.systemRunning();
+                if (mediaRouterF != null) {
+                    mediaRouterF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying MediaRouterService running", e);
             }
             traceEnd();
             traceBeginAndSlog("MakeMmsServiceReady");
             try {
-                if (mmsServiceF != null) mmsServiceF.systemRunning();
+                if (mmsServiceF != null) {
+                    mmsServiceF.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying MmsService running", e);
             }
@@ -2013,7 +2091,9 @@
                 // in the build and should reliably be there.
                 final IIncidentManager incident = IIncidentManager.Stub.asInterface(
                         ServiceManager.getService(Context.INCIDENT_SERVICE));
-                if (incident != null) incident.systemRunning();
+                if (incident != null) {
+                    incident.systemRunning();
+                }
             } catch (Throwable e) {
                 reportWtf("Notifying incident daemon running", e);
             }
@@ -2024,7 +2104,7 @@
     static final void startSystemUi(Context context, WindowManagerService windowManager) {
         Intent intent = new Intent();
         intent.setComponent(new ComponentName("com.android.systemui",
-                    "com.android.systemui.SystemUIService"));
+                "com.android.systemui.SystemUIService"));
         intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
         //Slog.d(TAG, "Starting service: " + intent);
         context.startServiceAsUser(intent, UserHandle.SYSTEM);
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index e67f8d3..565152c 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -12,10 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-
-##############################################################
-# FrameworksServicesLib app just for Robolectric test target #
-##############################################################
+###################################################################
+# FrameworksServicesLib app just for Robolectric test target      #
+###################################################################
 LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
@@ -28,85 +27,56 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     services.backup \
-    services.core
+    services.core \
+    services.net
 
 include $(BUILD_PACKAGE)
 
-##############################################
-# FrameworksServices Robolectric test target #
-##############################################
+###################################################################
+# FrameworksServicesLib Robolectric test target.                  #
+###################################################################
 include $(CLEAR_VARS)
 
-# Dependency platform-robolectric-android-all-stubs below contains a bunch of Android classes as
-# stubs that throw RuntimeExceptions when we use them. The goal is to include hidden APIs that
-# weren't included in Robolectric's Android jar files. However, we are testing the framework itself
-# here, so if we write stuff that is being used in the tests and exist in
-# platform-robolectric-android-all-stubs, the class loader is going to pick up the latter, and thus
-# we are going to test what we don't want. To solve this:
-#
-#   1. If the class being used should be visible to bundled apps:
-#      => Bypass the stubs target by including them in LOCAL_SRC_FILES and LOCAL_AIDL_INCLUDES
-#         (if aidl).
-#
-#   2. If it's not visible:
-#      => Remove the class from the stubs jar (common/robolectric/android-all/android-all-stubs.jar)
-#         and add the class path to
-#         common/robolectric/android-all/android-all-stubs_removed_classes.txt.
-#
+LOCAL_MODULE := FrameworksServicesRoboTests
 
-INTERNAL_BACKUP := ../../core/java/com/android/internal/backup
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_SRC_FILES := \
-    $(call all-java-files-under, src) \
-    $(call all-Iaidl-files-under, $(INTERNAL_BACKUP)) \
-    $(call all-java-files-under, ../../core/java/android/app/backup) \
-    $(call all-Iaidl-files-under, ../../core/java/android/app/backup) \
-    $(call all-java-files-under, ../../core/java/android/util/proto) \
-    ../../core/java/android/content/pm/PackageInfo.java \
-    ../../core/java/android/app/IBackupAgent.aidl \
-    ../../core/java/android/util/KeyValueSettingObserver.java \
-    ../../core/java/android/content/pm/PackageParser.java \
-    ../../core/java/android/content/pm/SigningInfo.java
+LOCAL_RESOURCE_DIR := \
+    $(LOCAL_PATH)/res
 
-LOCAL_AIDL_INCLUDES := \
-    $(call all-Iaidl-files-under, $(INTERNAL_BACKUP)) \
-    $(call all-Iaidl-files-under, ../../core/java/android/app/backup) \
-    ../../core/java/android/app/IBackupAgent.aidl
+LOCAL_JAVA_RESOURCE_DIRS := config
 
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    platform-robolectric-android-all-stubs \
-    android-support-test \
-    guava \
-    mockito-robolectric-prebuilt \
+# Include the testing libraries
+LOCAL_JAVA_LIBRARIES := \
     platform-test-annotations \
+    robolectric_android-all-stub \
+    Robolectric_all-target \
+    mockito-robolectric-prebuilt \
     truth-prebuilt \
     testng
 
-LOCAL_JAVA_LIBRARIES := \
-    junit \
-    platform-robolectric-3.6.2-prebuilt
-
 LOCAL_INSTRUMENTATION_FOR := FrameworksServicesLib
-LOCAL_MODULE := FrameworksServicesRoboTests
 
 LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
-###############################################################
-# FrameworksServices runner target to run the previous target #
-###############################################################
+###################################################################
+# FrameworksServicesLib runner target to run the previous target. #
+###################################################################
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := RunFrameworksServicesRoboTests
 
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    FrameworksServicesRoboTests
+LOCAL_JAVA_LIBRARIES := \
+    FrameworksServicesRoboTests \
+    platform-test-annotations \
+    robolectric_android-all-stub \
+    Robolectric_all-target \
+    mockito-robolectric-prebuilt \
+    truth-prebuilt \
+    testng
 
 LOCAL_TEST_PACKAGE := FrameworksServicesLib
 
-LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))backup/java
-
-include prebuilts/misc/common/robolectric/3.6.2/run_robotests.mk
+include external/robolectric-shadows/run_robotests.mk
\ No newline at end of file
diff --git a/services/robotests/config/robolectric.properties b/services/robotests/config/robolectric.properties
new file mode 100644
index 0000000..850557a
--- /dev/null
+++ b/services/robotests/config/robolectric.properties
@@ -0,0 +1 @@
+sdk=NEWEST_SDK
\ No newline at end of file
diff --git a/services/robotests/src/android/app/backup/BackupUtilsTest.java b/services/robotests/src/android/app/backup/BackupUtilsTest.java
index 04a2a14..099cde0 100644
--- a/services/robotests/src/android/app/backup/BackupUtilsTest.java
+++ b/services/robotests/src/android/app/backup/BackupUtilsTest.java
@@ -22,14 +22,11 @@
 import android.content.Context;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 import org.robolectric.annotation.internal.DoNotInstrument;
 
 import java.io.File;
@@ -38,9 +35,7 @@
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"android.app.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 @DoNotInstrument
 public class BackupUtilsTest {
diff --git a/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java b/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java
index 0d2c221..5b226f3 100644
--- a/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupAgentTimeoutParametersTest.java
@@ -25,22 +25,16 @@
 import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import android.util.KeyValueSettingObserver;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 /** Tests for {@link BackupAgentTimeoutParameters}. */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
-@SystemLoaderClasses({KeyValueSettingObserver.class})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class BackupAgentTimeoutParametersTest {
     private ContentResolver mContentResolver;
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
index 2a32c2e..affa1f3 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerConstantsTest.java
@@ -23,21 +23,15 @@
 import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
-import android.util.KeyValueSettingObserver;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
-@SystemLoaderClasses({KeyValueSettingObserver.class})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class BackupManagerConstantsTest {
     private static final String PACKAGE_NAME = "some.package.name";
diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
index de915ab..c4cb593 100644
--- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -22,7 +22,9 @@
 import static com.android.server.backup.testing.TransportData.localTransport;
 import static com.android.server.backup.testing.TransportTestUtils.setUpCurrentTransport;
 import static com.android.server.backup.testing.TransportTestUtils.setUpTransports;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
@@ -45,24 +47,23 @@
 import android.os.PowerSaveState;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
+
 import com.android.server.backup.testing.BackupManagerServiceTestUtils;
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.TransportNotRegisteredException;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowAppBackupUtils;
 import com.android.server.testing.shadows.ShadowBinder;
 import com.android.server.testing.shadows.ShadowKeyValueBackupJob;
 import com.android.server.testing.shadows.ShadowKeyValueBackupTask;
-import java.io.File;
-import java.util.List;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.Implements;
@@ -71,9 +72,11 @@
 import org.robolectric.shadows.ShadowPackageManager;
 import org.robolectric.shadows.ShadowSettings;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26, shadows = {ShadowAppBackupUtils.class})
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.io.File;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowAppBackupUtils.class})
 @Presubmit
 public class BackupManagerServiceTest {
     private static final String TAG = "BMSTest";
diff --git a/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java b/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
index dd0a58d..8e17209 100644
--- a/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
+++ b/services/robotests/src/com/android/server/backup/KeyValueBackupJobTest.java
@@ -22,19 +22,14 @@
 import android.os.Handler;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class KeyValueBackupJobTest {
     private Context mContext;
diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
index 051a4a0..693092d 100644
--- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
@@ -56,17 +56,14 @@
 import com.android.server.backup.transport.TransportClient;
 import com.android.server.backup.transport.TransportClientManager;
 import com.android.server.backup.transport.TransportNotRegisteredException;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import com.android.server.testing.shadows.FrameworkShadowContextImpl;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowPackageManager;
 
 import java.util.ArrayList;
@@ -75,12 +72,7 @@
 import java.util.Set;
 import java.util.stream.Stream;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {FrameworkShadowContextImpl.class})
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class TransportManagerTest {
     private static final String PACKAGE_A = "some.package.a";
@@ -682,7 +674,7 @@
                     transport.getTransportComponent().getPackageName(),
                     ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
         }
-        setUpTransports(transportSet.toArray(new TransportData[transportSet.size()]));
+        setUpTransports(transportSet.toArray(new TransportData[0]));
         TransportManager transportManager = createTransportManager(selectedTransport, transports);
         transportManager.registerTransports();
         return transportManager;
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
index 3b6e038..3f57240 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
@@ -19,17 +19,16 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.primitives.Bytes;
-import java.util.Arrays;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkHashTest {
     private static final int HASH_LENGTH_BYTES = 256 / 8;
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java
index 383bf1d..4354db7 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkListingTest.java
@@ -21,22 +21,20 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
+
 import com.android.internal.util.Preconditions;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.base.Charsets;
-import java.io.ByteArrayInputStream;
-import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-// Include android.util.proto in addition to classes under test because the latest versions of
-// android.util.proto.Proto{Input|Output}Stream are not part of Robolectric.
-@SystemLoaderPackages({"com.android.server.backup", "android.util.proto"})
+import java.io.ByteArrayInputStream;
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkListingTest {
     private static final String CHUNK_A = "CHUNK_A";
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.java
index 1dd7dc8..17c9a86 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkTest.java
@@ -21,21 +21,18 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.base.Charsets;
-import java.io.ByteArrayInputStream;
-import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-// Include android.util.proto in addition to classes under test because the latest versions of
-// android.util.proto.Proto{Input|Output}Stream are not part of Robolectric.
-@SystemLoaderPackages({"com.android.server.backup", "android.util.proto"})
+import java.io.ByteArrayInputStream;
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkTest {
     private static final String CHUNK_A = "CHUNK_A";
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java
index 1cd1528..0bf1417 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java
@@ -19,16 +19,14 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.primitives.Bytes;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class EncryptedChunkOrderingTest {
     private static final byte[] TEST_BYTE_ARRAY_1 = new byte[] {1, 2, 3, 4, 5};
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java
index 2cc3ef8..d0e5fb3 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java
@@ -17,32 +17,35 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.android.server.backup.testing.CryptoTestUtils.generateAesKey;
+
 import static com.google.common.truth.Truth.assertThat;
-import static java.nio.charset.StandardCharsets.UTF_8;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import java.security.SecureRandom;
-import javax.crypto.Cipher;
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.GCMParameterSpec;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.security.SecureRandom;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkEncryptorTest {
     private static final String MAC_ALGORITHM = "HmacSHA256";
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java
index 11796c0..2bbbf28 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java
@@ -19,20 +19,19 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ChunkHasherTest {
     private static final String KEY_ALGORITHM = "AES";
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java
index c5f9b10..8e801a1 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java
@@ -17,21 +17,22 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.testng.Assert.assertThrows;
 
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.primitives.Bytes;
-import java.util.Arrays;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class EncryptedChunkTest {
     private static final byte[] CHUNK_HASH_1_BYTES =
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java
index b162557..2f872be 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java
@@ -17,25 +17,25 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
 import com.android.server.backup.encryption.chunk.ChunksMetadataProto;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InOrder;
 import org.mockito.Mock;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class InlineLengthsEncryptedChunkEncoderTest {
 
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java
index b61dbe9..978bddb 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java
@@ -17,25 +17,25 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 
 import android.platform.test.annotations.Presubmit;
+
 import com.android.server.backup.encryption.chunk.ChunkHash;
 import com.android.server.backup.encryption.chunk.ChunksMetadataProto;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-import java.util.Arrays;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InOrder;
 import org.mockito.Mock;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.util.Arrays;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class LengthlessEncryptedChunkEncoderTest {
     private static final byte[] TEST_NONCE =
@@ -74,7 +74,7 @@
     }
 
     @Test
-    public void getChunkOrderingType_returnsExplicitStartsType() throws Exception {
+    public void getChunkOrderingType_returnsExplicitStartsType() {
         assertThat(mEncoder.getChunkOrderingType()).isEqualTo(ChunksMetadataProto.EXPLICIT_STARTS);
     }
 }
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java
index 8b54e1e..19ef8fb 100644
--- a/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java
@@ -17,23 +17,23 @@
 package com.android.server.backup.encryption.chunking;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.testng.Assert.assertThrows;
 
 import android.platform.test.annotations.Presubmit;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
+
 import com.google.common.primitives.Bytes;
-import java.io.ByteArrayOutputStream;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+import java.io.ByteArrayOutputStream;
+
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class RawBackupWriterTest {
     private static final byte[] TEST_BYTES = {1, 2, 3, 4, 5, 6};
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java
new file mode 100644
index 0000000..77b7347
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.android.server.backup.testing.CryptoTestUtils.generateAesKey;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Random;
+
+import javax.crypto.SecretKey;
+
+/** Tests for {@link ContentDefinedChunker}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class ContentDefinedChunkerTest {
+    private static final int WINDOW_SIZE_BYTES = 31;
+    private static final int MIN_SIZE_BYTES = 40;
+    private static final int MAX_SIZE_BYTES = 300;
+    private static final String CHUNK_BOUNDARY = "<----------BOUNDARY----------->";
+    private static final byte[] CHUNK_BOUNDARY_BYTES = CHUNK_BOUNDARY.getBytes(UTF_8);
+    private static final String CHUNK_1 = "This is the first chunk";
+    private static final String CHUNK_2 = "And this is the second chunk";
+    private static final String CHUNK_3 = "And finally here is the third chunk";
+    private static final String SMALL_CHUNK = "12345678";
+
+    private FingerprintMixer mFingerprintMixer;
+    private RabinFingerprint64 mRabinFingerprint64;
+    private ContentDefinedChunker mChunker;
+
+    /** Set up a {@link ContentDefinedChunker} and dependencies for use in the tests. */
+    @Before
+    public void setUp() throws Exception {
+        SecretKey secretKey = generateAesKey();
+        byte[] salt = new byte[FingerprintMixer.SALT_LENGTH_BYTES];
+        Random random = new Random();
+        random.nextBytes(salt);
+        mFingerprintMixer = new FingerprintMixer(secretKey, salt);
+
+        mRabinFingerprint64 = new RabinFingerprint64();
+        long chunkBoundaryFingerprint = calculateFingerprint(CHUNK_BOUNDARY_BYTES);
+        mChunker =
+                new ContentDefinedChunker(
+                        MIN_SIZE_BYTES,
+                        MAX_SIZE_BYTES,
+                        mRabinFingerprint64,
+                        mFingerprintMixer,
+                        (fingerprint) -> fingerprint == chunkBoundaryFingerprint);
+    }
+
+    /**
+     * Creating a {@link ContentDefinedChunker} with a minimum chunk size that is smaller than the
+     * window size should throw an {@link IllegalArgumentException}.
+     */
+    @Test
+    public void create_withMinChunkSizeSmallerThanWindowSize_throwsIllegalArgumentException() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () ->
+                        new ContentDefinedChunker(
+                                WINDOW_SIZE_BYTES - 1,
+                                MAX_SIZE_BYTES,
+                                mRabinFingerprint64,
+                                mFingerprintMixer,
+                                null));
+    }
+
+    /**
+     * Creating a {@link ContentDefinedChunker} with a maximum chunk size that is smaller than the
+     * minimum chunk size should throw an {@link IllegalArgumentException}.
+     */
+    @Test
+    public void create_withMaxChunkSizeSmallerThanMinChunkSize_throwsIllegalArgumentException() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () ->
+                        new ContentDefinedChunker(
+                                MIN_SIZE_BYTES,
+                                MIN_SIZE_BYTES - 1,
+                                mRabinFingerprint64,
+                                mFingerprintMixer,
+                                null));
+    }
+
+    /**
+     * {@link ContentDefinedChunker#chunkify(InputStream, Chunker.ChunkConsumer)} should split the
+     * input stream across chunk boundaries by default.
+     */
+    @Test
+    public void chunkify_withLargeChunks_splitsIntoChunksAcrossBoundaries() throws Exception {
+        byte[] input =
+                (CHUNK_1 + CHUNK_BOUNDARY + CHUNK_2 + CHUNK_BOUNDARY + CHUNK_3).getBytes(UTF_8);
+        ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
+        ArrayList<String> result = new ArrayList<>();
+
+        mChunker.chunkify(inputStream, (chunk) -> result.add(new String(chunk, UTF_8)));
+
+        assertThat(result)
+                .containsExactly(CHUNK_1 + CHUNK_BOUNDARY, CHUNK_2 + CHUNK_BOUNDARY, CHUNK_3)
+                .inOrder();
+    }
+
+    /** Chunks should be combined across boundaries until they reach the minimum chunk size. */
+    @Test
+    public void chunkify_withSmallChunks_combinesChunksUntilMinSize() throws Exception {
+        byte[] input =
+                (SMALL_CHUNK + CHUNK_BOUNDARY + CHUNK_2 + CHUNK_BOUNDARY + CHUNK_3).getBytes(UTF_8);
+        ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
+        ArrayList<String> result = new ArrayList<>();
+
+        mChunker.chunkify(inputStream, (chunk) -> result.add(new String(chunk, UTF_8)));
+
+        assertThat(result)
+                .containsExactly(SMALL_CHUNK + CHUNK_BOUNDARY + CHUNK_2 + CHUNK_BOUNDARY, CHUNK_3)
+                .inOrder();
+        assertThat(result.get(0).length()).isAtLeast(MIN_SIZE_BYTES);
+    }
+
+    /** Chunks can not be larger than the maximum chunk size. */
+    @Test
+    public void chunkify_doesNotProduceChunksLargerThanMaxSize() throws Exception {
+        byte[] largeInput = new byte[MAX_SIZE_BYTES * 10];
+        Arrays.fill(largeInput, "a".getBytes(UTF_8)[0]);
+        ByteArrayInputStream inputStream = new ByteArrayInputStream(largeInput);
+        ArrayList<String> result = new ArrayList<>();
+
+        mChunker.chunkify(inputStream, (chunk) -> result.add(new String(chunk, UTF_8)));
+
+        byte[] expectedChunkBytes = new byte[MAX_SIZE_BYTES];
+        Arrays.fill(expectedChunkBytes, "a".getBytes(UTF_8)[0]);
+        String expectedChunk = new String(expectedChunkBytes, UTF_8);
+        assertThat(result)
+                .containsExactly(
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk,
+                        expectedChunk)
+                .inOrder();
+    }
+
+    /**
+     * If the input stream signals zero availablility, {@link
+     * ContentDefinedChunker#chunkify(InputStream, Chunker.ChunkConsumer)} should still work.
+     */
+    @Test
+    public void chunkify_withInputStreamReturningZeroAvailability_returnsChunks() throws Exception {
+        byte[] input = (SMALL_CHUNK + CHUNK_BOUNDARY + CHUNK_2).getBytes(UTF_8);
+        ZeroAvailabilityInputStream zeroAvailabilityInputStream =
+                new ZeroAvailabilityInputStream(input);
+        ArrayList<String> result = new ArrayList<>();
+
+        mChunker.chunkify(
+                zeroAvailabilityInputStream, (chunk) -> result.add(new String(chunk, UTF_8)));
+
+        assertThat(result).containsExactly(SMALL_CHUNK + CHUNK_BOUNDARY + CHUNK_2).inOrder();
+    }
+
+    /**
+     * {@link ContentDefinedChunker#chunkify(InputStream, Chunker.ChunkConsumer)} should rethrow any
+     * exception thrown by its consumer.
+     */
+    @Test
+    public void chunkify_whenConsumerThrowsException_rethrowsException() throws Exception {
+        ByteArrayInputStream inputStream = new ByteArrayInputStream(new byte[] {1});
+
+        assertThrows(
+                GeneralSecurityException.class,
+                () ->
+                        mChunker.chunkify(
+                                inputStream,
+                                (chunk) -> {
+                                    throw new GeneralSecurityException();
+                                }));
+    }
+
+    private long calculateFingerprint(byte[] bytes) {
+        long fingerprint = 0;
+        for (byte inByte : bytes) {
+            fingerprint =
+                    mRabinFingerprint64.computeFingerprint64(
+                            /*inChar=*/ inByte, /*outChar=*/ (byte) 0, fingerprint);
+        }
+        return mFingerprintMixer.mix(fingerprint);
+    }
+
+    private static class ZeroAvailabilityInputStream extends ByteArrayInputStream {
+        ZeroAvailabilityInputStream(byte[] wrapped) {
+            super(wrapped);
+        }
+
+        @Override
+        public synchronized int available() {
+            return 0;
+        }
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java
new file mode 100644
index 0000000..936b5dc
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.util.HashSet;
+import java.util.Random;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+/** Tests for {@link FingerprintMixer}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class FingerprintMixerTest {
+    private static final String KEY_ALGORITHM = "AES";
+    private static final int SEED = 42;
+    private static final int SALT_LENGTH_BYTES = 256 / 8;
+    private static final int KEY_SIZE_BITS = 256;
+
+    private Random mSeededRandom;
+    private FingerprintMixer mFingerprintMixer;
+
+    /** Set up a {@link FingerprintMixer} with deterministic key and salt generation. */
+    @Before
+    public void setUp() throws Exception {
+        // Seed so that the tests are deterministic.
+        mSeededRandom = new Random(SEED);
+        mFingerprintMixer = new FingerprintMixer(randomKey(), randomSalt());
+    }
+
+    /**
+     * Construcing a {@link FingerprintMixer} with a salt that is too small should throw an {@link
+     * IllegalArgumentException}.
+     */
+    @Test
+    public void create_withIncorrectSaltSize_throwsIllegalArgumentException() {
+        byte[] tooSmallSalt = new byte[SALT_LENGTH_BYTES - 1];
+
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> new FingerprintMixer(randomKey(), tooSmallSalt));
+    }
+
+    /**
+     * Constructing a {@link FingerprintMixer} with a secret key that can't be encoded should throw
+     * an {@link InvalidKeyException}.
+     */
+    @Test
+    public void create_withUnencodableSecretKey_throwsInvalidKeyException() {
+        byte[] keyBytes = new byte[KEY_SIZE_BITS / 8];
+        UnencodableSecretKeySpec keySpec =
+                new UnencodableSecretKeySpec(keyBytes, 0, keyBytes.length, KEY_ALGORITHM);
+
+        assertThrows(InvalidKeyException.class, () -> new FingerprintMixer(keySpec, randomSalt()));
+    }
+
+    /**
+     * {@link FingerprintMixer#getAddend()} should not return the same addend for two different
+     * keys.
+     */
+    @Test
+    public void getAddend_withDifferentKey_returnsDifferentResult() throws Exception {
+        int iterations = 100_000;
+        HashSet<Long> returnedAddends = new HashSet<>();
+        byte[] salt = randomSalt();
+
+        for (int i = 0; i < iterations; i++) {
+            FingerprintMixer fingerprintMixer = new FingerprintMixer(randomKey(), salt);
+            long addend = fingerprintMixer.getAddend();
+            returnedAddends.add(addend);
+        }
+
+        assertThat(returnedAddends).containsNoDuplicates();
+    }
+
+    /**
+     * {@link FingerprintMixer#getMultiplicand()} should not return the same multiplicand for two
+     * different keys.
+     */
+    @Test
+    public void getMultiplicand_withDifferentKey_returnsDifferentResult() throws Exception {
+        int iterations = 100_000;
+        HashSet<Long> returnedMultiplicands = new HashSet<>();
+        byte[] salt = randomSalt();
+
+        for (int i = 0; i < iterations; i++) {
+            FingerprintMixer fingerprintMixer = new FingerprintMixer(randomKey(), salt);
+            long multiplicand = fingerprintMixer.getMultiplicand();
+            returnedMultiplicands.add(multiplicand);
+        }
+
+        assertThat(returnedMultiplicands).containsNoDuplicates();
+    }
+
+    /** The multiplicant returned by {@link FingerprintMixer} should always be odd. */
+    @Test
+    public void getMultiplicand_isOdd() throws Exception {
+        int iterations = 100_000;
+
+        for (int i = 0; i < iterations; i++) {
+            FingerprintMixer fingerprintMixer = new FingerprintMixer(randomKey(), randomSalt());
+
+            long multiplicand = fingerprintMixer.getMultiplicand();
+
+            assertThat(isOdd(multiplicand)).isTrue();
+        }
+    }
+
+    /** {@link FingerprintMixer#mix(long)} should have a random distribution. */
+    @Test
+    public void mix_randomlyDistributesBits() throws Exception {
+        int iterations = 100_000;
+        float tolerance = 0.1f;
+        int[] totals = new int[64];
+
+        for (int i = 0; i < iterations; i++) {
+            long n = mFingerprintMixer.mix(mSeededRandom.nextLong());
+            for (int j = 0; j < 64; j++) {
+                int bit = (int) (n >> j & 1);
+                totals[j] += bit;
+            }
+        }
+
+        for (int i = 0; i < 64; i++) {
+            float mean = ((float) totals[i]) / iterations;
+            float diff = Math.abs(mean - 0.5f);
+            assertThat(diff).isLessThan(tolerance);
+        }
+    }
+
+    /**
+     * {@link FingerprintMixer#mix(long)} should always produce a number that's different from the
+     * input.
+     */
+    @Test
+    public void mix_doesNotProduceSameNumberAsInput() {
+        int iterations = 100_000;
+
+        for (int i = 0; i < iterations; i++) {
+            assertThat(mFingerprintMixer.mix(i)).isNotEqualTo(i);
+        }
+    }
+
+    private byte[] randomSalt() {
+        byte[] salt = new byte[SALT_LENGTH_BYTES];
+        mSeededRandom.nextBytes(salt);
+        return salt;
+    }
+
+    /**
+     * Not a secure way of generating keys. We want to deterministically generate the same keys for
+     * each test run, though, to ensure the test is deterministic.
+     */
+    private SecretKey randomKey() {
+        byte[] keyBytes = new byte[KEY_SIZE_BITS / 8];
+        mSeededRandom.nextBytes(keyBytes);
+        return new SecretKeySpec(keyBytes, 0, keyBytes.length, KEY_ALGORITHM);
+    }
+
+    private static boolean isOdd(long n) {
+        return Math.abs(n % 2) == 1;
+    }
+
+    /**
+     * Subclass of {@link SecretKeySpec} that does not provide an encoded version. As per its
+     * contract in {@link Key}, that means {@code getEncoded()} always returns null.
+     */
+    private class UnencodableSecretKeySpec extends SecretKeySpec {
+        UnencodableSecretKeySpec(byte[] key, int offset, int len, String algorithm) {
+            super(key, offset, len, algorithm);
+        }
+
+        @Override
+        public byte[] getEncoded() {
+            return null;
+        }
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java
new file mode 100644
index 0000000..5494374
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+/** Tests for {@link Hkdf}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class HkdfTest {
+    /** HKDF Test Case 1 IKM from RFC 5869 */
+    private static final byte[] HKDF_CASE1_IKM = {
+        0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+        0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+        0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+        0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+        0x0b, 0x0b
+    };
+
+    /** HKDF Test Case 1 salt from RFC 5869 */
+    private static final byte[] HKDF_CASE1_SALT = {
+        0x00, 0x01, 0x02, 0x03, 0x04,
+        0x05, 0x06, 0x07, 0x08, 0x09,
+        0x0a, 0x0b, 0x0c
+    };
+
+    /** HKDF Test Case 1 info from RFC 5869 */
+    private static final byte[] HKDF_CASE1_INFO = {
+        (byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, (byte) 0xf4,
+        (byte) 0xf5, (byte) 0xf6, (byte) 0xf7, (byte) 0xf8, (byte) 0xf9
+    };
+
+    /** First 32 bytes of HKDF Test Case 1 OKM (output) from RFC 5869 */
+    private static final byte[] HKDF_CASE1_OKM = {
+        (byte) 0x3c, (byte) 0xb2, (byte) 0x5f, (byte) 0x25, (byte) 0xfa,
+        (byte) 0xac, (byte) 0xd5, (byte) 0x7a, (byte) 0x90, (byte) 0x43,
+        (byte) 0x4f, (byte) 0x64, (byte) 0xd0, (byte) 0x36, (byte) 0x2f,
+        (byte) 0x2a, (byte) 0x2d, (byte) 0x2d, (byte) 0x0a, (byte) 0x90,
+        (byte) 0xcf, (byte) 0x1a, (byte) 0x5a, (byte) 0x4c, (byte) 0x5d,
+        (byte) 0xb0, (byte) 0x2d, (byte) 0x56, (byte) 0xec, (byte) 0xc4,
+        (byte) 0xc5, (byte) 0xbf
+    };
+
+    /** Test the example from RFC 5869. */
+    @Test
+    public void hkdf_derivesKeyMaterial() throws Exception {
+        byte[] result = Hkdf.hkdf(HKDF_CASE1_IKM, HKDF_CASE1_SALT, HKDF_CASE1_INFO);
+
+        assertThat(result).isEqualTo(HKDF_CASE1_OKM);
+    }
+
+    /** Providing a key that is null should throw a {@link java.lang.NullPointerException}. */
+    @Test
+    public void hkdf_withNullKey_throwsNullPointerException() throws Exception {
+        assertThrows(
+                NullPointerException.class,
+                () -> Hkdf.hkdf(null, HKDF_CASE1_SALT, HKDF_CASE1_INFO));
+    }
+
+    /** Providing a salt that is null should throw a {@link java.lang.NullPointerException}. */
+    @Test
+    public void hkdf_withNullSalt_throwsNullPointerException() throws Exception {
+        assertThrows(
+                NullPointerException.class, () -> Hkdf.hkdf(HKDF_CASE1_IKM, null, HKDF_CASE1_INFO));
+    }
+
+    /** Providing data that is null should throw a {@link java.lang.NullPointerException}. */
+    @Test
+    public void hkdf_withNullData_throwsNullPointerException() throws Exception {
+        assertThrows(
+                NullPointerException.class, () -> Hkdf.hkdf(HKDF_CASE1_IKM, HKDF_CASE1_SALT, null));
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java
new file mode 100644
index 0000000..277dc37
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.Random;
+
+/** Tests for {@link IsChunkBreakpoint}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class IsChunkBreakpointTest {
+    private static final int RANDOM_SEED = 42;
+    private static final double TOLERANCE = 0.01;
+    private static final int NUMBER_OF_TESTS = 10000;
+    private static final int BITS_PER_LONG = 64;
+
+    private Random mRandom;
+
+    /** Make sure that tests are deterministic. */
+    @Before
+    public void setUp() {
+        mRandom = new Random(RANDOM_SEED);
+    }
+
+    /**
+     * Providing a negative average number of trials should throw an {@link
+     * IllegalArgumentException}.
+     */
+    @Test
+    public void create_withNegativeAverageNumberOfTrials_throwsIllegalArgumentException() {
+        assertThrows(IllegalArgumentException.class, () -> new IsChunkBreakpoint(-1));
+    }
+
+    // Note: the following three tests are compute-intensive, so be cautious adding more.
+
+    /**
+     * If the provided average number of trials is zero, a breakpoint should be expected after one
+     * trial on average.
+     */
+    @Test
+    public void
+            isBreakpoint_withZeroAverageNumberOfTrials_isTrueOnAverageAfterOneTrial() {
+        assertExpectedTrials(new IsChunkBreakpoint(0), /*expectedTrials=*/ 1);
+    }
+
+    /**
+     * If the provided average number of trials is 512, a breakpoint should be expected after 512
+     * trials on average.
+     */
+    @Test
+    public void
+            isBreakpoint_with512AverageNumberOfTrials_isTrueOnAverageAfter512Trials() {
+        assertExpectedTrials(new IsChunkBreakpoint(512), /*expectedTrials=*/ 512);
+    }
+
+    /**
+     * If the provided average number of trials is 1024, a breakpoint should be expected after 1024
+     * trials on average.
+     */
+    @Test
+    public void
+            isBreakpoint_with1024AverageNumberOfTrials_isTrueOnAverageAfter1024Trials() {
+        assertExpectedTrials(new IsChunkBreakpoint(1024), /*expectedTrials=*/ 1024);
+    }
+
+    /** The number of leading zeros should be the logarithm of the average number of trials. */
+    @Test
+    public void getLeadingZeros_squaredIsAverageNumberOfTrials() {
+        for (int i = 0; i < BITS_PER_LONG; i++) {
+            long averageNumberOfTrials = (long) Math.pow(2, i);
+
+            int leadingZeros = new IsChunkBreakpoint(averageNumberOfTrials).getLeadingZeros();
+
+            assertThat(leadingZeros).isEqualTo(i);
+        }
+    }
+
+    private void assertExpectedTrials(IsChunkBreakpoint isChunkBreakpoint, long expectedTrials) {
+        long sum = 0;
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            sum += numberOfTrialsTillBreakpoint(isChunkBreakpoint);
+        }
+        long averageTrials = sum / NUMBER_OF_TESTS;
+        assertThat((double) Math.abs(averageTrials - expectedTrials))
+                .isLessThan(TOLERANCE * expectedTrials);
+    }
+
+    private int numberOfTrialsTillBreakpoint(IsChunkBreakpoint isChunkBreakpoint) {
+        int trials = 0;
+
+        while (true) {
+            trials++;
+            if (isChunkBreakpoint.isBreakpoint(mRandom.nextLong())) {
+                return trials;
+            }
+        }
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java
new file mode 100644
index 0000000..729580c
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2018 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.backup.encryption.chunking.cdc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.platform.test.annotations.Presubmit;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+/** Tests for {@link RabinFingerprint64}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class RabinFingerprint64Test {
+    private static final int WINDOW_SIZE = 31;
+    private static final ImmutableList<String> TEST_STRINGS =
+            ImmutableList.of(
+                    "ervHTtChYXO6eXivYqThlyyzqkbRaOR",
+                    "IxaVunH9ZC3qneWfhj1GkBH4ys9CYqz",
+                    "wZRVjlE1p976icCFPX9pibk4PEBvjSH",
+                    "pHIVaT8x8If9D6s9croksgNmJpmGYWI");
+
+    private final RabinFingerprint64 mRabinFingerprint64 = new RabinFingerprint64();
+
+    /**
+     * No matter where in the input buffer a string occurs, {@link
+     * RabinFingerprint64#computeFingerprint64(byte, byte, long)} should return the same
+     * fingerprint.
+     */
+    @Test
+    public void computeFingerprint64_forSameWindow_returnsSameFingerprint() {
+        long fingerprint1 =
+                computeFingerprintAtPosition(getBytes(TEST_STRINGS.get(0)), WINDOW_SIZE - 1);
+        long fingerprint2 =
+                computeFingerprintAtPosition(
+                        getBytes(TEST_STRINGS.get(1), TEST_STRINGS.get(0)), WINDOW_SIZE * 2 - 1);
+        long fingerprint3 =
+                computeFingerprintAtPosition(
+                        getBytes(TEST_STRINGS.get(2), TEST_STRINGS.get(3), TEST_STRINGS.get(0)),
+                        WINDOW_SIZE * 3 - 1);
+        String stub = "abc";
+        long fingerprint4 =
+                computeFingerprintAtPosition(
+                        getBytes(stub, TEST_STRINGS.get(0)), WINDOW_SIZE + stub.length() - 1);
+
+        // Assert that all fingerprints are exactly the same
+        assertThat(ImmutableSet.of(fingerprint1, fingerprint2, fingerprint3, fingerprint4))
+                .hasSize(1);
+    }
+
+    /** The computed fingerprint should be different for different inputs. */
+    @Test
+    public void computeFingerprint64_withDifferentInput_returnsDifferentFingerprint() {
+        long fingerprint1 = computeFingerprintOf(TEST_STRINGS.get(0));
+        long fingerprint2 = computeFingerprintOf(TEST_STRINGS.get(1));
+        long fingerprint3 = computeFingerprintOf(TEST_STRINGS.get(2));
+        long fingerprint4 = computeFingerprintOf(TEST_STRINGS.get(3));
+
+        assertThat(ImmutableList.of(fingerprint1, fingerprint2, fingerprint3, fingerprint4))
+                .containsNoDuplicates();
+    }
+
+    /**
+     * An input with the same characters in a different order should return a different fingerprint.
+     */
+    @Test
+    public void computeFingerprint64_withSameInputInDifferentOrder_returnsDifferentFingerprint() {
+        long fingerprint1 = computeFingerprintOf("abcdefghijklmnopqrstuvwxyz12345");
+        long fingerprint2 = computeFingerprintOf("54321zyxwvutsrqponmlkjihgfedcba");
+        long fingerprint3 = computeFingerprintOf("4bcdefghijklmnopqrstuvwxyz123a5");
+        long fingerprint4 = computeFingerprintOf("bacdefghijklmnopqrstuvwxyz12345");
+
+        assertThat(ImmutableList.of(fingerprint1, fingerprint2, fingerprint3, fingerprint4))
+                .containsNoDuplicates();
+    }
+
+    /** UTF-8 bytes of all the given strings in order. */
+    private byte[] getBytes(String... strings) {
+        StringBuilder sb = new StringBuilder();
+        for (String s : strings) {
+            sb.append(s);
+        }
+        return sb.toString().getBytes(UTF_8);
+    }
+
+    /**
+     * The Rabin fingerprint of a window of bytes ending at {@code position} in the {@code bytes}
+     * array.
+     */
+    private long computeFingerprintAtPosition(byte[] bytes, int position) {
+        assertThat(position).isAtMost(bytes.length - 1);
+        long fingerprint = 0;
+        for (int i = 0; i <= position; i++) {
+            byte outChar;
+            if (i >= WINDOW_SIZE) {
+                outChar = bytes[i - WINDOW_SIZE];
+            } else {
+                outChar = (byte) 0;
+            }
+            fingerprint =
+                    mRabinFingerprint64.computeFingerprint64(
+                            /*inChar=*/ bytes[i], outChar, fingerprint);
+        }
+        return fingerprint;
+    }
+
+    private long computeFingerprintOf(String s) {
+        assertThat(s.length()).isEqualTo(WINDOW_SIZE);
+        return computeFingerprintAtPosition(s.getBytes(UTF_8), WINDOW_SIZE - 1);
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java b/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
index b771039..fd7ced2 100644
--- a/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
+++ b/services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java
@@ -7,6 +7,7 @@
 import static com.android.server.backup.BackupManagerService.BACKUP_WIDGET_METADATA_TOKEN;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.robolectric.Shadows.shadowOf;
 import static org.testng.Assert.expectThrows;
 
@@ -21,17 +22,24 @@
 import android.content.pm.Signature;
 import android.content.pm.SigningInfo;
 import android.os.Build;
-import android.os.Build.VERSION_CODES;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowBackupDataInput;
 import com.android.server.testing.shadows.ShadowBackupDataOutput;
 import com.android.server.testing.shadows.ShadowFullBackup;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplicationPackageManager;
+import org.robolectric.shadows.ShadowEnvironment;
+
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.File;
@@ -41,32 +49,20 @@
 import java.nio.file.Files;
 import java.nio.file.attribute.FileTime;
 
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowApplicationPackageManager;
-import org.robolectric.shadows.ShadowEnvironment;
-
-@RunWith(FrameworkRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
 @Config(
-        manifest = Config.NONE,
-        sdk = 26,
         shadows = {
             ShadowBackupDataInput.class,
             ShadowBackupDataOutput.class,
             ShadowEnvironment.class,
             ShadowFullBackup.class,
         })
-@SystemLoaderPackages({"com.android.server.backup", "android.app.backup"})
-@SystemLoaderClasses({PackageInfo.class, SigningInfo.class})
 public class AppMetadataBackupWriterTest {
     private static final String TEST_PACKAGE = "com.test.package";
     private static final String TEST_PACKAGE_INSTALLER = "com.test.package.installer";
     private static final Long TEST_PACKAGE_VERSION_CODE = 100L;
 
+    private PackageManager mPackageManager;
     private ShadowApplicationPackageManager mShadowPackageManager;
     private File mFilesDir;
     private File mBackupDataOutputFile;
@@ -76,8 +72,8 @@
     public void setUp() throws Exception {
         Application application = RuntimeEnvironment.application;
 
-        PackageManager packageManager = application.getPackageManager();
-        mShadowPackageManager = (ShadowApplicationPackageManager) shadowOf(packageManager);
+        mPackageManager = application.getPackageManager();
+        mShadowPackageManager = (ShadowApplicationPackageManager) shadowOf(mPackageManager);
 
         mFilesDir = RuntimeEnvironment.application.getFilesDir();
         mBackupDataOutputFile = new File(mFilesDir, "output");
@@ -87,7 +83,7 @@
                         mBackupDataOutputFile, ParcelFileDescriptor.MODE_READ_WRITE);
         FullBackupDataOutput output =
                 new FullBackupDataOutput(pfd, /* quota */ -1, /* transportFlags */ 0);
-        mBackupWriter = new AppMetadataBackupWriter(output, packageManager);
+        mBackupWriter = new AppMetadataBackupWriter(output, mPackageManager);
     }
 
     @After
@@ -211,36 +207,6 @@
      *     N* (signature byte array in ascii format per Signature.toCharsString())
      * </pre>
      */
-    @Config(sdk = VERSION_CODES.O)
-    @Test
-    public void testBackupManifest_whenApiO_writesCorrectApi() throws Exception {
-        PackageInfo packageInfo =
-                createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
-        File manifestFile = createFile(BACKUP_MANIFEST_FILENAME);
-
-        mBackupWriter.backupManifest(packageInfo, manifestFile, mFilesDir, /* withApk */ false);
-
-        byte[] manifestBytes = getWrittenBytes(mBackupDataOutputFile, /* includeTarHeader */ false);
-        String[] manifest = new String(manifestBytes, StandardCharsets.UTF_8).split("\n");
-        assertThat(manifest.length).isEqualTo(7);
-        assertThat(manifest[3]).isEqualTo(Integer.toString(VERSION_CODES.O)); // platform version
-        manifestFile.delete();
-    }
-
-    /**
-     * The manifest format is:
-     *
-     * <pre>
-     *     BACKUP_MANIFEST_VERSION
-     *     package name
-     *     package version code
-     *     platform version code
-     *     installer package name (can be empty)
-     *     boolean (1 if archive includes .apk, otherwise 0)
-     *     # of signatures N
-     *     N* (signature byte array in ascii format per Signature.toCharsString())
-     * </pre>
-     */
     @Test
     public void testBackupManifest_withoutInstallerPackage_writesEmptyInstaller() throws Exception {
         PackageInfo packageInfo = createPackageInfo(TEST_PACKAGE, null, TEST_PACKAGE_VERSION_CODE);
@@ -394,7 +360,7 @@
     }
 
     @Test
-    public void testBackupObb_withNoObbData_doesNotWriteBytesToOutput() throws Exception {
+    public void testBackupObb_withNoObbData_doesNotWriteBytesToOutput() {
         PackageInfo packageInfo =
                 createPackageInfo(TEST_PACKAGE, TEST_PACKAGE_INSTALLER, TEST_PACKAGE_VERSION_CODE);
         File obbDir = createObbDirForPackage(packageInfo.packageName);
@@ -416,7 +382,7 @@
         packageInfo.setLongVersionCode(versionCode);
         mShadowPackageManager.addPackage(packageInfo);
         if (installerPackageName != null) {
-            mShadowPackageManager.setInstallerPackageName(packageName, installerPackageName);
+            mPackageManager.setInstallerPackageName(packageName, installerPackageName);
         }
         return packageInfo;
     }
diff --git a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
index 646367e..6ee6eb6 100644
--- a/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/internal/PerformInitializeTaskTest.java
@@ -46,20 +46,18 @@
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.backup.BackupManagerService;
 import com.android.server.backup.TransportManager;
-import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportData;
+import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.TransportClient;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowSlog;
 
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
@@ -69,9 +67,8 @@
 import java.util.List;
 import java.util.stream.Stream;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26, shadows = ShadowSlog.class)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowSlog.class)
 @Presubmit
 public class PerformInitializeTaskTest {
     @Mock private BackupManagerService mBackupManagerService;
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java b/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java
index 3730335..b00b922 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/AgentExceptionTest.java
@@ -20,29 +20,24 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.io.IOException;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class AgentExceptionTest {
     @Test
-    public void testTransitory_isTransitory() throws Exception {
+    public void testTransitory_isTransitory() {
         AgentException exception = AgentException.transitory();
 
         assertThat(exception.isTransitory()).isTrue();
     }
 
     @Test
-    public void testTransitory_withCause() throws Exception {
+    public void testTransitory_withCause() {
         Exception cause = new IOException();
 
         AgentException exception = AgentException.transitory(cause);
@@ -52,14 +47,14 @@
     }
 
     @Test
-    public void testPermanent_isNotTransitory() throws Exception {
+    public void testPermanent_isNotTransitory() {
         AgentException exception = AgentException.permanent();
 
         assertThat(exception.isTransitory()).isFalse();
     }
 
     @Test
-    public void testPermanent_withCause() throws Exception {
+    public void testPermanent_withCause() {
         Exception cause = new IOException();
 
         AgentException exception = AgentException.permanent(cause);
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java b/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java
index 5ea74f1..d5603d6 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/BackupExceptionTest.java
@@ -20,18 +20,13 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.io.IOException;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class BackupExceptionTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java
index 31e8333..a0afb5e 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupReporterTest.java
@@ -27,9 +27,6 @@
 import android.util.Log;
 
 import com.android.server.backup.BackupManagerService;
-import com.android.server.backup.remote.RemoteResult;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowEventLog;
 import com.android.server.testing.shadows.ShadowSlog;
 
@@ -37,17 +34,11 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowLog;
 
-import java.lang.reflect.Field;
-
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {ShadowEventLog.class, ShadowSlog.class})
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowEventLog.class, ShadowSlog.class})
 @Presubmit
 public class KeyValueBackupReporterTest {
     @Mock private BackupManagerService mBackupManagerService;
@@ -57,33 +48,31 @@
     private KeyValueBackupReporter mReporter;
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         mReporter = new KeyValueBackupReporter(mBackupManagerService, mObserver, mMonitor);
     }
 
     @Test
-    public void testMoreDebug_isFalse() throws Exception {
-        boolean moreDebug = KeyValueBackupReporter.MORE_DEBUG;
-
-        assertThat(moreDebug).isFalse();
+    public void testMoreDebug_isFalse() {
+        assertThat(KeyValueBackupReporter.MORE_DEBUG).isFalse();
     }
 
     @Test
-    public void testOnNewThread_logsCorrectly() throws Exception {
+    public void testOnNewThread_logsCorrectly() {
         KeyValueBackupReporter.onNewThread("foo");
 
         assertLogcat(TAG, Log.DEBUG);
     }
 
     @Test
-    public void testGetMonitor_returnsMonitor() throws Exception {
+    public void testGetMonitor_returnsMonitor() {
         IBackupManagerMonitor monitor = mReporter.getMonitor();
 
         assertThat(monitor).isEqualTo(mMonitor);
     }
 
     @Test
-    public void testGetObserver_returnsObserver() throws Exception {
+    public void testGetObserver_returnsObserver() {
         IBackupObserver observer = mReporter.getObserver();
 
         assertThat(observer).isEqualTo(mObserver);
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index ba1d83e..a69f007 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -25,9 +25,12 @@
 import static android.app.backup.ForwardingBackupAgent.forward;
 
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createInitializedBackupManagerService;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
-import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBinderCallerAndApplicationAsSystem;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils
+        .createInitializedBackupManagerService;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils
+        .setUpBackupManagerServiceBasics;
+import static com.android.server.backup.testing.BackupManagerServiceTestUtils
+        .setUpBinderCallerAndApplicationAsSystem;
 import static com.android.server.backup.testing.PackageData.PM_PACKAGE;
 import static com.android.server.backup.testing.PackageData.fullBackupPackage;
 import static com.android.server.backup.testing.PackageData.keyValuePackage;
@@ -62,8 +65,8 @@
 import static org.mockito.Mockito.when;
 import static org.robolectric.Shadows.shadowOf;
 import static org.robolectric.shadow.api.Shadow.extract;
-import static org.testng.Assert.fail;
 import static org.testng.Assert.expectThrows;
+import static org.testng.Assert.fail;
 
 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 import static java.util.Collections.emptyList;
@@ -114,9 +117,6 @@
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderClasses;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.FrameworkShadowLooper;
 import com.android.server.testing.shadows.ShadowBackupDataInput;
 import com.android.server.testing.shadows.ShadowBackupDataOutput;
@@ -134,6 +134,7 @@
 import org.mockito.MockitoAnnotations;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
@@ -156,10 +157,8 @@
 import java.util.stream.Stream;
 
 // TODO: Test agents timing out
-@RunWith(FrameworkRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
 @Config(
-        manifest = Config.NONE,
-        sdk = 26,
         shadows = {
             FrameworkShadowLooper.class,
             ShadowBackupDataInput.class,
@@ -167,8 +166,6 @@
             ShadowEventLog.class,
             ShadowQueuedWork.class,
         })
-@SystemLoaderPackages({"com.android.server.backup", "android.app.backup"})
-@SystemLoaderClasses({IBackupTransport.class, IBackupAgent.class, PackageInfo.class})
 @Presubmit
 public class KeyValueBackupTaskTest {
     private static final PackageData PACKAGE_1 = keyValuePackage(1);
@@ -187,6 +184,7 @@
     private Handler mBackupHandler;
     private PowerManager.WakeLock mWakeLock;
     private KeyValueBackupReporter mReporter;
+    private PackageManager mPackageManager;
     private ShadowPackageManager mShadowPackageManager;
     private FakeIBackupManager mBackupManager;
     private File mBaseStateDir;
@@ -219,8 +217,8 @@
         mDataDir.mkdirs();
         assertThat(mDataDir.isDirectory()).isTrue();
 
-        PackageManager packageManager = mApplication.getPackageManager();
-        mShadowPackageManager = shadowOf(packageManager);
+        mPackageManager = mApplication.getPackageManager();
+        mShadowPackageManager = shadowOf(mPackageManager);
 
         mWakeLock = createBackupWakeLock(mApplication);
         mBackupManager = spy(FakeIBackupManager.class);
@@ -235,7 +233,7 @@
                 mBackupManagerService,
                 mApplication,
                 mTransportManager,
-                packageManager,
+                mPackageManager,
                 mBackupManagerService.getBackupHandler(),
                 mWakeLock,
                 mBackupManagerService.getAgentTimeoutParameters());
@@ -332,6 +330,22 @@
                 .isEqualTo("packageState".getBytes());
     }
 
+    /**
+     * Do not update backup token if the backup queue was empty
+     */
+    @Test
+    public void testRunTask_whenQueueEmptyOnFirstBackup_doesNotUpdateCurrentToken()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true);
+        mBackupManagerService.setCurrentToken(0L);
+        when(transportMock.transport.getCurrentRestoreSet()).thenReturn(1234L);
+
+        runTask(task);
+
+        assertThat(mBackupManagerService.getCurrentToken()).isEqualTo(0L);
+    }
+
     @Test
     public void testRunTask_whenOnePackageAndTransportUnavailable() throws Exception {
         TransportMock transportMock = setUpInitializedTransport(mTransport.unavailable());
@@ -2302,6 +2316,24 @@
         expectThrows(IllegalArgumentException.class, () -> task.handleCancel(false));
     }
 
+    /**
+     * Do not update backup token if no data was moved.
+     */
+    @Test
+    public void testRunTask_whenNoDataToBackupOnFirstBackup_doesNotUpdateCurrentToken()
+            throws Exception {
+        TransportMock transportMock = setUpInitializedTransport(mTransport);
+        mBackupManagerService.setCurrentToken(0L);
+        when(transportMock.transport.getCurrentRestoreSet()).thenReturn(1234L);
+        // Set up agent with no data.
+        setUpAgent(PACKAGE_1);
+        KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
+
+        runTask(task);
+
+        assertThat(mBackupManagerService.getCurrentToken()).isEqualTo(0L);
+    }
+
     private void runTask(KeyValueBackupTask task) {
         // Pretend we are not on the main-thread to prevent RemoteCall from complaining
         mShadowMainLooper.setCurrentThread(false);
@@ -2406,7 +2438,7 @@
 
     private AgentMock setUpAgent(PackageData packageData) {
         try {
-            mShadowPackageManager.setApplicationEnabledSetting(
+            mPackageManager.setApplicationEnabledSetting(
                     packageData.packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
             PackageInfo packageInfo = getPackageInfo(packageData);
             mShadowPackageManager.addPackage(packageInfo);
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java b/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java
index 4b79657..3698b79 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/TaskExceptionTest.java
@@ -23,18 +23,13 @@
 import android.app.backup.BackupTransport;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.io.IOException;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class TaskExceptionTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
index f3621e2..5ac26f4 100644
--- a/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java
@@ -20,18 +20,13 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.util.concurrent.CompletableFuture;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class FutureBackupCallbackTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
index 1d92bed..7ec2a4e 100644
--- a/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java
@@ -32,23 +32,19 @@
 import android.platform.test.annotations.Presubmit;
 
 import com.android.server.backup.testing.TestUtils.ThrowingRunnable;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Future;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class RemoteCallTest {
     /** A {@link RemoteCallable} that calls the callback immediately. */
@@ -267,9 +263,4 @@
     private static void postDelayed(Handler handler, ThrowingRunnable runnable, long delayMillis) {
         handler.postDelayed(() -> uncheck(runnable), delayMillis);
     }
-
-    /** Unchecked version of {@link Handler#post(Runnable)}. */
-    private static void post(Handler handler, ThrowingRunnable runnable) {
-        handler.post(() -> uncheck(runnable));
-    }
 }
diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
index 7f6fd57..b9a77fb 100644
--- a/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java
@@ -22,16 +22,11 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class RemoteResultTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java b/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
index e0d3c0c..38a54da 100644
--- a/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
+++ b/services/robotests/src/com/android/server/backup/remote/ServiceBackupCallbackTest.java
@@ -22,16 +22,11 @@
 import android.app.backup.IBackupManager;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class ServiceBackupCallbackTest {
     @Test
diff --git a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
index 2717120..0e2b95b 100644
--- a/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
+++ b/services/robotests/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java
@@ -19,7 +19,6 @@
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.createBackupWakeLock;
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics;
 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThreadAndGetLooper;
-
 import static com.android.server.backup.testing.TestUtils.assertEventLogged;
 import static com.android.server.backup.testing.TestUtils.assertEventNotLogged;
 import static com.android.server.backup.testing.TransportData.backupTransport;
@@ -58,8 +57,6 @@
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.ShadowEventLog;
 import com.android.server.testing.shadows.ShadowPerformUnifiedRestoreTask;
 
@@ -69,6 +66,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowApplication;
@@ -78,18 +76,14 @@
 
 import java.util.ArrayDeque;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class, ShadowBinder.class})
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class, ShadowBinder.class})
 @Presubmit
 public class ActiveRestoreSessionTest {
     private static final String PACKAGE_1 = "com.example.package1";
     private static final String PACKAGE_2 = "com.example.package2";
-    public static final long TOKEN_1 = 1L;
-    public static final long TOKEN_2 = 2L;
+    private static final long TOKEN_1 = 1L;
+    private static final long TOKEN_2 = 2L;
 
     @Mock private BackupManagerService mBackupManagerService;
     @Mock private TransportManager mTransportManager;
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
index bbec7af..7dd0d92 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java
@@ -17,6 +17,7 @@
 package com.android.server.backup.transport;
 
 import static com.android.server.backup.TransportManager.SERVICE_ACTION_TRANSPORT_HOST;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.argThat;
@@ -32,19 +33,15 @@
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class TransportClientManagerTest {
     private static final String PACKAGE_NAME = "random.package.name";
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
index f843b50..7281a3c 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportClientTest.java
@@ -49,8 +49,6 @@
 
 import com.android.internal.backup.IBackupTransport;
 import com.android.server.EventLogTags;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 import com.android.server.testing.shadows.FrameworkShadowLooper;
 import com.android.server.testing.shadows.ShadowCloseGuard;
 import com.android.server.testing.shadows.ShadowEventLog;
@@ -62,6 +60,7 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLog;
 import org.robolectric.shadows.ShadowLooper;
@@ -69,17 +68,13 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Supplier;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 26,
-        shadows = {
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
             ShadowEventLog.class,
             ShadowCloseGuard.class,
             ShadowSlog.class,
             FrameworkShadowLooper.class
         })
-@SystemLoaderPackages({"com.android.server.backup"})
 @Presubmit
 public class TransportClientTest {
     private static final String PACKAGE_NAME = "some.package.name";
@@ -137,7 +132,7 @@
     }
 
     @Test
-    public void testConnectAsync_callsBindService() throws Exception {
+    public void testConnectAsync_callsBindService() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller");
 
         verify(mContext)
@@ -149,7 +144,7 @@
     }
 
     @Test
-    public void testConnectAsync_callsListenerWhenConnected() throws Exception {
+    public void testConnectAsync_callsListenerWhenConnected() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
 
@@ -161,8 +156,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenPendingConnection_callsAllListenersWhenConnected()
-            throws Exception {
+    public void testConnectAsync_whenPendingConnection_callsAllListenersWhenConnected() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
 
@@ -177,7 +171,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenAlreadyConnected_callsListener() throws Exception {
+    public void testConnectAsync_whenAlreadyConnected_callsListener() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -190,7 +184,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenFrameworkDoesntBind_callsListener() throws Exception {
+    public void testConnectAsync_whenFrameworkDoesntBind_callsListener() {
         when(mContext.bindServiceAsUser(
                         eq(mBindIntent),
                         any(ServiceConnection.class),
@@ -206,7 +200,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenFrameworkDoesNotBind_releasesConnection() throws Exception {
+    public void testConnectAsync_whenFrameworkDoesNotBind_releasesConnection() {
         when(mContext.bindServiceAsUser(
                         eq(mBindIntent),
                         any(ServiceConnection.class),
@@ -221,8 +215,7 @@
     }
 
     @Test
-    public void testConnectAsync_afterOnServiceDisconnectedBeforeNewConnection_callsListener()
-            throws Exception {
+    public void testConnectAsync_afterOnServiceDisconnectedBeforeNewConnection_callsListener() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -235,8 +228,7 @@
     }
 
     @Test
-    public void testConnectAsync_afterOnServiceDisconnectedAfterNewConnection_callsListener()
-            throws Exception {
+    public void testConnectAsync_afterOnServiceDisconnectedAfterNewConnection_callsListener() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -251,7 +243,7 @@
     }
 
     @Test
-    public void testConnectAsync_callsListenerIfBindingDies() throws Exception {
+    public void testConnectAsync_callsListenerIfBindingDies() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
 
@@ -263,8 +255,7 @@
     }
 
     @Test
-    public void testConnectAsync_whenPendingConnection_callsListenersIfBindingDies()
-            throws Exception {
+    public void testConnectAsync_whenPendingConnection_callsListenersIfBindingDies() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
 
@@ -412,14 +403,14 @@
     }
 
     @Test
-    public void testMarkAsDisposed_whenCreated() throws Throwable {
+    public void testMarkAsDisposed_whenCreated() {
         mTransportClient.markAsDisposed();
 
         // No exception thrown
     }
 
     @Test
-    public void testMarkAsDisposed_afterOnBindingDied() throws Throwable {
+    public void testMarkAsDisposed_afterOnBindingDied() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onBindingDied(mTransportComponent);
@@ -430,7 +421,7 @@
     }
 
     @Test
-    public void testMarkAsDisposed_whenConnectedAndUnbound() throws Throwable {
+    public void testMarkAsDisposed_whenConnectedAndUnbound() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -442,7 +433,7 @@
     }
 
     @Test
-    public void testMarkAsDisposed_afterOnServiceDisconnected() throws Throwable {
+    public void testMarkAsDisposed_afterOnServiceDisconnected() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
@@ -454,14 +445,14 @@
     }
 
     @Test
-    public void testMarkAsDisposed_whenBound() throws Throwable {
+    public void testMarkAsDisposed_whenBound() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
 
         expectThrows(RuntimeException.class, mTransportClient::markAsDisposed);
     }
 
     @Test
-    public void testMarkAsDisposed_whenConnected() throws Throwable {
+    public void testMarkAsDisposed_whenConnected() {
         mTransportClient.connectAsync(mTransportConnectionListener, "caller1");
         ServiceConnection connection = verifyBindServiceAsUserAndCaptureServiceConnection(mContext);
         connection.onServiceConnected(mTransportComponent, mTransportBinder);
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java b/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
index 322db85..f01a6b0 100644
--- a/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
+++ b/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
@@ -25,17 +25,13 @@
 import android.platform.test.annotations.Presubmit;
 
 import com.android.server.backup.transport.TransportStats.Stats;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(manifest = Config.NONE, sdk = 26)
-@SystemLoaderPackages({"com.android.server.backup"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class TransportStatsTest {
     private static final double TOLERANCE = 0.0001;
diff --git a/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java b/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java
index 5046094..d58c3f7 100644
--- a/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssBatchingProviderTest.java
@@ -1,9 +1,10 @@
 package com.android.server.location;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.eq;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -11,27 +12,18 @@
 import android.platform.test.annotations.Presubmit;
 
 import com.android.server.location.GnssBatchingProvider.GnssBatchingProviderNative;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 /**
  * Unit tests for {@link GnssBatchingProvider}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        shadows = {
-        },
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssBatchingProviderTest {
 
diff --git a/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java b/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
index 187303c..beb5941 100644
--- a/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssGeofenceProviderTest.java
@@ -1,8 +1,8 @@
 package com.android.server.location;
 
-import static org.mockito.Matchers.anyDouble;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.anyDouble;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -11,25 +11,17 @@
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 /**
  * Unit tests for {@link GnssGeofenceProvider}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssGeofenceProviderTest {
     private static final int GEOFENCE_ID = 12345;
diff --git a/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java b/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
index 23d6cf6..b349b67 100644
--- a/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssMeasurementsProviderTest.java
@@ -1,6 +1,7 @@
 package com.android.server.location;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -10,26 +11,18 @@
 import android.os.Looper;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
 /**
  * Unit tests for {@link GnssMeasurementsProvider}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssMeasurementsProviderTest {
     @Mock
diff --git a/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java b/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java
index 8d3de3c..59e9a15 100644
--- a/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java
+++ b/services/robotests/src/com/android/server/location/GnssNavigationMessageProviderTest.java
@@ -10,25 +10,17 @@
 import android.os.Looper;
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 /**
  * Unit tests for {@link GnssNavigationMessageProvider}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssNavigationMessageProviderTest {
     @Mock
diff --git a/services/robotests/src/com/android/server/location/GnssPositionModeTest.java b/services/robotests/src/com/android/server/location/GnssPositionModeTest.java
index e6d53551..f37f50e 100644
--- a/services/robotests/src/com/android/server/location/GnssPositionModeTest.java
+++ b/services/robotests/src/com/android/server/location/GnssPositionModeTest.java
@@ -4,24 +4,16 @@
 
 import android.platform.test.annotations.Presubmit;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
 
 import java.util.HashSet;
 
 /**
  * Unit tests for {@link GnssPositionMode}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssPositionModeTest {
 
diff --git a/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java b/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java
index d6f5446..ba4a753 100644
--- a/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java
+++ b/services/robotests/src/com/android/server/location/GnssSatelliteBlacklistHelperTest.java
@@ -2,7 +2,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
@@ -13,18 +13,15 @@
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
 
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.Shadows;
-import org.robolectric.annotation.Config;
 
 import java.util.Collection;
 import java.util.List;
@@ -32,18 +29,10 @@
 /**
  * Unit tests for {@link GnssSatelliteBlacklistHelper}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        shadows = {
-        },
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class GnssSatelliteBlacklistHelperTest {
 
-    private Context mContext;
     private ContentResolver mContentResolver;
     @Mock
     private GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback mCallback;
@@ -51,9 +40,9 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mContentResolver = mContext.getContentResolver();
-        new GnssSatelliteBlacklistHelper(mContext, Looper.myLooper(), mCallback);
+        Context context = RuntimeEnvironment.application;
+        mContentResolver = context.getContentResolver();
+        new GnssSatelliteBlacklistHelper(context, Looper.myLooper(), mCallback);
     }
 
     @Test
diff --git a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java b/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
index a68b579..aac0a34 100644
--- a/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
+++ b/services/robotests/src/com/android/server/location/NtpTimeHelperTest.java
@@ -9,16 +9,14 @@
 import android.util.NtpTrustedTime;
 
 import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback;
-import com.android.server.testing.FrameworkRobolectricTestRunner;
-import com.android.server.testing.SystemLoaderPackages;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowLooper;
 import org.robolectric.shadows.ShadowSystemClock;
 
@@ -28,12 +26,7 @@
 /**
  * Unit tests for {@link NtpTimeHelper}.
  */
-@RunWith(FrameworkRobolectricTestRunner.class)
-@Config(
-        manifest = Config.NONE,
-        sdk = 27
-)
-@SystemLoaderPackages({"com.android.server.location"})
+@RunWith(RobolectricTestRunner.class)
 @Presubmit
 public class NtpTimeHelperTest {
 
diff --git a/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java b/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java
deleted file mode 100644
index d2a4d06..0000000
--- a/services/robotests/src/com/android/server/testing/FrameworkRobolectricTestRunner.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2017 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.testing;
-
-import static java.util.Arrays.asList;
-
-import com.google.common.collect.ImmutableSet;
-
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.internal.SandboxFactory;
-import org.robolectric.internal.SdkEnvironment;
-import org.robolectric.internal.bytecode.InstrumentationConfiguration;
-import org.robolectric.internal.bytecode.SandboxClassLoader;
-import org.robolectric.util.Util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.stream.Stream;
-
-import javax.annotation.Nonnull;
-
-/**
- * HACK
- * Robolectric loads up Android environment from prebuilt android jars before running a method.
- * These jars are versioned according to the SDK level configured for the method (or class). The
- * jars represent a snapshot of the Android APIs in that SDK level. For Robolectric tests that are
- * testing Android components themselves we don't want certain classes (usually the
- * class-under-test) to be loaded from the prebuilt jar, we want it instead to be loaded from the
- * dependencies of our test target, i.e. the system class loader. That way we can write tests
- * against the actual classes that are in the tree, not a past version of them. Ideally we would
- * have a locally built jar referenced by Robolectric, but until that happens one can use this
- * class.
- * This class reads the {@link SystemLoaderClasses} or {@link SystemLoaderPackages} annotations on
- * test classes, for classes that match the annotations it will bypass the android jar and load it
- * from the system class loader. Allowing the test to test the actual class in the tree.
- *
- * Implementation note: One could think about overriding
- * {@link RobolectricTestRunner#createClassLoaderConfig(FrameworkMethod)} method and putting the
- * classes in the annotation in the {@link InstrumentationConfiguration} list of classes not to
- * acquire. Unfortunately, this will not work because we will not be instrumenting the class.
- * Instead, we have to load the class bytes from the system class loader but still instrument it, we
- * do this by overriding {@link SandboxClassLoader#getByteCode(String)} and loading the class bytes
- * from the system class loader if it in the {@link SystemLoaderClasses} annotation. This way the
- * {@link SandboxClassLoader} still instruments the class, but it's not loaded from the android jar.
- * Finally, we inject the custom class loader in place of the default one.
- *
- * TODO: Remove this when we are using locally built android jars in the method's environment.
- */
-public class FrameworkRobolectricTestRunner extends RobolectricTestRunner {
-    private final SandboxFactory mSandboxFactory;
-
-    public FrameworkRobolectricTestRunner(Class<?> testClass) throws InitializationError {
-        super(testClass);
-        Set<String> classPrefixes = getSystemLoaderClassPrefixes(testClass);
-        mSandboxFactory = new FrameworkSandboxFactory(classPrefixes);
-    }
-
-    private Set<String> getSystemLoaderClassPrefixes(Class<?> testClass) {
-        Set<String> classPrefixes = new HashSet<>();
-        SystemLoaderClasses byClass = testClass.getAnnotation(SystemLoaderClasses.class);
-        if (byClass != null) {
-            Stream.of(byClass.value()).map(Class::getName).forEach(classPrefixes::add);
-        }
-        SystemLoaderPackages byPackage = testClass.getAnnotation(SystemLoaderPackages.class);
-        if (byPackage != null) {
-            classPrefixes.addAll(asList(byPackage.value()));
-        }
-        return classPrefixes;
-    }
-
-    @Nonnull
-    @Override
-    protected SdkEnvironment getSandbox(FrameworkMethod method) {
-        // HACK: Calling super just to get SdkConfig via sandbox.getSdkConfig(), because
-        // RobolectricFrameworkMethod, the runtime class of method, is package-protected
-        SdkEnvironment sandbox = super.getSandbox(method);
-        return mSandboxFactory.getSdkEnvironment(
-                createClassLoaderConfig(method),
-                getJarResolver(),
-                sandbox.getSdkConfig());
-    }
-
-    private static class FrameworkClassLoader extends SandboxClassLoader {
-        private final Set<String> mSystemLoaderClassPrefixes;
-
-        private FrameworkClassLoader(
-                Set<String> systemLoaderClassPrefixes,
-                ClassLoader systemClassLoader,
-                InstrumentationConfiguration instrumentationConfig,
-                URL... urls) {
-            super(systemClassLoader, instrumentationConfig, urls);
-            mSystemLoaderClassPrefixes = systemLoaderClassPrefixes;
-        }
-
-        @Override
-        protected byte[] getByteCode(String className) throws ClassNotFoundException {
-            String classFileName = className.replace('.', '/') + ".class";
-            if (shouldLoadFromSystemLoader(className)) {
-                try (InputStream classByteStream = getResourceAsStream(classFileName)) {
-                    if (classByteStream == null) {
-                        throw new ClassNotFoundException(className);
-                    }
-                    return Util.readBytes(classByteStream);
-                } catch (IOException e) {
-                    throw new ClassNotFoundException(
-                            "Couldn't load " + className + " from system class loader", e);
-                }
-            }
-            return super.getByteCode(className);
-        }
-
-        /**
-         * HACK^2
-         * The framework Robolectric run configuration puts a prebuilt in front of us, so we try not
-         * to load the class from there, if possible.
-         */
-        @Override
-        public InputStream getResourceAsStream(String resource) {
-            try {
-                Enumeration<URL> urls = getResources(resource);
-                while (urls.hasMoreElements()) {
-                    URL url = urls.nextElement();
-                    if (!url.toString().toLowerCase().contains("prebuilt")) {
-                        return url.openStream();
-                    }
-                }
-            } catch (IOException e) {
-                // Fall through
-            }
-            return super.getResourceAsStream(resource);
-        }
-
-        /**
-         * Classes like com.package.ClassName$InnerClass should also be loaded from the system class
-         * loader, so we test if the classes in the annotation are prefixes of the class to load.
-         */
-        private boolean shouldLoadFromSystemLoader(String className) {
-            for (String classPrefix : mSystemLoaderClassPrefixes) {
-                if (className.startsWith(classPrefix)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-
-    private static class FrameworkSandboxFactory extends SandboxFactory {
-        private final Set<String> mSystemLoaderClassPrefixes;
-
-        private FrameworkSandboxFactory(Set<String> systemLoaderClassPrefixes) {
-            mSystemLoaderClassPrefixes = systemLoaderClassPrefixes;
-        }
-
-        @Nonnull
-        @Override
-        public ClassLoader createClassLoader(
-                InstrumentationConfiguration instrumentationConfig, URL... urls) {
-            return new FrameworkClassLoader(
-                    mSystemLoaderClassPrefixes,
-                    ClassLoader.getSystemClassLoader(),
-                    instrumentationConfig,
-                    urls);
-        }
-    }
-}
diff --git a/services/robotests/src/com/android/server/testing/SystemLoaderClasses.java b/services/robotests/src/com/android/server/testing/SystemLoaderClasses.java
deleted file mode 100644
index 646a413..0000000
--- a/services/robotests/src/com/android/server/testing/SystemLoaderClasses.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2017 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.testing;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation to be used in test classes that run with {@link FrameworkRobolectricTestRunner}.
- * This will make the classes specified be loaded from the system class loader, NOT from the
- * Robolectric android jar.
- *
- * @see FrameworkRobolectricTestRunner
- */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface SystemLoaderClasses {
-    Class<?>[] value() default {};
-}
diff --git a/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java b/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java
deleted file mode 100644
index e01c0a4..0000000
--- a/services/robotests/src/com/android/server/testing/SystemLoaderPackages.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2018 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.testing;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation to be used in test classes that run with {@link FrameworkRobolectricTestRunner}.
- * This will make the classes under the specified packages be loaded from the system class loader,
- * NOT from the Robolectric android jar.
- *
- * @see FrameworkRobolectricTestRunner
- */
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface SystemLoaderPackages {
-    String[] value() default {};
-}
diff --git a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowContextImpl.java b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowContextImpl.java
deleted file mode 100644
index 6d22073..0000000
--- a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowContextImpl.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2018 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.testing.shadows;
-
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.UserHandle;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowContextImpl;
-
-@Implements(className = ShadowContextImpl.CLASS_NAME, inheritImplementationMethods = true)
-public class FrameworkShadowContextImpl extends ShadowContextImpl {
-    @Implementation
-    public boolean bindServiceAsUser(
-            Intent service,
-            ServiceConnection connection,
-            int flags,
-            UserHandle user) {
-        return bindService(service, connection, flags);
-    }
-}
diff --git a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java
index c0eeb38..16d16cd 100644
--- a/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java
+++ b/services/robotests/src/com/android/server/testing/shadows/FrameworkShadowLooper.java
@@ -25,7 +25,7 @@
 
 import java.util.Optional;
 
-@Implements(value = Looper.class, inheritImplementationMethods = true)
+@Implements(value = Looper.class)
 public class FrameworkShadowLooper extends ShadowLooper {
     @RealObject private Looper mLooper;
     private Optional<Boolean> mIsCurrentThread = Optional.empty();
@@ -39,7 +39,7 @@
     }
 
     @Implementation
-    public boolean isCurrentThread() {
+    protected boolean isCurrentThread() {
         if (mIsCurrentThread.isPresent()) {
             return mIsCurrentThread.get();
         }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
index 21faa09..5fffb14 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java
@@ -26,6 +26,7 @@
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
 
 import java.util.HashSet;
 import java.util.Set;
@@ -52,21 +53,22 @@
     }
 
     @Implementation
-    public static boolean appIsRunningAndEligibleForBackupWithTransport(
+    protected static boolean appIsRunningAndEligibleForBackupWithTransport(
             @Nullable TransportClient transportClient, String packageName, PackageManager pm) {
         return sAppsRunningAndEligibleForBackupWithTransport.contains(packageName);
     }
 
     @Implementation
-    public static boolean appIsEligibleForBackup(ApplicationInfo app, PackageManager pm) {
+    protected static boolean appIsEligibleForBackup(ApplicationInfo app, PackageManager pm) {
         return sAppsEligibleForBackup.contains(app.packageName);
     }
 
     @Implementation
-    public static boolean appGetsFullBackup(PackageInfo packageInfo) {
+    protected static boolean appGetsFullBackup(PackageInfo packageInfo) {
         return sAppsGetFullBackup.contains(packageInfo.packageName);
     }
 
+    @Resetter
     public static void reset() {
         sAppsRunningAndEligibleForBackupWithTransport.clear();
         sAppsEligibleForBackup.clear();
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
index 4901828..e7d2a68 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataInput.java
@@ -52,12 +52,12 @@
     private boolean mHeaderReady;
 
     @Implementation
-    public void __constructor__(FileDescriptor fd) {
+    protected void __constructor__(FileDescriptor fd) {
         mFileDescriptor = fd;
     }
 
     @Implementation
-    public boolean readNextHeader() throws IOException {
+    protected boolean readNextHeader() throws IOException {
         if (sReadNextHeaderThrow) {
             sReadNextHeaderThrow = false;
             throw new IOException("Fake exception");
@@ -75,19 +75,19 @@
     }
 
     @Implementation
-    public String getKey() {
+    protected String getKey() {
         checkHeaderReady();
         return mKey;
     }
 
     @Implementation
-    public int getDataSize() {
+    protected int getDataSize() {
         checkHeaderReady();
         return mSize;
     }
 
     @Implementation
-    public int readEntityData(byte[] data, int offset, int size) throws IOException {
+    protected int readEntityData(byte[] data, int offset, int size) throws IOException {
         checkHeaderReady();
         int result = mInput.read(data, offset, size);
         if (result < 0) {
@@ -97,7 +97,7 @@
     }
 
     @Implementation
-    public void skipEntityData() throws IOException {
+    protected void skipEntityData() throws IOException {
         checkHeaderReady();
         mInput.read(new byte[mSize], 0, mSize);
     }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
index 5812c3c..4aef28c 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBackupDataOutput.java
@@ -39,19 +39,19 @@
     private int mTransportFlags;
 
     @Implementation
-    public void __constructor__(FileDescriptor fd, long quota, int transportFlags) {
+    protected void __constructor__(FileDescriptor fd, long quota, int transportFlags) {
         mFileDescriptor = fd;
         mQuota = quota;
         mTransportFlags = transportFlags;
     }
 
     @Implementation
-    public long getQuota() {
+    protected long getQuota() {
         return mQuota;
     }
 
     @Implementation
-    public int getTransportFlags() {
+    protected int getTransportFlags() {
         return mTransportFlags;
     }
 
@@ -61,7 +61,7 @@
     }
 
     @Implementation
-    public int writeEntityHeader(String key, int dataSize) throws IOException {
+    protected int writeEntityHeader(String key, int dataSize) throws IOException {
         ensureOutput();
         final int size;
         try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {
@@ -81,7 +81,7 @@
     }
 
     @Implementation
-    public int writeEntityData(byte[] data, int size) throws IOException {
+    protected int writeEntityData(byte[] data, int size) throws IOException {
         ensureOutput();
         mOutput.write(data, 0, size);
         mOutput.flush();
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java b/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java
index 043d44b..1ece49e 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowBinder.java
@@ -17,6 +17,7 @@
 package com.android.server.testing.shadows;
 
 import android.os.Binder;
+
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
@@ -31,14 +32,14 @@
     private static Integer originalCallingUid;
 
     @Implementation
-    public static long clearCallingIdentity() {
+    protected static long clearCallingIdentity() {
         originalCallingUid = getCallingUid();
         setCallingUid(LOCAL_UID);
         return 1L;
     }
 
     @Implementation
-    public static void restoreCallingIdentity(long token) {
+    protected static void restoreCallingIdentity(long token) {
         setCallingUid(originalCallingUid);
     }
 }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java b/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java
index 3df1723..5d9c88b 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowEventLog.java
@@ -32,14 +32,14 @@
     private static final LinkedHashSet<Entry> ENTRIES = new LinkedHashSet<>();
 
     @Implementation
-    public static int writeEvent(int tag, Object... values) {
+    protected static int writeEvent(int tag, Object... values) {
         ENTRIES.add(new Entry(tag, Arrays.asList(values)));
         // Currently we don't care about the return value, if we do, estimate it correctly
         return 0;
     }
 
     @Implementation
-    public static int writeEvent(int tag, String string) {
+    protected static int writeEvent(int tag, String string) {
         return writeEvent(tag, (Object) string);
     }
 
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java b/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java
index 3c913e3..4756476 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowFullBackup.java
@@ -31,7 +31,7 @@
      * implementation.
      */
     @Implementation
-    public static int backupToTar(
+    protected static int backupToTar(
             String packageName,
             String domain,
             String linkdomain,
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java
index 3941f17..23c44b0 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupJob.java
@@ -18,8 +18,10 @@
 
 import android.content.Context;
 import android.os.Binder;
+
 import com.android.server.backup.BackupManagerConstants;
 import com.android.server.backup.KeyValueBackupJob;
+
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
@@ -32,7 +34,7 @@
     }
 
     @Implementation
-    public static void schedule(Context ctx, long delay, BackupManagerConstants constants) {
+    protected static void schedule(Context ctx, long delay, BackupManagerConstants constants) {
         callingUid = Binder.getCallingUid();
     }
 }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
index b7db56b..ca80664 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowKeyValueBackupTask.java
@@ -53,7 +53,7 @@
     private List<String> mPendingFullBackups;
 
     @Implementation
-    public void __constructor__(
+    protected void __constructor__(
             BackupManagerService backupManagerService,
             TransportClient transportClient,
             String transportDirName,
@@ -71,7 +71,7 @@
     }
 
     @Implementation
-    public void execute() {
+    protected void execute() {
         mListener.onFinished("ShadowKeyValueBackupTask.execute()");
     }
 
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowPerformUnifiedRestoreTask.java b/services/robotests/src/com/android/server/testing/shadows/ShadowPerformUnifiedRestoreTask.java
index 0f93c7a..228d4eb 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowPerformUnifiedRestoreTask.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowPerformUnifiedRestoreTask.java
@@ -54,7 +54,7 @@
     private OnTaskFinishedListener mListener;
 
     @Implementation
-    public void __constructor__(
+    protected void __constructor__(
             BackupManagerService backupManagerService,
             TransportClient transportClient,
             IRestoreObserver observer,
@@ -74,7 +74,7 @@
     }
 
     @Implementation
-    public void execute() {
+    protected void execute() {
         mBackupManagerService.setRestoreInProgress(false);
         mListener.onFinished("ShadowPerformUnifiedRestoreTask.execute()");
     }
diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowSlog.java b/services/robotests/src/com/android/server/testing/shadows/ShadowSlog.java
index 737b0c8..32ef1bc 100644
--- a/services/robotests/src/com/android/server/testing/shadows/ShadowSlog.java
+++ b/services/robotests/src/com/android/server/testing/shadows/ShadowSlog.java
@@ -21,92 +21,91 @@
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowLog;
 
 @Implements(Slog.class)
 public class ShadowSlog {
     @Implementation
-    public static int v(String tag, String msg) {
+    protected static int v(String tag, String msg) {
         return Log.v(tag, msg);
     }
 
     @Implementation
-    public static int v(String tag, String msg, Throwable tr) {
+    protected static int v(String tag, String msg, Throwable tr) {
         return Log.v(tag, msg, tr);
     }
 
     @Implementation
-    public static int d(String tag, String msg) {
+    protected static int d(String tag, String msg) {
         return Log.d(tag, msg);
     }
 
     @Implementation
-    public static int d(String tag, String msg, Throwable tr) {
+    protected static int d(String tag, String msg, Throwable tr) {
         return Log.d(tag, msg, tr);
     }
 
     @Implementation
-    public static int i(String tag, String msg) {
+    protected static int i(String tag, String msg) {
         return Log.i(tag, msg);
     }
 
     @Implementation
-    public static int i(String tag, String msg, Throwable tr) {
+    protected static int i(String tag, String msg, Throwable tr) {
         return Log.i(tag, msg, tr);
     }
 
     @Implementation
-    public static int w(String tag, String msg) {
+    protected static int w(String tag, String msg) {
         return Log.w(tag, msg);
     }
 
     @Implementation
-    public static int w(String tag, String msg, Throwable tr) {
+    protected static int w(String tag, String msg, Throwable tr) {
         return Log.w(tag, msg, tr);
     }
 
     @Implementation
-    public static int w(String tag, Throwable tr) {
+    protected static int w(String tag, Throwable tr) {
         return Log.w(tag, tr);
     }
 
     @Implementation
-    public static int e(String tag, String msg) {
+    protected static int e(String tag, String msg) {
         return Log.e(tag, msg);
     }
 
     @Implementation
-    public static int e(String tag, String msg, Throwable tr) {
+    protected static int e(String tag, String msg, Throwable tr) {
         return Log.e(tag, msg, tr);
     }
 
     @Implementation
-    public static int wtf(String tag, String msg) {
+    protected static int wtf(String tag, String msg) {
         return Log.wtf(tag, msg);
     }
 
     @Implementation
-    public static void wtfQuiet(String tag, String msg) {
+    protected static void wtfQuiet(String tag, String msg) {
         Log.wtf(tag, msg);
     }
 
     @Implementation
-    public static int wtfStack(String tag, String msg) {
+    protected static int wtfStack(String tag, String msg) {
         return Log.wtf(tag, msg);
     }
 
     @Implementation
-    public static int wtf(String tag, Throwable tr) {
+    protected static int wtf(String tag, Throwable tr) {
         return Log.wtf(tag, tr);
     }
 
     @Implementation
-    public static int wtf(String tag, String msg, Throwable tr) {
+    protected static int wtf(String tag, String msg, Throwable tr) {
         return Log.wtf(tag, msg, tr);
     }
 
     @Implementation
-    public static int println(int priority, String tag, String msg) {
+    protected static int println(int priority, String tag, String msg) {
         return Log.println(priority, tag, msg);
     }
 }
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 878179b..e2f8995 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -33,7 +33,8 @@
     testables \
     testng \
     ub-uiautomator\
-    platformprotosnano
+    platformprotosnano \
+    hamcrest-library
 
 LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl
 
diff --git a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
index e53518c..e6b328a 100644
--- a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
@@ -21,15 +21,16 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.when;
 
+import android.app.ActivityManagerInternal;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
-import android.os.UserHandle;
 import android.os.UserManagerInternal;
 import android.os.storage.StorageManagerInternal;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -47,6 +48,7 @@
     @Mock private PackageManager mPm;
     @Mock private PackageManagerInternal mPmi;
     @Mock private UserManagerInternal mUmi;
+    @Mock private ActivityManagerInternal mAmi;
 
     private static final String PKG_GREY = "com.grey";
     private static final String PKG_RED = "com.red";
@@ -55,6 +57,10 @@
     private static final int UID_GREY = 10000;
     private static final int UID_COLORS = 10001;
 
+    private static final int PID_GREY = 1111;
+    private static final int PID_RED = 2222;
+    private static final int PID_BLUE = 3333;
+
     private static final String NAME_COLORS = "colors";
 
     private static ApplicationInfo buildApplicationInfo(String packageName, int uid) {
@@ -74,6 +80,8 @@
         LocalServices.addService(PackageManagerInternal.class, mPmi);
         LocalServices.removeServiceForTest(UserManagerInternal.class);
         LocalServices.addService(UserManagerInternal.class, mUmi);
+        LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+        LocalServices.addService(ActivityManagerInternal.class, mAmi);
 
         when(mContext.getPackageManager()).thenReturn(mPm);
 
@@ -86,37 +94,52 @@
         when(mPmi.getPackagesForSharedUserId(eq(NAME_COLORS), anyInt()))
                 .thenReturn(new String[] { PKG_RED, PKG_BLUE });
 
+        when(mPm.getPackagesForUid(eq(UID_GREY))).thenReturn(new String[] { PKG_GREY });
+        when(mPm.getPackagesForUid(eq(UID_COLORS))).thenReturn(new String[] { PKG_RED, PKG_BLUE });
+
+        setIsAppStorageSandboxed(PID_BLUE, UID_COLORS, true);
+        setIsAppStorageSandboxed(PID_GREY, UID_GREY, true);
+        setIsAppStorageSandboxed(PID_RED, UID_COLORS, true);
+
         mService = new StorageManagerService(mContext);
     }
 
+    private void setIsAppStorageSandboxed(int pid, int uid, boolean sandboxed) {
+        when(mAmi.isAppStorageSandboxed(pid, uid)).thenReturn(sandboxed);
+    }
+
     @Test
     public void testNone() throws Exception {
         assertTranslation(
                 "/dev/null",
-                "/dev/null", PKG_GREY);
+                "/dev/null", PID_GREY, UID_GREY);
         assertTranslation(
                 "/dev/null",
-                "/dev/null", PKG_RED);
+                "/dev/null", PID_RED, UID_COLORS);
     }
 
     @Test
     public void testPrimary() throws Exception {
         assertTranslation(
                 "/storage/emulated/0/Android/sandbox/com.grey/foo.jpg",
-                "/storage/emulated/0/foo.jpg", PKG_GREY);
+                "/storage/emulated/0/foo.jpg",
+                PID_GREY, UID_GREY);
         assertTranslation(
-                "/storage/emulated/0/Android/sandbox/shared:colors/foo.jpg",
-                "/storage/emulated/0/foo.jpg", PKG_RED);
+                "/storage/emulated/0/Android/sandbox/shared-colors/foo.jpg",
+                "/storage/emulated/0/foo.jpg",
+                PID_RED, UID_COLORS);
     }
 
     @Test
     public void testSecondary() throws Exception {
         assertTranslation(
                 "/storage/0000-0000/Android/sandbox/com.grey/foo/bar.jpg",
-                "/storage/0000-0000/foo/bar.jpg", PKG_GREY);
+                "/storage/0000-0000/foo/bar.jpg",
+                PID_GREY, UID_GREY);
         assertTranslation(
-                "/storage/0000-0000/Android/sandbox/shared:colors/foo/bar.jpg",
-                "/storage/0000-0000/foo/bar.jpg", PKG_RED);
+                "/storage/0000-0000/Android/sandbox/shared-colors/foo/bar.jpg",
+                "/storage/0000-0000/foo/bar.jpg",
+                PID_RED, UID_COLORS);
     }
 
     @Test
@@ -124,13 +147,15 @@
         // Accessing their own paths goes straight through
         assertTranslation(
                 "/storage/emulated/0/Android/data/com.grey/foo.jpg",
-                "/storage/emulated/0/Android/data/com.grey/foo.jpg", PKG_GREY);
+                "/storage/emulated/0/Android/data/com.grey/foo.jpg",
+                PID_GREY, UID_GREY);
 
         // Accessing other package paths goes into sandbox
         assertTranslation(
-                "/storage/emulated/0/Android/sandbox/shared:colors/"
+                "/storage/emulated/0/Android/sandbox/shared-colors/"
                         + "Android/data/com.grey/foo.jpg",
-                "/storage/emulated/0/Android/data/com.grey/foo.jpg", PKG_RED);
+                "/storage/emulated/0/Android/data/com.grey/foo.jpg",
+                PID_RED, UID_COLORS);
     }
 
     @Test
@@ -138,16 +163,19 @@
         // Accessing their own paths goes straight through
         assertTranslation(
                 "/storage/emulated/0/Android/data/com.red/foo.jpg",
-                "/storage/emulated/0/Android/data/com.red/foo.jpg", PKG_RED);
+                "/storage/emulated/0/Android/data/com.red/foo.jpg",
+                PID_RED, UID_COLORS);
         assertTranslation(
                 "/storage/emulated/0/Android/data/com.red/foo.jpg",
-                "/storage/emulated/0/Android/data/com.red/foo.jpg", PKG_BLUE);
+                "/storage/emulated/0/Android/data/com.red/foo.jpg",
+                PID_BLUE, UID_COLORS);
 
         // Accessing other package paths goes into sandbox
         assertTranslation(
                 "/storage/emulated/0/Android/sandbox/com.grey/"
                         + "Android/data/com.red/foo.jpg",
-                "/storage/emulated/0/Android/data/com.red/foo.jpg", PKG_GREY);
+                "/storage/emulated/0/Android/data/com.red/foo.jpg",
+                PID_GREY, UID_GREY);
     }
 
     @Test
@@ -156,7 +184,7 @@
         try {
             mService.translateAppToSystem(
                     "/storage/emulated/0/../foo.jpg",
-                    PKG_GREY, UserHandle.USER_SYSTEM);
+                    PID_GREY, UID_GREY);
             fail();
         } catch (SecurityException expected) {
         }
@@ -165,7 +193,7 @@
         try {
             mService.translateSystemToApp(
                     "/storage/emulated/0/foo.jpg",
-                    PKG_GREY, UserHandle.USER_SYSTEM);
+                    PID_GREY, UID_GREY);
             fail();
         } catch (SecurityException expected) {
         }
@@ -173,18 +201,34 @@
         // Sandboxes can't see paths in other sandboxes
         try {
             mService.translateSystemToApp(
-                    "/storage/emulated/0/Android/sandbox/shared:colors/foo.jpg",
-                    PKG_GREY, UserHandle.USER_SYSTEM);
+                    "/storage/emulated/0/Android/sandbox/shared-colors/foo.jpg",
+                    PID_GREY, UID_GREY);
             fail();
         } catch (SecurityException expected) {
         }
     }
 
-    private void assertTranslation(String system, String sandbox, String packageName)
-            throws Exception {
+    @Test
+    public void testPackageNotSandboxed() throws Exception {
+        setIsAppStorageSandboxed(PID_RED, UID_COLORS, false);
+
+        // Both app and system have the same view
+        assertTranslation(
+                "/storage/emulated/0/Android/data/com.red/foo.jpg",
+                "/storage/emulated/0/Android/data/com.red/foo.jpg",
+                PID_RED, UID_COLORS);
+
+        assertTranslation(
+                "/storage/emulated/0/Android/sandbox/com.grey/bar.jpg",
+                "/storage/emulated/0/Android/sandbox/com.grey/bar.jpg",
+                PID_RED, UID_COLORS);
+    }
+
+    private void assertTranslation(String system, String sandbox,
+            int pid, int uid) throws Exception {
         assertEquals(system,
-                mService.translateAppToSystem(sandbox, packageName, UserHandle.USER_SYSTEM));
+                mService.translateAppToSystem(sandbox, pid, uid));
         assertEquals(sandbox,
-                mService.translateSystemToApp(system, packageName, UserHandle.USER_SYSTEM));
+                mService.translateSystemToApp(system, pid, uid));
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java b/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
deleted file mode 100644
index c162c3b..0000000
--- a/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2018 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 static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import android.content.ContentResolver;
-import android.provider.Settings;
-import android.test.mock.MockContentResolver;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.util.Preconditions;
-import com.android.internal.util.test.FakeSettingsProvider;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Tests for {@link GlobalSettingsToPropertiesMapper}
- *
- * Build/Install/Run:
- *  atest FrameworksServicesTests:GlobalSettingsToPropertiesMapperTest
- */
-@SmallTest
-public class GlobalSettingsToPropertiesMapperTest {
-    private static final String[][] TEST_MAPPING = new String[][] {
-        {Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "TestProperty"}
-    };
-
-    private TestMapper mTestMapper;
-    private MockContentResolver mMockContentResolver;
-
-    @Before
-    public void setup() {
-        // Use FakeSettingsProvider to not affect global state
-        mMockContentResolver = new MockContentResolver(getInstrumentation().getTargetContext());
-        mMockContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
-        mTestMapper = new TestMapper(mMockContentResolver);
-    }
-
-    @Test
-    public void testUpdatePropertiesFromGlobalSettings() {
-        Settings.Global.putString(mMockContentResolver,
-                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue");
-
-        mTestMapper.updatePropertiesFromGlobalSettings();
-        String propValue = mTestMapper.systemPropertiesGet("TestProperty");
-        assertEquals("testValue", propValue);
-
-        Settings.Global.putString(mMockContentResolver,
-                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue2");
-        mTestMapper.updatePropertyFromSetting(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
-                "TestProperty");
-        propValue = mTestMapper.systemPropertiesGet("TestProperty");
-        assertEquals("testValue2", propValue);
-
-        Settings.Global.putString(mMockContentResolver,
-                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, null);
-        mTestMapper.updatePropertyFromSetting(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
-                "TestProperty");
-        propValue = mTestMapper.systemPropertiesGet("TestProperty");
-        assertEquals("", propValue);
-    }
-
-    @Test
-    public void testUpdatePropertiesFromGlobalSettings_PropertyAndSettingNotPresent() {
-        // Test that empty property will not not be set if setting is not set
-        mTestMapper.updatePropertiesFromGlobalSettings();
-        String propValue = mTestMapper.systemPropertiesGet("TestProperty");
-        assertNull("Property should not be set if setting is null", propValue);
-    }
-
-    private static class TestMapper extends GlobalSettingsToPropertiesMapper {
-        private final Map<String, String> mProps = new HashMap<>();
-
-        TestMapper(ContentResolver contentResolver) {
-            super(contentResolver, TEST_MAPPING);
-        }
-
-        @Override
-        protected String systemPropertiesGet(String key) {
-            Preconditions.checkNotNull(key);
-            return mProps.get(key);
-        }
-
-        @Override
-        protected void systemPropertiesSet(String key, String value) {
-            Preconditions.checkNotNull(value);
-            Preconditions.checkNotNull(key);
-            mProps.put(key, value);
-        }
-    }
-}
-
diff --git a/services/tests/servicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java b/services/tests/servicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java
new file mode 100644
index 0000000..d965f8a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2018 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.content.ContentResolver;
+import android.provider.Settings;
+import android.test.mock.MockContentResolver;
+import android.text.TextUtils;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.test.FakeSettingsProvider;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Tests for {@link SettingsToPropertiesMapper}
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SettingsToPropertiesMapperTest {
+    private static final String NAME_VALID_CHARACTERS_REGEX = "^[\\w\\.\\-@:]*$";
+    private static final String[] TEST_MAPPING = new String[] {
+            Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS
+    };
+
+    private TestMapper mTestMapper;
+    private MockContentResolver mMockContentResolver;
+
+    @Before
+    public void setupForEach() {
+        // Use FakeSettingsProvider to not affect global state
+        mMockContentResolver = new MockContentResolver(InstrumentationRegistry.getContext());
+        mMockContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+        mTestMapper = new TestMapper(mMockContentResolver);
+    }
+
+    @Test
+    public void validateRegisteredGlobalSettings() {
+        HashSet<String> hashSet = new HashSet<>();
+        for (String globalSetting : SettingsToPropertiesMapper.sGlobalSettings) {
+            if (hashSet.contains(globalSetting)) {
+                Assert.fail("globalSetting "
+                        + globalSetting
+                        + " is registered more than once in "
+                        + "SettingsToPropertiesMapper.sGlobalSettings.");
+            }
+            hashSet.add(globalSetting);
+            if (TextUtils.isEmpty(globalSetting)) {
+                Assert.fail("empty globalSetting registered.");
+            }
+            if (!globalSetting.matches(NAME_VALID_CHARACTERS_REGEX)) {
+                Assert.fail(globalSetting + " contains invalid characters. "
+                        + "Only alphanumeric characters, '.', '-', '@', ':' and '_' are valid.");
+            }
+        }
+    }
+
+    @Test
+    public void testUpdatePropertiesFromSettings() {
+        Settings.Global.putString(mMockContentResolver,
+                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue");
+
+        String systemPropertyName = "persist.device_config.global_settings."
+                + "sqlite_compatibility_wal_flags";
+
+        mTestMapper.updatePropertiesFromSettings();
+        String propValue = mTestMapper.systemPropertiesGet(systemPropertyName);
+        Assert.assertEquals("testValue", propValue);
+
+        Settings.Global.putString(mMockContentResolver,
+                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue2");
+        mTestMapper.updatePropertyFromSetting(
+                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
+                systemPropertyName,
+                true);
+        propValue = mTestMapper.systemPropertiesGet(systemPropertyName);
+        Assert.assertEquals("testValue2", propValue);
+
+        Settings.Global.putString(mMockContentResolver,
+                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, null);
+        mTestMapper.updatePropertyFromSetting(
+                Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
+                systemPropertyName,
+                true);
+        propValue = mTestMapper.systemPropertiesGet(systemPropertyName);
+        Assert.assertEquals("", propValue);
+    }
+
+    @Test
+    public void testMakePropertyName() {
+        try {
+            Assert.assertEquals("persist.device_config.test_category.test_flag",
+                    SettingsToPropertiesMapper.makePropertyName("test_category", "test_flag"));
+        } catch (Exception e) {
+            Assert.fail("Unexpected exception: " + e.getMessage());
+        }
+
+        try {
+            Assert.assertEquals(null,
+                    SettingsToPropertiesMapper.makePropertyName("test_category!!!", "test_flag"));
+        } catch (Exception e) {
+            Assert.fail("Unexpected exception: " + e.getMessage());
+        }
+
+        try {
+            Assert.assertEquals(null,
+                    SettingsToPropertiesMapper.makePropertyName("test_category", ".test_flag"));
+        } catch (Exception e) {
+            Assert.fail("Unexpected exception: " + e.getMessage());
+        }
+    }
+
+    @Test
+    public void testUpdatePropertiesFromSettings_PropertyAndSettingNotPresent() {
+        // Test that empty property will not not be set if setting is not set
+        mTestMapper.updatePropertiesFromSettings();
+        String propValue = mTestMapper.systemPropertiesGet("TestProperty");
+        Assert.assertNull("Property should not be set if setting is null", propValue);
+    }
+
+    @Test
+    public void testIsNativeFlagsResetPerformed() {
+        mTestMapper.systemPropertiesSet("device_config.reset_performed", "true");
+        Assert.assertTrue(mTestMapper.isNativeFlagsResetPerformed());
+
+        mTestMapper.systemPropertiesSet("device_config.reset_performed", "false");
+        Assert.assertFalse(mTestMapper.isNativeFlagsResetPerformed());
+
+        mTestMapper.systemPropertiesSet("device_config.reset_performed", "");
+        Assert.assertFalse(mTestMapper.isNativeFlagsResetPerformed());
+    }
+
+    @Test
+    public void testGetResetNativeCategories() {
+        mTestMapper.systemPropertiesSet("device_config.reset_performed", "");
+        Assert.assertEquals(mTestMapper.getResetNativeCategories().length, 0);
+
+        mTestMapper.systemPropertiesSet("device_config.reset_performed", "true");
+        mTestMapper.setFileContent("");
+        Assert.assertEquals(mTestMapper.getResetNativeCategories().length, 0);
+
+        mTestMapper.systemPropertiesSet("device_config.reset_performed", "true");
+        mTestMapper.setFileContent("persist.device_config.category1.flag;"
+                + "persist.device_config.category2.flag;persist.device_config.category3.flag;"
+                + "persist.device_config.category3.flag2");
+        List<String> categories = Arrays.asList(mTestMapper.getResetNativeCategories());
+        Assert.assertEquals(3, categories.size());
+        Assert.assertTrue(categories.contains("category1"));
+        Assert.assertTrue(categories.contains("category2"));
+        Assert.assertTrue(categories.contains("category3"));
+    }
+
+    private static class TestMapper extends SettingsToPropertiesMapper {
+        private final Map<String, String> mProps = new HashMap<>();
+
+        private String mFileContent = "";
+
+        TestMapper(ContentResolver contentResolver) {
+            super(contentResolver, TEST_MAPPING, new String[] {});
+        }
+
+        @Override
+        protected String systemPropertiesGet(String key) {
+            Preconditions.checkNotNull(key);
+            return mProps.get(key);
+        }
+
+        @Override
+        protected void systemPropertiesSet(String key, String value) {
+            Preconditions.checkNotNull(value);
+            Preconditions.checkNotNull(key);
+            mProps.put(key, value);
+        }
+
+        protected void setFileContent(String fileContent) {
+            mFileContent = fileContent;
+        }
+
+        @Override
+        protected String getResetFlagsFileContent() {
+            return mFileContent;
+        }
+    }
+}
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 2b5b812..a847b6a 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -38,12 +38,13 @@
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.security.KeyChain;
-import android.support.annotation.NonNull;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
 import android.util.Pair;
 import android.view.IWindowManager;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.net.NetworkPolicyManagerInternal;
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 213961c..be00bb6 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -30,11 +30,12 @@
 import android.os.Handler;
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
-import android.support.annotation.NonNull;
 import android.test.mock.MockContext;
 import android.util.ArrayMap;
 import android.util.ExceptionUtils;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.util.FunctionalUtils;
 
 import org.junit.Assert;
diff --git a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
index e62e07d..6b7634d 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
@@ -29,6 +29,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.os.Build;
 import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
@@ -47,6 +48,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@Presubmit
 public class JobSetTest {
     private static final String TAG = JobSetTest.class.getSimpleName();
     private static final int SECONDARY_USER_ID_1 = 12;
@@ -64,6 +66,7 @@
         final PackageManagerInternal pm = mock(PackageManagerInternal.class);
         when(pm.getPackageTargetSdkVersion(anyString()))
                 .thenReturn(Build.VERSION_CODES.CUR_DEVELOPMENT);
+        LocalServices.removeServiceForTest(PackageManagerInternal.class);
         LocalServices.addService(PackageManagerInternal.class, pm);
         assumeFalse("Test cannot run in user " + mContext.getUserId(),
                 mContext.getUserId() == SECONDARY_USER_ID_1
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index b0b7def..58c4bbf 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -15,7 +15,10 @@
  */
 package com.android.server.pm;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -38,12 +41,12 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import libcore.io.IoUtils;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import libcore.io.IoUtils;
-
 import java.io.File;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
@@ -461,6 +464,7 @@
         pkg.services.add(new PackageParser.Service(dummy, new ServiceInfo()));
         pkg.instrumentation.add(new PackageParser.Instrumentation(dummy, new InstrumentationInfo()));
         pkg.requestedPermissions.add("foo7");
+        pkg.implicitPermissions.add("foo25");
 
         pkg.protectedBroadcasts = new ArrayList<>();
         pkg.protectedBroadcasts.add("foo8");
@@ -490,7 +494,7 @@
         pkg.usesLibraryFiles = new String[] { "foo13"};
 
         pkg.usesLibraryInfos = new ArrayList<>();
-        pkg.usesLibraryInfos.add(new SharedLibraryInfo(null, null, null, 0L, 0, null, null));
+        pkg.usesLibraryInfos.add(new SharedLibraryInfo(null, null, null, 0L, 0, null, null, null));
 
         pkg.mOriginalPackages = new ArrayList<>();
         pkg.mOriginalPackages.add("foo14");
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
index 553d234..c6be1c0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
@@ -16,6 +16,10 @@
 
 package com.android.server.pm;
 
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_IGNORED;
+import static android.app.AppOpsManager.OP_PLAY_AUDIO;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -35,12 +39,14 @@
 import android.content.pm.PackageManager;
 import android.content.pm.SuspendDialogInfo;
 import android.content.res.Resources;
+import android.media.AudioAttributes;
 import android.os.BaseBundle;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
@@ -54,6 +60,8 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.app.IAppOpsCallback;
+import com.android.internal.app.IAppOpsService;
 import com.android.servicestests.apps.suspendtestapp.SuspendTestActivity;
 import com.android.servicestests.apps.suspendtestapp.SuspendTestReceiver;
 
@@ -550,6 +558,32 @@
         assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
     }
 
+    @Test
+    public void testAudioOpBlockedOnSuspend() throws Exception {
+        final IAppOpsService iAppOps = IAppOpsService.Stub.asInterface(
+                ServiceManager.getService(Context.APP_OPS_SERVICE));
+        final CountDownLatch latch = new CountDownLatch(1);
+        final IAppOpsCallback watcher = new IAppOpsCallback.Stub() {
+            @Override
+            public void opChanged(int op, int uid, String packageName) {
+                if (op == OP_PLAY_AUDIO && packageName.equals(TEST_APP_PACKAGE_NAME)) {
+                    latch.countDown();
+                }
+            }
+        };
+        iAppOps.startWatchingMode(OP_PLAY_AUDIO, TEST_APP_PACKAGE_NAME, watcher);
+        final int testPackageUid = mPackageManager.getPackageUid(TEST_APP_PACKAGE_NAME, 0);
+        int audioOpMode = iAppOps.checkAudioOperation(OP_PLAY_AUDIO,
+                AudioAttributes.USAGE_UNKNOWN, testPackageUid, TEST_APP_PACKAGE_NAME);
+        assertEquals("Audio muted for unsuspended package", MODE_ALLOWED, audioOpMode);
+        suspendTestPackage(null, null, null);
+        assertTrue("AppOpsWatcher did not callback", latch.await(5, TimeUnit.SECONDS));
+        audioOpMode = iAppOps.checkAudioOperation(OP_PLAY_AUDIO,
+                AudioAttributes.USAGE_UNKNOWN, testPackageUid, TEST_APP_PACKAGE_NAME);
+        assertEquals("Audio not muted for suspended package", MODE_IGNORED, audioOpMode);
+        iAppOps.stopWatchingMode(watcher);
+    }
+
     @After
     public void tearDown() throws IOException {
         mAppCommsReceiver.unregister();
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
index 416a616..dad7b93 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -68,6 +68,7 @@
     private static final String PATH_CLASS_LOADER_NAME = PathClassLoader.class.getName();
     private static final String DELEGATE_LAST_CLASS_LOADER_NAME =
             DelegateLastClassLoader.class.getName();
+    private static final String UNSUPPORTED_CLASS_LOADER_NAME = "unsupported.class_loader";
 
     @Rule public MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
     @Mock Installer mInstaller;
@@ -105,7 +106,7 @@
         mDoesNotExist = new TestData("DOES.NOT.EXIST", isa, mUser1);
 
         mBarUser0UnsupportedClassLoader = new TestData(bar, isa, mUser0,
-                "unsupported.class_loader");
+                UNSUPPORTED_CLASS_LOADER_NAME);
         mBarUser0DelegateLastClassLoader = new TestData(bar, isa, mUser0,
                 DELEGATE_LAST_CLASS_LOADER_NAME);
 
@@ -401,15 +402,25 @@
         List<String> secondaries = mBarUser0UnsupportedClassLoader.getSecondaryDexPaths();
         notifyDexLoad(mBarUser0UnsupportedClassLoader, secondaries, mUser0);
 
-        PackageUseInfo pui = getPackageUseInfo(mBarUser0UnsupportedClassLoader);
-        assertIsUsedByOtherApps(mBarUser0UnsupportedClassLoader, pui, false);
-        assertEquals(secondaries.size(), pui.getDexUseInfoMap().size());
-        // We expect that all the contexts are unsupported.
-        String[] expectedContexts =
-                Collections.nCopies(secondaries.size(),
-                        PackageDexUsage.UNSUPPORTED_CLASS_LOADER_CONTEXT).toArray(new String[0]);
-        assertSecondaryUse(mBarUser0UnsupportedClassLoader, pui, secondaries,
-                /*isUsedByOtherApps*/false, mUser0, expectedContexts);
+        assertNoUseInfo(mBarUser0UnsupportedClassLoader);
+    }
+
+    @Test
+    public void testNotifySupportedAndUnsupportedClassLoader() {
+        String classPath = String.join(File.pathSeparator, mBarUser0.getSecondaryDexPaths());
+        List<String> classLoaders =
+                Arrays.asList(PATH_CLASS_LOADER_NAME, UNSUPPORTED_CLASS_LOADER_NAME);
+        List<String> classPaths = Arrays.asList(classPath, classPath);
+        notifyDexLoad(mBarUser0, classLoaders, classPaths, mUser0);
+
+        assertNoUseInfo(mBarUser0);
+    }
+
+    @Test
+    public void testNotifyNullClassPath() {
+        notifyDexLoad(mBarUser0, null, mUser0);
+
+        assertNoUseInfo(mBarUser0);
     }
 
     @Test
@@ -438,27 +449,18 @@
     }
 
     @Test
-    public void testNotifyUnsupportedClassLoaderDoesNotChange() {
-        List<String> secondaries = mBarUser0UnsupportedClassLoader.getSecondaryDexPaths();
+    public void testNotifyUnsupportedClassLoaderDoesNotChangeExisting() {
+        List<String> secondaries = mBarUser0.getSecondaryDexPaths();
+
+        notifyDexLoad(mBarUser0, secondaries, mUser0);
+        PackageUseInfo pui = getPackageUseInfo(mBarUser0);
+        assertSecondaryUse(mBarUser0, pui, secondaries, /*isUsedByOtherApps*/false, mUser0);
+
+        // Record bar secondaries again with an unsupported class loader. This should not change the
+        // context.
         notifyDexLoad(mBarUser0UnsupportedClassLoader, secondaries, mUser0);
-
-        PackageUseInfo pui = getPackageUseInfo(mBarUser0UnsupportedClassLoader);
-        assertIsUsedByOtherApps(mBarUser0UnsupportedClassLoader, pui, false);
-        assertEquals(secondaries.size(), pui.getDexUseInfoMap().size());
-        // We expect that all the contexts are unsupported.
-        String[] expectedContexts =
-                Collections.nCopies(secondaries.size(),
-                        PackageDexUsage.UNSUPPORTED_CLASS_LOADER_CONTEXT).toArray(new String[0]);
-        assertSecondaryUse(mBarUser0UnsupportedClassLoader, pui, secondaries,
-                /*isUsedByOtherApps*/false, mUser0, expectedContexts);
-
-        // Record bar secondaries again with a different class loader. This will change the context.
-        // However, because the context was already marked as unsupported we should not chage it.
-        notifyDexLoad(mBarUser0DelegateLastClassLoader, secondaries, mUser0);
-        pui = getPackageUseInfo(mBarUser0UnsupportedClassLoader);
-        assertSecondaryUse(mBarUser0UnsupportedClassLoader, pui, secondaries,
-                /*isUsedByOtherApps*/false, mUser0, expectedContexts);
-
+        pui = getPackageUseInfo(mBarUser0);
+        assertSecondaryUse(mBarUser0, pui, secondaries, /*isUsedByOtherApps*/false, mUser0);
     }
 
     @Test
@@ -516,14 +518,17 @@
         // By default, assume a single class loader in the chain.
         // This makes writing tests much easier.
         List<String> classLoaders = Arrays.asList(testData.mClassLoader);
-        List<String> classPaths = Arrays.asList(String.join(File.pathSeparator, dexPaths));
+        List<String> classPaths = (dexPaths == null)
+                                  ? Arrays.asList((String) null)
+                                  : Arrays.asList(String.join(File.pathSeparator, dexPaths));
         notifyDexLoad(testData, classLoaders, classPaths, loaderUserId);
     }
 
-    private void notifyDexLoad(TestData testData, List<String> classLoader, List<String> classPaths,
-            int loaderUserId) {
-        mDexManager.notifyDexLoad(testData.mPackageInfo.applicationInfo, classLoader, classPaths,
-                testData.mLoaderIsa, loaderUserId);
+    private void notifyDexLoad(TestData testData, List<String> classLoaders,
+            List<String> classPaths, int loaderUserId) {
+        // We call the internal function so any exceptions thrown cause test failures.
+        mDexManager.notifyDexLoadInternal(testData.mPackageInfo.applicationInfo, classLoaders,
+                classPaths, testData.mLoaderIsa, loaderUserId);
     }
 
     private PackageUseInfo getPackageUseInfo(TestData testData) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
index 77f517b..cd15a57 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
@@ -353,6 +353,18 @@
     }
 
     @Test
+    public void testProcessContextForDexLoadNoClassPath() {
+        List<String> classLoaders = Arrays.asList(
+                DELEGATE_LAST_CLASS_LOADER_NAME,
+                PATH_CLASS_LOADER_NAME);
+        List<String> classPaths = Arrays.asList(
+                String.join(File.pathSeparator, "foo.dex", "bar.dex"),
+                null);
+        String[] context = DexoptUtils.processContextForDexLoad(classLoaders, classPaths);
+        assertNull(context);
+    }
+
+    @Test
     public void testProcessContextForDexLoadIllegalCallEmptyList() {
         boolean gotException = false;
         try {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
index 3e93dcf..7755e94 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
@@ -399,20 +399,6 @@
     }
 
     @Test
-    public void testRecordClassLoaderContextUnsupportedContext() {
-        // Record a secondary dex file.
-        assertTrue(record(mFooSecondary1User0));
-        // Now update its context.
-        TestData unsupportedContext = mFooSecondary1User0.updateClassLoaderContext(
-                PackageDexUsage.UNSUPPORTED_CLASS_LOADER_CONTEXT);
-        assertTrue(record(unsupportedContext));
-
-        assertPackageDexUsage(null, unsupportedContext);
-        writeAndReadBack();
-        assertPackageDexUsage(null, unsupportedContext);
-    }
-
-    @Test
     public void testRecordClassLoaderContextTransitionFromUnknown() {
         // Record a secondary dex file.
         TestData unknownContext = mFooSecondary1User0.updateClassLoaderContext(
@@ -440,29 +426,41 @@
         PackageDexUsage.DexUseInfo validContext = new DexUseInfo(isUsedByOtherApps, userId,
                 "valid_context", "arm");
         assertFalse(validContext.isUnknownClassLoaderContext());
-        assertFalse(validContext.isUnsupportedClassLoaderContext());
         assertFalse(validContext.isVariableClassLoaderContext());
 
-        PackageDexUsage.DexUseInfo unsupportedContext = new DexUseInfo(isUsedByOtherApps, userId,
-                PackageDexUsage.UNSUPPORTED_CLASS_LOADER_CONTEXT, "arm");
-        assertFalse(unsupportedContext.isUnknownClassLoaderContext());
-        assertTrue(unsupportedContext.isUnsupportedClassLoaderContext());
-        assertFalse(unsupportedContext.isVariableClassLoaderContext());
-
         PackageDexUsage.DexUseInfo variableContext = new DexUseInfo(isUsedByOtherApps, userId,
                 PackageDexUsage.VARIABLE_CLASS_LOADER_CONTEXT, "arm");
         assertFalse(variableContext.isUnknownClassLoaderContext());
-        assertFalse(variableContext.isUnsupportedClassLoaderContext());
         assertTrue(variableContext.isVariableClassLoaderContext());
 
         PackageDexUsage.DexUseInfo unknownContext = new DexUseInfo(isUsedByOtherApps, userId,
                 PackageDexUsage.UNKNOWN_CLASS_LOADER_CONTEXT, "arm");
         assertTrue(unknownContext.isUnknownClassLoaderContext());
-        assertFalse(unknownContext.isUnsupportedClassLoaderContext());
         assertFalse(unknownContext.isVariableClassLoaderContext());
     }
 
     @Test
+    public void testUnsupportedClassLoaderDiscardedOnRead() throws Exception {
+        String content = "PACKAGE_MANAGER__PACKAGE_DEX_USAGE__2\n"
+                + mBarSecondary1User0.mPackageName + "\n"
+                + "#" + mBarSecondary1User0.mDexFile + "\n"
+                + "0,0," + mBarSecondary1User0.mLoaderIsa + "\n"
+                + "@\n"
+                + "=UnsupportedClassLoaderContext=\n"
+
+                + mFooSecondary1User0.mPackageName + "\n"
+                + "#" + mFooSecondary1User0.mDexFile + "\n"
+                + "0,0," + mFooSecondary1User0.mLoaderIsa + "\n"
+                + "@\n"
+                + mFooSecondary1User0.mClassLoaderContext + "\n";
+
+        mPackageDexUsage.read(new StringReader(content));
+
+        assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0);
+        assertPackageDexUsage(mBarBaseUser0);
+    }
+
+    @Test
     public void testReadVersion1() {
         String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
         // Equivalent to
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
index fd04970..f31ca55 100644
--- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
@@ -115,7 +115,12 @@
             mTarget.setSettingsLocked(
                     mPersistedState.global.getOrDefault(Global.LOW_POWER_MODE, 0) != 0,
                     mPersistedState.global.getOrDefault(Global.LOW_POWER_MODE_STICKY, 0) != 0,
-                    mDevice.getLowPowerModeTriggerLevel());
+                    mDevice.getLowPowerModeTriggerLevel(),
+                    mPersistedState.global.getOrDefault(Global.AUTOMATIC_POWER_SAVER_MODE, 0),
+                    mPersistedState.global.getOrDefault(
+                            Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0) != 0,
+                    mPersistedState.global.getOrDefault(
+                            Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 100));
         }
 
         public void putGlobalSetting(String key, int value) {
@@ -174,6 +179,9 @@
         when(mMockResources.getBoolean(
                 com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled))
                 .thenReturn(false);
+        when(mMockResources.getInteger(
+                com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold))
+                .thenReturn(80);
 
         mPersistedState = new DevicePersistedState();
         initDevice();
@@ -303,6 +311,7 @@
     @Test
     public void testAutoBatterySaver() {
         mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
+        mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 0);
 
         assertEquals(false, mDevice.batterySaverEnabled);
         assertEquals(100, mPersistedState.batteryLevel);
@@ -515,6 +524,7 @@
                 .thenReturn(true);
         initDevice();
         mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
+        mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 0);
 
         mTarget.setBatterySaverEnabledManually(true);
 
@@ -626,4 +636,123 @@
         assertEquals(90, mPersistedState.batteryLevel);
         assertEquals(false, mPersistedState.batteryLow);
     }
+
+    @Test
+    public void testAutoBatterySaver_smartBatterySaverEnabled() {
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 50);
+        mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 1);
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(100, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(90);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(90, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(51);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(51, mPersistedState.batteryLevel);
+
+        // Hit the threshold. BS should be disabled since dynamic power savings still off
+        mDevice.setBatteryLevel(50);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(50, mPersistedState.batteryLevel);
+
+        // dynamic power savings comes on, battery saver should turn on
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 1);
+        mDevice.setBatteryLevel(40);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(40, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(true);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(40, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(false);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(40, mPersistedState.batteryLevel);
+
+        mTarget.setBatterySaverEnabledManually(false); // Manually disable -> snooze.
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(40, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(30);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        // Plug in and out, snooze will reset.
+        mDevice.setPowered(true);
+        mDevice.setPowered(false);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(true);
+        mDevice.setBatteryLevel(60);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(60, mPersistedState.batteryLevel);
+
+        mDevice.setPowered(false);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(60, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(40);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(40, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(70);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(70, mPersistedState.batteryLevel);
+
+        // Bump up the threshold.
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 71);
+        mDevice.setBatteryLevel(mPersistedState.batteryLevel);
+
+        // changes are only registered if some battery level changed
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(70, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(69);
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(69, mPersistedState.batteryLevel);
+
+        // Then down.
+        mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 60);
+        mDevice.setBatteryLevel(mPersistedState.batteryLevel);
+
+        // changes are only registered if battery level changed
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(69, mPersistedState.batteryLevel);
+
+        mDevice.setBatteryLevel(68);
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(68, mPersistedState.batteryLevel);
+
+        // Reboot in low state -> automatically enable BS.
+        mDevice.setPowered(false);
+        mDevice.setBatteryLevel(30);
+        mTarget.setBatterySaverEnabledManually(false);
+
+        assertEquals(false, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+
+        initDevice();
+
+        assertEquals(true, mDevice.batterySaverEnabled);
+        assertEquals(30, mPersistedState.batteryLevel);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index caaa0bb..41d5691 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -129,6 +129,7 @@
 
     static class MyInjector extends AppStandbyController.Injector {
         long mElapsedRealtime;
+        boolean mIsAppIdleEnabled = true;
         boolean mIsCharging;
         List<String> mPowerSaveWhitelistExceptIdle = new ArrayList<>();
         boolean mDisplayOn;
@@ -160,7 +161,7 @@
 
         @Override
         boolean isAppIdleEnabled() {
-            return true;
+            return mIsAppIdleEnabled;
         }
 
         @Override
@@ -277,6 +278,13 @@
         }
     }
 
+    private void setAppIdleEnabled(AppStandbyController controller, boolean enabled) {
+        mInjector.mIsAppIdleEnabled = enabled;
+        if (controller != null) {
+            controller.setAppIdleEnabled(enabled);
+        }
+    }
+
     private AppStandbyController setupController() throws Exception {
         mInjector.mElapsedRealtime = 0;
         setupPm(mInjector.getContext().getPackageManager());
@@ -346,7 +354,7 @@
         public void onParoleStateChanged(boolean isParoleOn) {
             synchronized (this) {
                 // Only record information if it is being looked for
-                if (mLatch.getCount() > 0) {
+                if (mLatch != null && mLatch.getCount() > 0) {
                     mOnParole = isParoleOn;
                     mLastParoleChangeTime = getCurrentTime();
                     mLatch.countDown();
@@ -407,6 +415,74 @@
                 marginOfError);
     }
 
+    @Test
+    public void testEnabledState() throws Exception {
+        TestParoleListener paroleListener = new TestParoleListener();
+        mController.addListener(paroleListener);
+        long lastUpdateTime;
+
+        // Test that listeners are notified if enabled changes when the device is not in parole.
+        setChargingState(mController, false);
+
+        // Start off not enabled. Device is effectively on permanent parole.
+        setAppIdleEnabled(mController, false);
+
+        // Enable controller
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, true);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertFalse(paroleListener.mOnParole);
+        lastUpdateTime = paroleListener.getLastParoleChangeTime();
+
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, true);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertFalse(paroleListener.mOnParole);
+        // Make sure AppStandbyController doesn't notify listeners when there's no change.
+        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
+
+        // Disable controller
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, false);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertTrue(paroleListener.mOnParole);
+        lastUpdateTime = paroleListener.getLastParoleChangeTime();
+
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, false);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertTrue(paroleListener.mOnParole);
+        // Make sure AppStandbyController doesn't notify listeners when there's no change.
+        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
+
+
+        // Test that listeners aren't notified if enabled status changes when the device is already
+        // in parole.
+
+        // A device is in parole whenever it's charging.
+        setChargingState(mController, true);
+
+        // Start off not enabled.
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, false);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertTrue(paroleListener.mOnParole);
+        lastUpdateTime = paroleListener.getLastParoleChangeTime();
+
+        // Test that toggling doesn't notify the listener.
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, true);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertTrue(paroleListener.mOnParole);
+        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
+
+        paroleListener.rearmLatch();
+        setAppIdleEnabled(mController, false);
+        paroleListener.awaitOnLatch(STABLE_CHARGING_THRESHOLD * 3 / 2);
+        assertTrue(paroleListener.mOnParole);
+        assertEquals(lastUpdateTime, paroleListener.getLastParoleChangeTime());
+    }
+
     private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket) {
         mInjector.mElapsedRealtime = elapsedTime;
         controller.checkIdleStates(USER_ID);
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
index 793d6b0..8496a96 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
@@ -19,12 +19,13 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.app.PendingIntent;
 import android.os.HandlerThread;
 import android.os.Looper;
 
-import androidx.test.filters.MediumTest;
+import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.After;
@@ -32,11 +33,13 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 @RunWith(AndroidJUnit4.class)
-@MediumTest
+@LargeTest
 public class AppTimeLimitControllerTests {
 
     private static final String PKG_SOC1 = "package.soc1";
@@ -159,7 +162,6 @@
         assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
         addUsageSessionObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, TIME_1_MIN);
         assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID2));
-        assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
     }
 
     /** Verify app usage observer is removed */
@@ -180,6 +182,42 @@
         assertFalse("Observer wasn't removed", hasUsageSessionObserver(UID, OBS_ID1));
     }
 
+    /** Verify nothing happens when a nonexistent app usage observer is removed */
+    @Test
+    public void testAppUsageObserver_RemoveMissingObserver() {
+        assertFalse("Observer should not exist", hasAppUsageObserver(UID, OBS_ID1));
+        try {
+            mController.removeAppUsageObserver(UID, OBS_ID1, USER_ID);
+        } catch (Exception e) {
+            StringWriter sw = new StringWriter();
+            sw.write("Hit exception trying to remove nonexistent observer:\n");
+            sw.write(e.toString());
+            PrintWriter pw = new PrintWriter(sw);
+            e.printStackTrace(pw);
+            sw.write("\nTest Failed!");
+            fail(sw.toString());
+        }
+        assertFalse("Observer should not exist", hasAppUsageObserver(UID, OBS_ID1));
+    }
+
+    /** Verify nothing happens when a nonexistent usage session observer is removed */
+    @Test
+    public void testUsageSessionObserver_RemoveMissingObserver() {
+        assertFalse("Observer should not exist", hasUsageSessionObserver(UID, OBS_ID1));
+        try {
+            mController.removeUsageSessionObserver(UID, OBS_ID1, USER_ID);
+        } catch (Exception e) {
+            StringWriter sw = new StringWriter();
+            sw.write("Hit exception trying to remove nonexistent observer:");
+            sw.write(e.toString());
+            PrintWriter pw = new PrintWriter(sw);
+            e.printStackTrace(pw);
+            sw.write("\nTest Failed!");
+            fail(sw.toString());
+        }
+        assertFalse("Observer should not exist", hasUsageSessionObserver(UID, OBS_ID1));
+    }
+
     /** Re-adding an observer should result in only one copy */
     @Test
     public void testAppUsageObserver_ObserverReAdd() {
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
index 473682d..bf7f53d 100644
--- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -16,13 +16,12 @@
 
 package com.android.server.usage;
 
-import static junit.framework.TestCase.assertNull;
 import static junit.framework.TestCase.fail;
 
 import static org.testng.Assert.assertEquals;
 
 import android.app.usage.EventList;
-import android.app.usage.UsageEvents;
+import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
@@ -112,6 +111,8 @@
         long time = System.currentTimeMillis() - (numberOfEvents*timeProgression);
         mIntervalStats = new IntervalStats();
 
+        mIntervalStats.majorVersion = 7;
+        mIntervalStats.minorVersion = 8;
         mIntervalStats.beginTime = time;
         mIntervalStats.interactiveTracker.count = 2;
         mIntervalStats.interactiveTracker.duration = 111111;
@@ -127,41 +128,39 @@
         }
 
         for (int i = 0; i < numberOfEvents; i++) {
-            UsageEvents.Event event = new UsageEvents.Event();
+            Event event = new Event();
             final int packageInt = ((i / 3) % 7);
             event.mPackage = "fake.package.name" + packageInt; //clusters of 3 events from 7 "apps"
             if (packageInt == 3) {
                 // Third app is an instant app
-                event.mFlags |= UsageEvents.Event.FLAG_IS_PACKAGE_INSTANT_APP;
-            } else if (packageInt == 2 || packageInt == 4) {
-                event.mClass = ".fake.class.name" + i % 11;
+                event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
             }
 
-
+            event.mClass = ".fake.class.name" + i % 11;
             event.mTimeStamp = time;
             event.mEventType = i % 19; //"random" event type
 
             switch (event.mEventType) {
-                case UsageEvents.Event.CONFIGURATION_CHANGE:
+                case Event.CONFIGURATION_CHANGE:
                     //empty config,
                     event.mConfiguration = new Configuration();
                     break;
-                case UsageEvents.Event.SHORTCUT_INVOCATION:
+                case Event.SHORTCUT_INVOCATION:
                     //"random" shortcut
                     event.mShortcutId = "shortcut" + (i % 8);
                     break;
-                case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+                case Event.STANDBY_BUCKET_CHANGED:
                     //"random" bucket and reason
                     event.mBucketAndReason = (((i % 5 + 1) * 10) << 16) & (i % 5 + 1) << 8;
                     break;
-                case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+                case Event.NOTIFICATION_INTERRUPTION:
                     //"random" channel
                     event.mNotificationChannelId = "channel" + (i % 5);
                     break;
             }
 
             mIntervalStats.events.insert(event);
-            mIntervalStats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+            mIntervalStats.update(event.mPackage, event.mClass, event.mTimeStamp, event.mEventType);
 
             time += timeProgression; // Arbitrary progression of time
         }
@@ -221,29 +220,30 @@
         // mEndTimeStamp is based on the enclosing IntervalStats, don't bother checking
         assertEquals(us1.mLastTimeUsed, us2.mLastTimeUsed);
         assertEquals(us1.mTotalTimeInForeground, us2.mTotalTimeInForeground);
+        assertEquals(us1.mLastTimeForegroundServiceUsed, us2.mLastTimeForegroundServiceUsed);
+        assertEquals(us1.mTotalTimeForegroundServiceUsed, us2.mTotalTimeForegroundServiceUsed);
         // mLaunchCount not persisted, so skipped
         assertEquals(us1.mAppLaunchCount, us2.mAppLaunchCount);
-        assertEquals(us1.mLastEvent, us2.mLastEvent);
         assertEquals(us1.mChooserCounts, us2.mChooserCounts);
     }
 
-    void compareUsageEvent(UsageEvents.Event e1, UsageEvents.Event e2, int debugId) {
+    void compareUsageEvent(Event e1, Event e2, int debugId) {
         assertEquals(e1.mPackage, e2.mPackage, "Usage event " + debugId);
         assertEquals(e1.mClass, e2.mClass, "Usage event " + debugId);
         assertEquals(e1.mTimeStamp, e2.mTimeStamp, "Usage event " + debugId);
         assertEquals(e1.mEventType, e2.mEventType, "Usage event " + debugId);
         switch (e1.mEventType) {
-            case UsageEvents.Event.CONFIGURATION_CHANGE:
+            case Event.CONFIGURATION_CHANGE:
                 assertEquals(e1.mConfiguration, e2.mConfiguration,
                         "Usage event " + debugId + e2.mConfiguration.toString());
                 break;
-            case UsageEvents.Event.SHORTCUT_INVOCATION:
+            case Event.SHORTCUT_INVOCATION:
                 assertEquals(e1.mShortcutId, e2.mShortcutId, "Usage event " + debugId);
                 break;
-            case UsageEvents.Event.STANDBY_BUCKET_CHANGED:
+            case Event.STANDBY_BUCKET_CHANGED:
                 assertEquals(e1.mBucketAndReason, e2.mBucketAndReason, "Usage event " + debugId);
                 break;
-            case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
+            case Event.NOTIFICATION_INTERRUPTION:
                 assertEquals(e1.mNotificationChannelId, e2.mNotificationChannelId,
                         "Usage event " + debugId);
                 break;
@@ -252,6 +252,8 @@
     }
 
     void compareIntervalStats(IntervalStats stats1, IntervalStats stats2) {
+        assertEquals(stats1.majorVersion, stats2.majorVersion);
+        assertEquals(stats1.minorVersion, stats2.minorVersion);
         assertEquals(stats1.beginTime, stats2.beginTime);
         assertEquals(stats1.endTime, stats2.endTime);
         assertEquals(stats1.interactiveTracker.count, stats2.interactiveTracker.count);
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index a8e1ed4..552390d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -190,7 +190,11 @@
 
     private void performRotation(DisplayRotation spiedRotation, int rotationToReport) {
         doReturn(rotationToReport).when(spiedRotation).rotationForOrientation(anyInt(), anyInt());
+        int oldRotation = mDisplayContent.getRotation();
         mWm.updateRotation(false, false);
+        // Must manually apply here since ATM doesn't know about the display during this test
+        // (meaning it can't perform the normal sendNewConfiguration flow).
+        mDisplayContent.applyRotationLocked(oldRotation, mDisplayContent.getRotation());
         // Prevent the next rotation from being deferred by animation.
         mWm.mAnimator.setScreenRotationAnimationLocked(mDisplayContent.getDisplayId(), null);
         mWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
index b6a7cfb..991981f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
@@ -37,7 +37,7 @@
 
 /**
  * Build/Install/Run:
- *  atest FrameworksServicesTests:DimmerTests;
+ *  atest FrameworksServicesTests:DimmerTests
  */
 @Presubmit
 public class DimmerTests extends WindowTestsBase {
@@ -211,7 +211,7 @@
         mDimmer.updateDims(mTransaction, new Rect());
         verify(mSurfaceAnimatorStarter).startAnimation(any(SurfaceAnimator.class), any(
                 SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean());
-        verify(dimLayer).destroy();
+        verify(mHost.getPendingTransaction()).destroy(dimLayer);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index dd374e9..c1655bc 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -40,6 +40,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.doNothing;
@@ -108,7 +109,7 @@
         final WindowState imeAppTarget =
                 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
 
-        mWm.mInputMethodTarget = imeAppTarget;
+        mDisplayContent.mInputMethodTarget = imeAppTarget;
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -124,8 +125,8 @@
     }
 
     @Test
-    public void testForAllWindows_WithChildWindowImeTarget() {
-        mWm.mInputMethodTarget = mChildAppWindowAbove;
+    public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
+        mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -140,8 +141,8 @@
     }
 
     @Test
-    public void testForAllWindows_WithStatusBarImeTarget() {
-        mWm.mInputMethodTarget = mStatusBarWindow;
+    public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
+        mDisplayContent.mInputMethodTarget = mStatusBarWindow;
 
         assertForAllWindowsOrder(Arrays.asList(
                 mWallpaperWindow,
@@ -230,7 +231,6 @@
      */
     @Test
     public void testDisplayOverrideConfigUpdate() {
-        final int displayId = mDisplayContent.getDisplayId();
         final Configuration currentOverrideConfig = mDisplayContent.getOverrideConfiguration();
 
         // Create new, slightly changed override configuration and apply it to the display.
@@ -238,7 +238,7 @@
         newOverrideConfig.densityDpi += 120;
         newOverrideConfig.fontScale += 0.3;
 
-        mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, displayId);
+        mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, mDisplayContent);
 
         // Check that override config is applied.
         assertEquals(newOverrideConfig, mDisplayContent.getOverrideConfiguration());
@@ -249,14 +249,15 @@
      */
     @Test
     public void testDefaultDisplayOverrideConfigUpdate() {
-        final Configuration currentConfig = mDisplayContent.getConfiguration();
+        DisplayContent defaultDisplay = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
+        final Configuration currentConfig = defaultDisplay.getConfiguration();
 
         // Create new, slightly changed override configuration and apply it to the display.
         final Configuration newOverrideConfig = new Configuration(currentConfig);
         newOverrideConfig.densityDpi += 120;
         newOverrideConfig.fontScale += 0.3;
 
-        mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY);
+        mWm.setNewDisplayOverrideConfiguration(newOverrideConfig, defaultDisplay);
 
         // Check that global configuration is updated, as we've updated default display's config.
         Configuration globalConfig = mWm.mRoot.getConfiguration();
@@ -264,7 +265,7 @@
         assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
 
         // Return back to original values.
-        mWm.setNewDisplayOverrideConfiguration(currentConfig, DEFAULT_DISPLAY);
+        mWm.setNewDisplayOverrideConfiguration(currentConfig, defaultDisplay);
         globalConfig = mWm.mRoot.getConfiguration();
         assertEquals(currentConfig.densityDpi, globalConfig.densityDpi);
         assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
@@ -568,6 +569,32 @@
         assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
     }
 
+    @Test
+    public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
+        final DisplayContent newDisplay = createNewDisplay();
+
+        final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
+        final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
+        appWin.setHasSurface(true);
+        appWin1.setHasSurface(true);
+
+        // Set current input method window on default display, make sure the input method target
+        // is appWin & null on the other display.
+        mDisplayContent.setInputMethodWindowLocked(mImeWindow);
+        newDisplay.setInputMethodWindowLocked(null);
+        assertTrue("appWin should be IME target window",
+                appWin.equals(mDisplayContent.mInputMethodTarget));
+        assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
+
+        // Switch input method window on new display & make sure the input method target also
+        // switched as expected.
+        newDisplay.setInputMethodWindowLocked(mImeWindow);
+        mDisplayContent.setInputMethodWindowLocked(null);
+        assertTrue("appWin1 should be IME target window",
+                appWin1.equals(newDisplay.mInputMethodTarget));
+        assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
+    }
+
     private boolean isOptionsPanelAtRight(int displayId) {
         return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
     }
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
similarity index 70%
rename from services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
rename to services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index f0c49c8..b823e70 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -16,6 +16,9 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY;
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
+
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertEquals;
@@ -43,20 +46,23 @@
 import java.io.File;
 
 /**
- * Tests for the {@link DisplaySettings} class.
+ * Tests for the {@link DisplayWindowSettings} class.
  *
  * Build/Install/Run:
- *  atest FrameworksServicesTests:DisplaySettingsTests
+ *  atest FrameworksServicesTests:DisplayWindowSettingsTests
  */
 @SmallTest
 @Presubmit
-public class DisplaySettingsTests extends WindowTestsBase {
+public class DisplayWindowSettingsTests extends WindowTestsBase {
 
     private static final File TEST_FOLDER = getInstrumentation().getTargetContext().getCacheDir();
-    private DisplaySettings mTarget;
+    private DisplayWindowSettings mTarget;
+
+    DisplayInfo mPrivateDisplayInfo;
 
     private DisplayContent mPrimaryDisplay;
     private DisplayContent mSecondaryDisplay;
+    private DisplayContent mPrivateDisplay;
 
     @Before
     public void setUp() throws Exception {
@@ -64,12 +70,19 @@
 
         mWm.setSupportsFreeformWindowManagement(false);
         mWm.setIsPc(false);
+        mWm.setForceDesktopModeOnExternalDisplays(false);
 
-        mTarget = new DisplaySettings(mWm, TEST_FOLDER);
+        mTarget = new DisplayWindowSettings(mWm, TEST_FOLDER);
 
         mPrimaryDisplay = mWm.getDefaultDisplayContentLocked();
         mSecondaryDisplay = mDisplayContent;
         assertNotEquals(Display.DEFAULT_DISPLAY, mSecondaryDisplay.getDisplayId());
+
+        mPrivateDisplayInfo = new DisplayInfo(mDisplayInfo);
+        mPrivateDisplayInfo.flags |= Display.FLAG_PRIVATE;
+        mPrivateDisplay = createNewDisplay(mPrivateDisplayInfo);
+        assertNotEquals(Display.DEFAULT_DISPLAY, mPrivateDisplay.getDisplayId());
+        assertNotEquals(mSecondaryDisplay.getDisplayId(), mPrivateDisplay.getDisplayId());
     }
 
     @After
@@ -78,7 +91,7 @@
     }
 
     @Test
-    public void testPrimaryDisplayDefaultToFullscreenWithoutFreeformSupport() {
+    public void testPrimaryDisplayDefaultToFullscreen_NoFreeformSupport() {
         mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
 
         assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
@@ -86,7 +99,7 @@
     }
 
     @Test
-    public void testPrimaryDisplayDefaultToFullscreenWithFreeformSupportNonPc() {
+    public void testPrimaryDisplayDefaultToFullscreen_HasFreeformSupport_NonPc_NoDesktopMode() {
         mWm.setSupportsFreeformWindowManagement(true);
 
         mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
@@ -96,7 +109,18 @@
     }
 
     @Test
-    public void testPrimaryDisplayDefaultToFreeformWithFreeformIsPc() {
+    public void testPrimaryDisplayDefaultToFullscreen_HasFreeformSupport_NonPc_HasDesktopMode() {
+        mWm.setSupportsFreeformWindowManagement(true);
+        mWm.setForceDesktopModeOnExternalDisplays(true);
+
+        mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+        assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+                mPrimaryDisplay.getWindowingMode());
+    }
+
+    @Test
+    public void testPrimaryDisplayDefaultToFreeform_HasFreeformSupport_IsPc() {
         mWm.setSupportsFreeformWindowManagement(true);
         mWm.setIsPc(true);
 
@@ -107,7 +131,7 @@
     }
 
     @Test
-    public void testSecondaryDisplayDefaultToFullscreenWithoutFreeformSupport() {
+    public void testSecondaryDisplayDefaultToFullscreen_NoFreeformSupport() {
         mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
 
         assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
@@ -115,17 +139,28 @@
     }
 
     @Test
-    public void testSecondaryDisplayDefaultToFreeformWithFreeformSupportNonPc() {
+    public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_NonPc_NoDesktopMode() {
         mWm.setSupportsFreeformWindowManagement(true);
 
         mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
 
+        assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+                mSecondaryDisplay.getWindowingMode());
+    }
+
+    @Test
+    public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_NonPc_HasDesktopMode() {
+        mWm.setSupportsFreeformWindowManagement(true);
+        mWm.setForceDesktopModeOnExternalDisplays(true);
+
+        mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
         assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM,
                 mSecondaryDisplay.getWindowingMode());
     }
 
     @Test
-    public void testSecondaryDisplayDefaultToFreeformWithFreeformSupportIsPc() {
+    public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_IsPc() {
         mWm.setSupportsFreeformWindowManagement(true);
         mWm.setIsPc(true);
 
@@ -238,6 +273,67 @@
     }
 
     @Test
+    public void testPrivateDisplayDefaultToDestroyContent() {
+        assertEquals(REMOVE_CONTENT_MODE_DESTROY,
+                mTarget.getRemoveContentModeLocked(mPrivateDisplay));
+    }
+
+    @Test
+    public void testPublicDisplayDefaultToMoveToPrimary() {
+        assertEquals(REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY,
+                mTarget.getRemoveContentModeLocked(mSecondaryDisplay));
+    }
+
+    @Test
+    public void testDefaultToNotShowWithInsecureKeyguard() {
+        assertFalse(mTarget.shouldShowWithInsecureKeyguardLocked(mPrivateDisplay));
+        assertFalse(mTarget.shouldShowWithInsecureKeyguardLocked(mSecondaryDisplay));
+    }
+
+    @Test
+    public void testPublicDisplayNotAllowSetShouldShowWithInsecureKeyguard() {
+        mTarget.setShouldShowWithInsecureKeyguardLocked(mSecondaryDisplay, true);
+
+        assertFalse(mTarget.shouldShowWithInsecureKeyguardLocked(mSecondaryDisplay));
+    }
+
+    @Test
+    public void testPrivateDisplayAllowSetShouldShowWithInsecureKeyguard() {
+        mTarget.setShouldShowWithInsecureKeyguardLocked(mPrivateDisplay, true);
+
+        assertTrue(mTarget.shouldShowWithInsecureKeyguardLocked(mPrivateDisplay));
+    }
+
+    @Test
+    public void testPrimaryDisplayShouldShowSystemDecors() {
+        assertTrue(mTarget.shouldShowSystemDecorsLocked(mPrimaryDisplay));
+
+        mTarget.setShouldShowSystemDecorsLocked(mPrimaryDisplay, false);
+
+        // Default display should show system decors
+        assertTrue(mTarget.shouldShowSystemDecorsLocked(mPrimaryDisplay));
+    }
+
+    @Test
+    public void testSecondaryDisplayDefaultToNotShowSystemDecors() {
+        assertFalse(mTarget.shouldShowSystemDecorsLocked(mSecondaryDisplay));
+    }
+
+    @Test
+    public void testPrimaryDisplayShouldShowIme() {
+        assertTrue(mTarget.shouldShowImeLocked(mPrimaryDisplay));
+
+        mTarget.setShouldShowImeLocked(mPrimaryDisplay, false);
+
+        assertTrue(mTarget.shouldShowImeLocked(mPrimaryDisplay));
+    }
+
+    @Test
+    public void testSecondaryDisplayDefaultToNotShowIme() {
+        assertFalse(mTarget.shouldShowImeLocked(mSecondaryDisplay));
+    }
+
+    @Test
     public void testPersistUserRotationModeInSameInstance() {
         mTarget.setUserRotation(mSecondaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
                 Surface.ROTATION_90);
@@ -294,11 +390,11 @@
 
     /**
      * This method helps to ensure read and write persistent settings successfully because the
-     * constructor of {@link DisplaySettings} should read the persistent file from the given path
-     * that also means the previous state must be written correctly.
+     * constructor of {@link DisplayWindowSettings} should read the persistent file from the given
+     * path that also means the previous state must be written correctly.
      */
     private void applySettingsToDisplayByNewInstance(DisplayContent display) {
-        new DisplaySettings(mWm, TEST_FOLDER).applySettingsToDisplayLocked(display);
+        new DisplayWindowSettings(mWm, TEST_FOLDER).applySettingsToDisplayLocked(display);
     }
 
     private static boolean deleteRecursively(File file) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java
deleted file mode 100644
index 62a617d..0000000
--- a/services/tests/servicestests/src/com/android/server/wm/RootWindowContainerTests.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2018 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.wm;
-
-import static org.junit.Assert.assertEquals;
-
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Tests for the {@link RootWindowContainer} class.
- *
- * Build/Install/Run:
- *  atest FrameworksServicesTests:RootWindowContainerTests
- */
-@SmallTest
-@Presubmit
-public class RootWindowContainerTests extends WindowTestsBase {
-    @Test
-    public void testSetDisplayOverrideConfigurationIfNeeded() {
-        synchronized (mWm.mGlobalLock) {
-            // Add first stack we expect to be updated with configuration change.
-            final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
-            stack.getOverrideConfiguration().windowConfiguration.setBounds(new Rect(0, 0, 5, 5));
-
-            // Add second task that will be set for deferred removal that should not be returned
-            // with the configuration change.
-            final TaskStack deferredDeletedStack = createTaskStackOnDisplay(mDisplayContent);
-            deferredDeletedStack.getOverrideConfiguration().windowConfiguration.setBounds(
-                    new Rect(0, 0, 5, 5));
-            deferredDeletedStack.mDeferRemoval = true;
-
-            final Configuration override = new Configuration(
-                    mDisplayContent.getOverrideConfiguration());
-            override.windowConfiguration.setBounds(new Rect(0, 0, 10, 10));
-
-            // Set display override.
-            final int[] results = mWm.mRoot.setDisplayOverrideConfigurationIfNeeded(override,
-                    mDisplayContent.getDisplayId());
-
-            // Ensure only first stack is returned.
-            assertEquals(1, results.length);
-            assertEquals(stack.mStackId, results[0]);
-        }
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index 0f9b825..946ffb60 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -24,6 +24,7 @@
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import android.app.ActivityManager.TaskSnapshot;
+import android.content.ComponentName;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.GraphicBuffer;
@@ -126,9 +127,9 @@
             Canvas c = buffer.lockCanvas();
             c.drawColor(Color.RED);
             buffer.unlockCanvasAndPost(c);
-            return new TaskSnapshot(buffer, ORIENTATION_PORTRAIT, TEST_INSETS,
-                    mScale < 1f /* reducedResolution */, mScale, mIsRealSnapshot, mWindowingMode,
-                    mSystemUiVisibility, mIsTranslucent);
+            return new TaskSnapshot(new ComponentName("", ""), buffer, ORIENTATION_PORTRAIT,
+                    TEST_INSETS, mScale < 1f /* reducedResolution */, mScale, mIsRealSnapshot,
+                    mWindowingMode, mSystemUiVisibility, mIsTranslucent);
         }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index 7c16191..a569b9e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -30,6 +30,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager.TaskSnapshot;
+import android.content.ComponentName;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.GraphicBuffer;
@@ -60,7 +61,7 @@
             int windowFlags, Rect taskBounds) {
         final GraphicBuffer buffer = GraphicBuffer.create(width, height, PixelFormat.RGBA_8888,
                 GraphicBuffer.USAGE_SW_READ_RARELY | GraphicBuffer.USAGE_SW_WRITE_NEVER);
-        final TaskSnapshot snapshot = new TaskSnapshot(buffer,
+        final TaskSnapshot snapshot = new TaskSnapshot(new ComponentName("", ""), buffer,
                 ORIENTATION_PORTRAIT, contentInsets, false, 1.0f, true /* isRealSnapshot */,
                 WINDOWING_MODE_FULLSCREEN, 0 /* systemUiVisibility */, false /* isTranslucent */);
         mSurface = new TaskSnapshotSurface(mWm, new Window(), new Surface(), snapshot, "Test",
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
index e8d0a06..99deeb9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
@@ -53,7 +53,8 @@
     }
 
     @Override
-    public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) throws RemoteException {
+    public void windowFocusChanged(boolean hasFocus, boolean inTouchMode, boolean reportToClient)
+            throws RemoteException {
     }
 
     @Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java
index 4369c96..3643457 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java
@@ -22,6 +22,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOW_CONFIG_ALWAYS_ON_TOP;
 import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
+import static android.app.WindowConfiguration.WINDOW_CONFIG_ROTATION;
 import static android.app.WindowConfiguration.WINDOW_CONFIG_WINDOWING_MODE;
 import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
 
@@ -33,6 +34,7 @@
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.view.DisplayInfo;
+import android.view.Surface;
 
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
@@ -66,11 +68,13 @@
         final WindowConfiguration winConfig2 = config2.windowConfiguration;
         final Configuration config3 = new Configuration();
         final WindowConfiguration winConfig3 = config3.windowConfiguration;
+        final Configuration config4 = new Configuration();
+        final WindowConfiguration winConfig4 = config4.windowConfiguration;
 
         winConfig1.setAppBounds(0, 1, 1, 0);
         winConfig2.setAppBounds(1, 2, 2, 1);
         winConfig3.setAppBounds(winConfig1.getAppBounds());
-
+        winConfig4.setRotation(Surface.ROTATION_90);
 
         assertEquals(CONFIG_WINDOW_CONFIGURATION, config1.diff(config2));
         assertEquals(0, config1.diffPublicOnly(config2));
@@ -86,6 +90,9 @@
                 | WINDOW_CONFIG_ALWAYS_ON_TOP,
                 winConfig1.diff(winConfig2, false /* compareUndefined */));
 
+        assertEquals(WINDOW_CONFIG_ROTATION,
+                winConfig1.diff(winConfig4, false /* compareUndefined */));
+
         assertEquals(0, config1.diff(config3));
         assertEquals(0, config1.diffPublicOnly(config3));
         assertEquals(0, winConfig1.diff(winConfig3, false /* compareUndefined */));
@@ -123,11 +130,18 @@
         winConfig2.setAppBounds(0, 2, 3, 4);
         assertNotEquals(config1.compareTo(config2), 0);
         assertNotEquals(winConfig1.compareTo(winConfig2), 0);
+        winConfig2.setAppBounds(winConfig1.getAppBounds());
 
         // No bounds
         assertEquals(config1.compareTo(blankConfig), -1);
         assertEquals(winConfig1.compareTo(blankWinConfig), -1);
 
+        // Different rotation
+        winConfig2.setRotation(Surface.ROTATION_180);
+        assertNotEquals(config1.compareTo(config2), 0);
+        assertNotEquals(winConfig1.compareTo(winConfig2), 0);
+        winConfig2.setRotation(winConfig1.getRotation());
+
         assertEquals(blankConfig.compareTo(config1), 1);
         assertEquals(blankWinConfig.compareTo(winConfig1), 1);
     }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
index 2b8b934..fcde08e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
@@ -52,7 +52,7 @@
                 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
                 TYPE_BASE_APPLICATION, mDisplayContent, "splitScreenSecondaryWindow");
 
-        mWm.mInputMethodTarget = splitScreenWindow;
+        mDisplayContent.mInputMethodTarget = splitScreenWindow;
 
         Consumer<WindowState> c = mock(Consumer.class);
         mDisplayContent.forAllWindows(c, false);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
index 4e75ec9..9a13efb 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
@@ -124,9 +124,10 @@
                     doReturn(input[1]).when(ims).monitorInput(anyString(), anyInt());
                 }
 
-                mService = WindowManagerService.main(context, ims, false,
-                        false, mPolicy = new TestWindowManagerPolicy(
-                                WindowManagerServiceRule.this::getWindowManagerService));
+                mService = WindowManagerService.main(context, ims, false, false,
+                        mPolicy = new TestWindowManagerPolicy(
+                                WindowManagerServiceRule.this::getWindowManagerService),
+                        new WindowManagerGlobalLock());
                 mService.mTransactionFactory = () -> {
                     final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
                     mSurfaceTransactions.add(new WeakReference<>(transaction));
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index 9e12f02..80bb936 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -32,6 +32,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Rect;
@@ -53,14 +54,6 @@
 public class WindowTestUtils {
     private static int sNextTaskId = 0;
 
-    /** Retrieves an instance of a mock {@link WindowManagerService}. */
-    static WindowManagerService getMockWindowManagerService() {
-        final WindowManagerService service = mock(WindowManagerService.class);
-        final WindowManagerGlobalLock lock = new WindowManagerGlobalLock();
-        doReturn(lock).when(service).getWindowManagerLock();
-        return service;
-    }
-
     /** An extension of {@link DisplayContent} to gain package scoped access. */
     public static class TestDisplayContent extends DisplayContent {
 
@@ -152,17 +145,19 @@
         private TestAppWindowToken(DisplayContent dc) {
             super(dc.mService, new IApplicationToken.Stub() {
                 public String getName() {return null;}
-                }, false, dc, true /* fillsParent */);
+                }, new ComponentName("", ""), false, dc, true /* fillsParent */);
         }
 
         TestAppWindowToken(WindowManagerService service, IApplicationToken token,
-                boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
-                boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
-                int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
-                boolean alwaysFocusable, AppWindowContainerController controller) {
-            super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
-                    showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
-                    launchTaskBehind, alwaysFocusable, controller);
+                ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
+                long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
+                int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
+                boolean launchTaskBehind, boolean alwaysFocusable,
+                AppWindowContainerController controller) {
+            super(service, token, activityComponent, voiceInteraction, dc,
+                    inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
+                    orientation, rotationAnimationHint, configChanges, launchTaskBehind,
+                    alwaysFocusable, controller);
         }
 
         int getWindowsCount() {
@@ -326,22 +321,24 @@
 
         TestAppWindowContainerController(TestTaskWindowContainerController taskController,
                 IApplicationToken token) {
-            super(taskController, token, null /* listener */, 0 /* index */,
-                    SCREEN_ORIENTATION_UNSPECIFIED, true /* fullscreen */,
-                    true /* showForAllUsers */, 0 /* configChanges */, false /* voiceInteraction */,
-                    false /* launchTaskBehind */, false /* alwaysFocusable */,
-                    0 /* targetSdkVersion */, 0 /* rotationAnimationHint */,
-                    0 /* inputDispatchingTimeoutNanos */, taskController.mService);
+            super(taskController, token, new ComponentName("", "") /* activityComponent */,
+                    null /* listener */, 0 /* index */, SCREEN_ORIENTATION_UNSPECIFIED,
+                    true /* fullscreen */, true /* showForAllUsers */, 0 /* configChanges */,
+                    false /* voiceInteraction */, false /* launchTaskBehind */,
+                    false /* alwaysFocusable */, 0 /* targetSdkVersion */,
+                    0 /* rotationAnimationHint */, 0 /* inputDispatchingTimeoutNanos */,
+                    taskController.mService);
             mToken = token;
         }
 
         @Override
         AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
-                boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
+                ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
+                long inputDispatchingTimeoutNanos,
                 boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
                 int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
                 boolean alwaysFocusable, AppWindowContainerController controller) {
-            return new TestAppWindowToken(service, token, voiceInteraction, dc,
+            return new TestAppWindowToken(service, token, activityComponent, voiceInteraction, dc,
                     inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
                     orientation,
                     rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 945cbb9..53858c7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -192,7 +192,7 @@
                 mWm.getDefaultDisplayContentLocked().mAppTransition
                         .removeAppTransitionTimeoutCallbacks();
                 mWm.mH.removeMessages(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT);
-                mWm.mInputMethodTarget = null;
+                mDisplayContent.mInputMethodTarget = null;
             }
 
             // Wait until everything is really cleaned up.
@@ -354,9 +354,14 @@
 
     /** Creates a {@link DisplayContent} and adds it to the system. */
     DisplayContent createNewDisplay() {
+        return createNewDisplay(mDisplayInfo);
+    }
+
+    /** Creates a {@link DisplayContent} and adds it to the system. */
+    DisplayContent createNewDisplay(DisplayInfo displayInfo) {
         final int displayId = sNextDisplayId++;
         final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
-                mDisplayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
+                displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
         synchronized (mWm.mGlobalLock) {
             return new DisplayContent(display, mWm, mWallpaperController,
                     mock(DisplayWindowController.class));
diff --git a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
index 32e4e02..3dcea75 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
@@ -122,7 +122,6 @@
         public SurfaceControl build() {
             final SurfaceControl sc = super.build();
             mTransaction.addParentFor(sc, mPendingParent);
-            mTransaction = null;
             mPendingParent = null;
             return sc;
         }
@@ -138,7 +137,6 @@
         @Override
         public SurfaceControl.Builder make(SurfaceSession s) {
             final LayerRecordingTransaction transaction = mTransaction;
-            mTransaction = null;
             return new HierarchyRecorder(s, transaction);
         }
     }
@@ -211,7 +209,7 @@
 
     @Test
     public void testAssignWindowLayers_ForImeWithNoTarget() {
-        mWm.mInputMethodTarget = null;
+        mDisplayContent.mInputMethodTarget = null;
         mDisplayContent.assignChildLayers(mTransaction);
 
         // The Ime has an higher base layer than app windows and lower base layer than system
@@ -229,7 +227,7 @@
     @Test
     public void testAssignWindowLayers_ForImeWithAppTarget() {
         final WindowState imeAppTarget = createWindow("imeAppTarget");
-        mWm.mInputMethodTarget = imeAppTarget;
+        mDisplayContent.mInputMethodTarget = imeAppTarget;
 
         mDisplayContent.assignChildLayers(mTransaction);
 
@@ -255,7 +253,7 @@
                 TYPE_APPLICATION_MEDIA_OVERLAY, imeAppTarget.mToken,
                 "imeAppTargetChildBelowWindow");
 
-        mWm.mInputMethodTarget = imeAppTarget;
+        mDisplayContent.mInputMethodTarget = imeAppTarget;
         mDisplayContent.assignChildLayers(mTransaction);
 
         // Ime should be above all app windows except for child windows that are z-ordered above it
@@ -277,7 +275,7 @@
         final WindowState imeAppTarget = createWindow("imeAppTarget");
         final WindowState appAboveImeTarget = createWindow("appAboveImeTarget");
 
-        mWm.mInputMethodTarget = imeAppTarget;
+        mDisplayContent.mInputMethodTarget = imeAppTarget;
         mDisplayContent.assignChildLayers(mTransaction);
 
         // Ime should be above all app windows except for non-fullscreen app window above it and
@@ -300,7 +298,7 @@
                 mDisplayContent, "imeSystemOverlayTarget",
                 true /* ownerCanAddInternalSystemWindow */);
 
-        mWm.mInputMethodTarget = imeSystemOverlayTarget;
+        mDisplayContent.mInputMethodTarget = imeSystemOverlayTarget;
         mDisplayContent.assignChildLayers(mTransaction);
 
         // The IME target base layer is higher than all window except for the nav bar window, so the
@@ -323,7 +321,7 @@
 
     @Test
     public void testAssignWindowLayers_ForStatusBarImeTarget() {
-        mWm.mInputMethodTarget = mStatusBarWindow;
+        mDisplayContent.mInputMethodTarget = mStatusBarWindow;
         mDisplayContent.assignChildLayers(mTransaction);
 
         assertWindowHigher(mImeWindow, mChildAppWindowAbove);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 59eab3f..9da204f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -417,6 +417,7 @@
 
         verifyLights();
         assertTrue(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -429,6 +430,7 @@
         verifyNeverVibrate();
         verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -439,6 +441,7 @@
 
         verifyBeep();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -449,6 +452,7 @@
 
         verifyNeverBeep();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -461,6 +465,7 @@
         verifyNeverBeep();
         verifyNeverVibrate();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -473,6 +478,7 @@
         verifyNeverBeep();
         verifyNeverVibrate();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -489,6 +495,7 @@
         verifyBeepLooped();
         verify(mAccessibilityService, times(2)).sendAccessibilityEvent(any(), anyInt());
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -517,6 +524,7 @@
 
         verifyNeverStopAudio();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -530,7 +538,9 @@
 
         verifyNeverStopAudio();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
         assertFalse(s.isInterruptive());
+        assertFalse(s.getAudiblyAlerted());
     }
 
     /**
@@ -567,6 +577,7 @@
         mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
         verifyNeverStopAudio();
         assertTrue(other.isInterruptive());
+        assertTrue(other.getAudiblyAlerted());
     }
 
     @Test
@@ -592,12 +603,14 @@
         // set up internal state
         mService.buzzBeepBlinkLocked(r);
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
         Mockito.reset(mRingtonePlayer);
 
         // quiet update should stop making noise
         mService.buzzBeepBlinkLocked(s);
         verifyStopAudio();
         assertFalse(s.isInterruptive());
+        assertFalse(s.getAudiblyAlerted());
     }
 
     @Test
@@ -609,12 +622,14 @@
         // set up internal state
         mService.buzzBeepBlinkLocked(r);
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
         Mockito.reset(mRingtonePlayer);
 
         // stop making noise - this is a weird corner case, but quiet should override once
         mService.buzzBeepBlinkLocked(s);
         verifyStopAudio();
         assertFalse(s.isInterruptive());
+        assertFalse(s.getAudiblyAlerted());
     }
 
     @Test
@@ -631,6 +646,7 @@
         verify(mService, times(1)).playInCallNotification();
         verifyNeverBeep(); // doesn't play normal beep
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -650,6 +666,7 @@
                 eq(effect), anyString(),
                 (AudioAttributes) anyObject());
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -667,6 +684,7 @@
         verifyNeverVibrate();
         verifyBeepLooped();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -686,6 +704,7 @@
         verify(mRingtonePlayer, never()).playAsync
                 (anyObject(), anyObject(), anyBoolean(), anyObject());
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -702,6 +721,7 @@
 
         verifyDelayedVibrateLooped();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -713,6 +733,7 @@
         verifyNeverBeep();
         verifyVibrate();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -722,6 +743,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyVibrateLooped();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -737,6 +759,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyVibrate();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -747,6 +770,7 @@
 
         verifyNeverBeep();
         assertFalse(child.isInterruptive());
+        assertFalse(child.getAudiblyAlerted());
     }
 
     @Test
@@ -759,6 +783,7 @@
         verifyBeepLooped();
         // summaries are never interruptive for notification counts
         assertFalse(summary.isInterruptive());
+        assertTrue(summary.getAudiblyAlerted());
     }
 
     @Test
@@ -769,6 +794,7 @@
 
         verifyBeepLooped();
         assertTrue(nonGroup.isInterruptive());
+        assertTrue(nonGroup.getAudiblyAlerted());
     }
 
     @Test
@@ -780,6 +806,7 @@
 
         verifyNeverBeep();
         assertFalse(summary.isInterruptive());
+        assertFalse(summary.getAudiblyAlerted());
     }
 
     @Test
@@ -790,6 +817,7 @@
 
         verifyBeepLooped();
         assertTrue(child.isInterruptive());
+        assertTrue(child.getAudiblyAlerted());
     }
 
     @Test
@@ -800,6 +828,7 @@
 
         verifyBeepLooped();
         assertTrue(nonGroup.isInterruptive());
+        assertTrue(nonGroup.getAudiblyAlerted());
     }
 
     @Test
@@ -810,6 +839,7 @@
 
         verifyBeepLooped();
         assertTrue(group.isInterruptive());
+        assertTrue(group.getAudiblyAlerted());
     }
 
     @Test
@@ -822,11 +852,13 @@
         mService.buzzBeepBlinkLocked(r);
         Mockito.reset(mVibrator);
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
 
         // update should not beep
         mService.buzzBeepBlinkLocked(s);
         verifyNeverVibrate();
         assertFalse(s.isInterruptive());
+        assertFalse(s.getAudiblyAlerted());
     }
 
     @Test
@@ -839,6 +871,7 @@
 
         verifyNeverStopVibrate();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
     }
 
     @Test
@@ -852,7 +885,9 @@
 
         verifyNeverStopVibrate();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
         assertFalse(s.isInterruptive());
+        assertFalse(s.getAudiblyAlerted());
     }
 
     @Test
@@ -871,8 +906,11 @@
         mService.buzzBeepBlinkLocked(s); // this no longer owns the stream
         verifyNeverStopVibrate();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
         assertTrue(other.isInterruptive());
+        assertTrue(other.getAudiblyAlerted());
         assertFalse(s.isInterruptive());
+        assertFalse(s.getAudiblyAlerted());
     }
 
     @Test
@@ -888,6 +926,7 @@
         mService.buzzBeepBlinkLocked(other);
         verifyNeverStopVibrate();
         assertFalse(other.isInterruptive());
+        assertFalse(other.getAudiblyAlerted());
     }
 
     @Test
@@ -904,7 +943,9 @@
         mService.buzzBeepBlinkLocked(s);
         verifyStopVibrate();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
         assertFalse(s.isInterruptive());
+        assertFalse(s.getAudiblyAlerted());
     }
 
     @Test
@@ -921,7 +962,9 @@
         mService.buzzBeepBlinkLocked(s);
         verifyStopVibrate();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
         assertFalse(s.isInterruptive());
+        assertFalse(s.getAudiblyAlerted());
     }
 
     @Test
@@ -939,7 +982,9 @@
         mService.buzzBeepBlinkLocked(s);
         verifyStopVibrate();
         assertTrue(r.isInterruptive());
+        assertTrue(r.getAudiblyAlerted());
         assertFalse(s.isInterruptive());
+        assertFalse(s.getAudiblyAlerted());
     }
 
     @Test
@@ -957,6 +1002,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyNeverBeep();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -968,6 +1014,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyNeverBeep();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -1010,6 +1057,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyNeverBeep();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -1043,6 +1091,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyNeverLights();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -1052,6 +1101,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyNeverLights();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -1060,6 +1110,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyLights();
         assertTrue(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
 
         r = getLightsOnceNotification();
         r.isUpdate = true;
@@ -1067,6 +1118,7 @@
         // checks that lights happened once, i.e. this new call didn't trigger them again
         verifyLights();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -1076,6 +1128,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyNeverLights();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -1084,6 +1137,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyNeverLights();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -1093,6 +1147,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyNeverLights();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -1102,6 +1157,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyNeverLights();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -1111,6 +1167,7 @@
         mService.buzzBeepBlinkLocked(r);
         verifyNeverLights();
         assertFalse(r.isInterruptive());
+        assertFalse(r.getAudiblyAlerted());
     }
 
     @Test
@@ -1121,6 +1178,7 @@
 
         verifyNeverLights();
         assertFalse(child.isInterruptive());
+        assertFalse(child.getAudiblyAlerted());
     }
 
     @Test
@@ -1133,6 +1191,7 @@
         verifyLights();
         // summaries should never count for interruptiveness counts
         assertFalse(summary.isInterruptive());
+        assertFalse(summary.getAudiblyAlerted());
     }
 
     @Test
@@ -1143,6 +1202,7 @@
 
         verifyLights();
         assertTrue(nonGroup.isInterruptive());
+        assertFalse(nonGroup.getAudiblyAlerted());
     }
 
     @Test
@@ -1154,6 +1214,7 @@
 
         verifyNeverLights();
         assertFalse(summary.isInterruptive());
+        assertFalse(summary.getAudiblyAlerted());
     }
 
     @Test
@@ -1164,6 +1225,7 @@
 
         verifyLights();
         assertTrue(child.isInterruptive());
+        assertFalse(child.getAudiblyAlerted());
     }
 
     @Test
@@ -1174,6 +1236,7 @@
 
         verifyLights();
         assertTrue(nonGroup.isInterruptive());
+        assertFalse(nonGroup.getAudiblyAlerted());
     }
 
     @Test
@@ -1184,6 +1247,7 @@
 
         verifyLights();
         assertTrue(group.isInterruptive());
+        assertFalse(group.getAudiblyAlerted());
     }
 
     static class VibrateRepeatMatcher implements ArgumentMatcher<VibrationEffect> {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
index f17a30d..410ab87 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
@@ -72,7 +72,7 @@
         assertTrue(r.getGroupKey().contains(GroupHelper.AUTOGROUP_KEY));
         assertEquals(people, r.getPeopleOverride());
         assertEquals(snoozeCriteria, r.getSnoozeCriteria());
-        assertEquals(smartActions, r.getSmartActions());
+        assertEquals(smartActions, r.getSystemGeneratedSmartActions());
     }
 
     @Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
index f255d49..bcba15d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -38,12 +38,10 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.Parcel;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.NotificationRankingUpdate;
 import android.service.notification.SnoozeCriterion;
-import android.service.notification.StatusBarNotification;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -94,6 +92,7 @@
             assertEquals(getShowBadge(i), ranking.canShowBadge());
             assertEquals(getUserSentiment(i), ranking.getUserSentiment());
             assertEquals(getHidden(i), ranking.isSuspended());
+            assertEquals(audiblyAlerted(i), ranking.audiblyAlerted());
             assertActionsEqual(getSmartActions(key, i), ranking.getSmartActions());
             assertEquals(getSmartReplies(key, i), ranking.getSmartReplies());
         }
@@ -114,6 +113,8 @@
         Bundle mHidden = new Bundle();
         Bundle smartActions = new Bundle();
         Bundle smartReplies = new Bundle();
+        Bundle audiblyAlerted = new Bundle();
+        Bundle noisy = new Bundle();
 
         for (int i = 0; i < mKeys.length; i++) {
             String key = mKeys[i];
@@ -133,12 +134,14 @@
             mHidden.putBoolean(key, getHidden(i));
             smartActions.putParcelableArrayList(key, getSmartActions(key, i));
             smartReplies.putCharSequenceArrayList(key, getSmartReplies(key, i));
+            audiblyAlerted.putBoolean(key, audiblyAlerted(i));
+            noisy.putBoolean(key, getNoisy(i));
         }
         NotificationRankingUpdate update = new NotificationRankingUpdate(mKeys,
                 interceptedKeys.toArray(new String[0]), visibilityOverrides,
                 suppressedVisualEffects, importance, explanation, overrideGroupKeys,
                 channels, overridePeople, snoozeCriteria, showBadge, userSentiment, mHidden,
-                smartActions, smartReplies);
+                smartActions, smartReplies, audiblyAlerted, noisy);
         return update;
     }
 
@@ -190,6 +193,14 @@
         return index % 2 == 0;
     }
 
+    private boolean audiblyAlerted(int index) {
+        return index < 2;
+    }
+
+    private boolean getNoisy(int index) {
+        return index < 1;
+    }
+
     private ArrayList<String> getPeople(String key, int index) {
         ArrayList<String> people = new ArrayList<>();
         for (int i = 0; i < index; i++) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
index 1b59e75..8690110 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -708,14 +708,14 @@
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
                 false /* lights */, false /* defaultLights */, groupId /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
-        assertNull(record.getSmartActions());
+        assertNull(record.getSystemGeneratedSmartActions());
 
         ArrayList<Notification.Action> smartActions = new ArrayList<>();
         smartActions.add(new Notification.Action.Builder(
                 Icon.createWithResource(getContext(), R.drawable.btn_default),
                 "text", null).build());
-        record.setSmartActions(smartActions);
-        assertEquals(smartActions, record.getSmartActions());
+        record.setSystemGeneratedSmartActions(smartActions);
+        assertEquals(smartActions, record.getSystemGeneratedSmartActions());
     }
 
     @Test
@@ -801,4 +801,16 @@
         assertEquals(1.0f, record.getContactAffinity());
         assertEquals(IMPORTANCE_LOW, record.getImportance());
     }
+
+    @Test
+    public void testSetAudiblyAlerted() {
+        StatusBarNotification sbn = getNotification(PKG_O, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+        record.setAudiblyAlerted(true);
+
+        assertTrue(record.getAudiblyAlerted());
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 3fe381b..1a218b2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -27,7 +27,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -98,7 +97,7 @@
     private static final UserHandle USER = UserHandle.of(0);
     private static final int UID_O = 1111;
     private static final String SYSTEM_PKG = "android";
-    private static final int SYSTEM_UID= 1000;
+    private static final int SYSTEM_UID = 1000;
     private static final UserHandle USER2 = UserHandle.of(10);
     private static final String TEST_CHANNEL_ID = "test_channel_id";
     private static final String TEST_AUTHORITY = "test";
@@ -1091,6 +1090,158 @@
     }
 
     @Test
+    public void testGetChannelsBypassingDndCount_noChannelsBypassing() throws Exception {
+        assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+                USER.getIdentifier()).getList().size());
+    }
+
+    @Test
+    public void testGetChannelsBypassingDnd_noChannelsForUserIdBypassing()
+            throws Exception {
+        int user = 9;
+        NotificationChannel channel = new NotificationChannel("id", "name",
+                NotificationManager.IMPORTANCE_MAX);
+        channel.setBypassDnd(true);
+        mHelper.createNotificationChannel(PKG_N_MR1, 111, channel, true, true);
+
+        assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+                user).getList().size());
+    }
+
+    @Test
+    public void testGetChannelsBypassingDndCount_oneChannelBypassing_groupBlocked() {
+        int user = USER.getIdentifier();
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        NotificationChannel channel1 = new NotificationChannel("id1", "name1",
+                NotificationManager.IMPORTANCE_MAX);
+        channel1.setBypassDnd(true);
+        channel1.setGroup(ncg.getId());
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, user, ncg,  /* fromTargetApp */ true);
+        mHelper.createNotificationChannel(PKG_N_MR1, user, channel1, true, /*has DND access*/ true);
+
+        assertEquals(1, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+                user).getList().size());
+
+        // disable group
+        ncg.setBlocked(true);
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, user, ncg,  /* fromTargetApp */ false);
+        assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+                user).getList().size());
+    }
+
+    @Test
+    public void testGetChannelsBypassingDndCount_multipleChannelsBypassing() {
+        int user = USER.getIdentifier();
+        NotificationChannel channel1 = new NotificationChannel("id1", "name1",
+                NotificationManager.IMPORTANCE_MAX);
+        NotificationChannel channel2 = new NotificationChannel("id2", "name2",
+                NotificationManager.IMPORTANCE_MAX);
+        NotificationChannel channel3 = new NotificationChannel("id3", "name3",
+                NotificationManager.IMPORTANCE_MAX);
+        channel1.setBypassDnd(true);
+        channel2.setBypassDnd(true);
+        channel3.setBypassDnd(true);
+        // has DND access, so can set bypassDnd attribute
+        mHelper.createNotificationChannel(PKG_N_MR1, user, channel1, true, /*has DND access*/ true);
+        mHelper.createNotificationChannel(PKG_N_MR1, user, channel2, true, true);
+        mHelper.createNotificationChannel(PKG_N_MR1, user, channel3, true, true);
+        assertEquals(3, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+                user).getList().size());
+
+        // block notifications from this app
+        mHelper.setEnabled(PKG_N_MR1, user, false);
+        assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+                user).getList().size());
+
+        // re-enable notifications from this app
+        mHelper.setEnabled(PKG_N_MR1, user, true);
+        assertEquals(3, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+                user).getList().size());
+
+        // setBypassDnd false for some channels
+        channel1.setBypassDnd(false);
+        channel2.setBypassDnd(false);
+        assertEquals(1, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+                user).getList().size());
+
+        // setBypassDnd false for rest of the channels
+        channel3.setBypassDnd(false);
+        assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+                user).getList().size());
+    }
+
+    @Test
+    public void testGetAppsBypassingDndCount_noAppsBypassing() throws Exception {
+        assertEquals(0, mHelper.getAppsBypassingDndCount(USER.getIdentifier()));
+    }
+
+    @Test
+    public void testGetAppsBypassingDndCount_noAppsForUserIdBypassing() throws Exception {
+        int user = 9;
+        NotificationChannel channel = new NotificationChannel("id", "name",
+                NotificationManager.IMPORTANCE_MAX);
+        channel.setBypassDnd(true);
+        mHelper.createNotificationChannel(PKG_N_MR1, 111, channel, true, true);
+
+        assertEquals(0, mHelper.getAppsBypassingDndCount(user));
+    }
+
+    @Test
+    public void testGetAppsBypassingDndCount_oneChannelBypassing_groupBlocked() {
+        int user = USER.getIdentifier();
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        NotificationChannel channel1 = new NotificationChannel("id1", "name1",
+                NotificationManager.IMPORTANCE_MAX);
+        channel1.setBypassDnd(true);
+        channel1.setGroup(ncg.getId());
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, user, ncg,  /* fromTargetApp */ true);
+        mHelper.createNotificationChannel(PKG_N_MR1, user, channel1, true, /*has DND access*/ true);
+
+        assertEquals(1, mHelper.getAppsBypassingDndCount(user));
+
+        // disable group
+        ncg.setBlocked(true);
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, user, ncg,  /* fromTargetApp */ false);
+        assertEquals(0, mHelper.getAppsBypassingDndCount(user));
+    }
+
+    @Test
+    public void testGetAppsBypassingDndCount_oneAppBypassing() {
+        int user = USER.getIdentifier();
+        NotificationChannel channel1 = new NotificationChannel("id1", "name1",
+                NotificationManager.IMPORTANCE_MAX);
+        NotificationChannel channel2 = new NotificationChannel("id2", "name2",
+                NotificationManager.IMPORTANCE_MAX);
+        NotificationChannel channel3 = new NotificationChannel("id3", "name3",
+                NotificationManager.IMPORTANCE_MAX);
+        channel1.setBypassDnd(true);
+        channel2.setBypassDnd(true);
+        channel3.setBypassDnd(true);
+        // has DND access, so can set bypassDnd attribute
+        mHelper.createNotificationChannel(PKG_N_MR1, user, channel1, true, /*has DND access*/ true);
+        mHelper.createNotificationChannel(PKG_N_MR1, user, channel2, true, true);
+        mHelper.createNotificationChannel(PKG_N_MR1, user, channel3, true, true);
+        assertEquals(1, mHelper.getAppsBypassingDndCount(user));
+
+        // block notifications from this app
+        mHelper.setEnabled(PKG_N_MR1, user, false);
+        assertEquals(0, mHelper.getAppsBypassingDndCount(user)); // no apps can bypass dnd
+
+        // re-enable notifications from this app
+        mHelper.setEnabled(PKG_N_MR1, user, true);
+        assertEquals(1, mHelper.getAppsBypassingDndCount(user));
+
+        // setBypassDnd false for some channels
+        channel1.setBypassDnd(false);
+        channel2.setBypassDnd(false);
+        assertEquals(1, mHelper.getAppsBypassingDndCount(user));
+
+        // setBypassDnd false for rest of the channels
+        channel3.setBypassDnd(false);
+        assertEquals(0, mHelper.getAppsBypassingDndCount(user));
+    }
+
+    @Test
     public void testCreateAndDeleteCanChannelsBypassDnd() throws Exception {
         // create notification channel that can't bypass dnd
         // expected result: areChannelsBypassingDnd = false
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
index 6c125d1..32f389a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
@@ -71,7 +71,8 @@
 
     private NotificationRecord getNotificationRecord(NotificationChannel c) {
         StatusBarNotification sbn = mock(StatusBarNotification.class);
-        when(sbn.getNotification()).thenReturn(mock(Notification.class));
+        Notification notification = mock(Notification.class);
+        when(sbn.getNotification()).thenReturn(notification);
         return new NotificationRecord(mContext, sbn, c);
     }
 
diff --git a/services/tests/wmtests/Android.mk b/services/tests/wmtests/Android.mk
index dd656c3..9655b3d 100644
--- a/services/tests/wmtests/Android.mk
+++ b/services/tests/wmtests/Android.mk
@@ -23,6 +23,7 @@
     truth-prebuilt \
     testables \
     ub-uiautomator \
+    hamcrest-library
 
 LOCAL_JAVA_LIBRARIES := \
     android.test.mock \
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index 73a34b6..ff84803 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -41,7 +41,8 @@
         <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityRequestedOrientationChange" />
         <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityTaskChangeCallbacks" />
         <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityTaskDescriptionChange" />
-        <activity android:name="com.android.server.wm.ScreenDecorWindowTests$TestActivity" />
+        <activity android:name="com.android.server.wm.ScreenDecorWindowTests$TestActivity"
+                  android:showWhenLocked="true" />
     </application>
 
     <instrumentation
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index d3f1a0a..7a9c8dc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
@@ -27,7 +28,12 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 import android.platform.test.annotations.Presubmit;
 
@@ -120,6 +126,39 @@
         assertTrue(stack2.isFocusedStackOnDisplay());
     }
 
+    /**
+     * Verifies {@link ActivityDisplay#remove} should not resume home stack on the removing display.
+     */
+    @Test
+    public void testNotResumeHomeStackOnRemovingDisplay() {
+        // Create a display which supports system decoration and allows reparenting stacks to
+        // another display when the display is removed.
+        final ActivityDisplay display = spy(createNewActivityDisplay());
+        doReturn(false).when(display).shouldDestroyContentOnRemove();
+        doReturn(true).when(display).supportsSystemDecorations();
+        mSupervisor.addChild(display, ActivityDisplay.POSITION_TOP);
+
+        // Put home stack on the display.
+        final ActivityStack homeStack = display.createStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+        final TaskRecord task = new TaskBuilder(mSupervisor).setStack(homeStack).build();
+        new ActivityBuilder(mService).setTask(task).build();
+        display.removeChild(homeStack);
+        final ActivityStack spiedHomeStack = spy(homeStack);
+        display.addChild(spiedHomeStack, ActivityDisplay.POSITION_TOP);
+        reset(spiedHomeStack);
+
+        // Put a finishing standard activity which will be reparented.
+        final ActivityStack stack = createFullscreenStackWithSimpleActivityAt(display);
+        stack.topRunningActivityLocked().makeFinishingLocked();
+
+        display.remove();
+
+        // The removed display should have no focused stack and its home stack should never resume.
+        assertNull(display.getFocusedStack());
+        verify(spiedHomeStack, never()).resumeTopActivityUncheckedLocked(any(), any());
+    }
+
     private ActivityStack createFullscreenStackWithSimpleActivityAt(ActivityDisplay display) {
         final ActivityStack fullscreenStack = display.createStack(
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, ON_TOP);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
new file mode 100644
index 0000000..215c51d
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2018 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.wm;
+
+import static android.app.ActivityManager.START_SUCCESS;
+import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.content.Intent;
+import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
+import android.util.SparseIntArray;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link ActivityMetricsLaunchObserver} class.
+ *
+ * Build/Install/Run:
+ *  atest WmTests:ActivityMetricsLaunchObserverTests
+ */
+@SmallTest
+@Presubmit
+@FlakyTest(detail="promote once confirmed non-flaky")
+public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
+    private ActivityMetricsLogger mActivityMetricsLogger;
+    private ActivityMetricsLaunchObserver mLaunchObserver;
+
+    private TestActivityStack mStack;
+    private TaskRecord mTask;
+    private ActivityRecord mActivityRecord;
+    private ActivityRecord mActivityRecordTrampoline;
+
+    @Before
+    public void setUpAMLO() throws Exception {
+        setupActivityTaskManagerService();
+
+        mActivityMetricsLogger =
+                new ActivityMetricsLogger(mSupervisor, mService.mContext, mService.mH.getLooper());
+
+        mLaunchObserver = mock(ActivityMetricsLaunchObserver.class);
+
+        // TODO: Use ActivityMetricsLaunchObserverRegistry .
+        java.lang.reflect.Field f =
+                mActivityMetricsLogger.getClass().getDeclaredField("mLaunchObserver");
+        f.setAccessible(true);
+        f.set(mActivityMetricsLogger, mLaunchObserver);
+
+        // Sometimes we need an ActivityRecord for ActivityMetricsLogger to do anything useful.
+        // This seems to be the easiest way to create an ActivityRecord.
+        mStack = mSupervisor.getDefaultDisplay().createStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+        mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
+        mActivityRecord = new ActivityBuilder(mService).setTask(mTask).build();
+        mActivityRecordTrampoline = new ActivityBuilder(mService).setTask(mTask).build();
+    }
+
+    @Test
+    public void testOnIntentStarted() throws Exception {
+        Intent intent = new Intent("action 1");
+
+        mActivityMetricsLogger.notifyActivityLaunching(intent);
+
+        verify(mLaunchObserver).onIntentStarted(eq(intent));
+        verifyNoMoreInteractions(mLaunchObserver);
+    }
+
+    @Test
+    public void testOnIntentFailed() throws Exception {
+        testOnIntentStarted();
+
+        ActivityRecord activityRecord = null;
+
+        // Bringing an intent that's already running 'to front' is not considered
+        // as an ACTIVITY_LAUNCHED state transition.
+        mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
+                activityRecord);
+
+        verify(mLaunchObserver).onIntentFailed();
+        verifyNoMoreInteractions(mLaunchObserver);
+    }
+
+    @Test
+    public void testOnActivityLaunched() throws Exception {
+        testOnIntentStarted();
+
+        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
+                mActivityRecord);
+
+        verify(mLaunchObserver).onActivityLaunched(eq(mActivityRecord), anyInt());
+        verifyNoMoreInteractions(mLaunchObserver);
+    }
+
+    @Test
+    public void testOnActivityLaunchFinished() throws Exception {
+       testOnActivityLaunched();
+
+       mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
+               SystemClock.uptimeMillis());
+
+       mActivityMetricsLogger.notifyWindowsDrawn(mActivityRecord.getWindowingMode(),
+               SystemClock.uptimeMillis());
+
+       verify(mLaunchObserver).onActivityLaunchFinished(eq(mActivityRecord));
+       verifyNoMoreInteractions(mLaunchObserver);
+    }
+
+    @Test
+    public void testOnActivityLaunchCancelled() throws Exception {
+       testOnActivityLaunched();
+
+       mActivityRecord.nowVisible = true;
+
+       // Cannot time already-visible activities.
+       mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mActivityRecord);
+
+       verify(mLaunchObserver).onActivityLaunchCancelled(eq(mActivityRecord));
+       verifyNoMoreInteractions(mLaunchObserver);
+    }
+
+    @Test
+    public void testOnActivityLaunchedTrampoline() throws Exception {
+        testOnIntentStarted();
+
+        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
+                mActivityRecord);
+
+        verify(mLaunchObserver).onActivityLaunched(eq(mActivityRecord), anyInt());
+
+        // A second, distinct, activity launch is coalesced into the the current app launch sequence
+        mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
+                mActivityRecordTrampoline);
+
+        verifyNoMoreInteractions(mLaunchObserver);
+    }
+
+    @Test
+    public void testOnActivityLaunchFinishedTrampoline() throws Exception {
+       testOnActivityLaunchedTrampoline();
+
+       mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
+               SystemClock.uptimeMillis());
+
+       mActivityMetricsLogger.notifyWindowsDrawn(mActivityRecordTrampoline.getWindowingMode(),
+               SystemClock.uptimeMillis());
+
+       verify(mLaunchObserver).onActivityLaunchFinished(eq(mActivityRecordTrampoline));
+       verifyNoMoreInteractions(mLaunchObserver);
+    }
+
+    @Test
+    public void testOnActivityLaunchCancelledTrampoline() throws Exception {
+       testOnActivityLaunchedTrampoline();
+
+       mActivityRecordTrampoline.nowVisible = true;
+
+       // Cannot time already-visible activities.
+       mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
+               mActivityRecordTrampoline);
+
+       verify(mLaunchObserver).onActivityLaunchCancelled(eq(mActivityRecordTrampoline));
+       verifyNoMoreInteractions(mLaunchObserver);
+    }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index a794d6d..16dd92f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -25,12 +25,13 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
+import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
+import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
 import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
 import static com.android.server.wm.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
 
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertEquals;
@@ -54,7 +55,10 @@
 
 import android.app.ActivityOptions;
 import android.app.WaitResult;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.graphics.Rect;
+import android.os.Build;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.MediumTest;
@@ -431,12 +435,32 @@
                 eq(activity), eq(null /* targetOptions */));
     }
 
+    /**
+     * Tests home activities that targeted sdk before Q cannot start on secondary display.
+     */
+    @Test
+    public void testStartHomeTargetSdkBeforeQ() throws Exception {
+        final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
+        mSupervisor.addChild(secondDisplay, POSITION_TOP);
+        doReturn(true).when(secondDisplay).supportsSystemDecorations();
+
+        final ActivityInfo info = new ActivityInfo();
+        info.launchMode = LAUNCH_MULTIPLE;
+        info.applicationInfo = new ApplicationInfo();
+        info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
+        assertTrue(mSupervisor.canStartHomeOnDisplay(info, secondDisplay.mDisplayId,
+                false /* allowInstrumenting */));
+
+        info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
+        assertFalse(mSupervisor.canStartHomeOnDisplay(info, secondDisplay.mDisplayId,
+                false /* allowInstrumenting */));
+    }
 
     /**
      * Tests that home activities can be started on the displays that supports system decorations.
      */
     @Test
-    public void testStartHomeOnAllDisplays() throws Exception {
+    public void testStartHomeOnAllDisplays() {
         // Create secondary displays.
         final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
         mSupervisor.addChild(secondDisplay, POSITION_TOP);
@@ -450,7 +474,7 @@
                 .create(any(), anyInt(), any(), any(), any(), any());
         doReturn(true).when(mService.mStackSupervisor)
                 .ensureVisibilityAndConfig(any(), anyInt(), anyBoolean(), anyBoolean());
-        doReturn(true).when(mSupervisor).canStartHomeOnDisplay(any(), anyInt());
+        doReturn(true).when(mSupervisor).canStartHomeOnDisplay(any(), anyInt(), anyBoolean());
 
         mSupervisor.startHomeOnAllDisplays(0, "testStartHome");
 
@@ -458,4 +482,49 @@
         assertNotNull(secondDisplay.getTopStack());
         assertTrue(secondDisplay.getTopStack().isActivityTypeHome());
     }
+
+    /**
+     * Tests that home activities won't be started before booting when display added.
+     */
+    @Test
+    public void testNotStartHomeBeforeBoot() {
+        final int displayId = 1;
+        final boolean isBooting = mService.mAmInternal.isBooting();
+        final boolean isBooted = mService.mAmInternal.isBooted();
+        try {
+            mService.mAmInternal.setBooting(false);
+            mService.mAmInternal.setBooted(false);
+            mSupervisor.onDisplayAdded(displayId);
+            verify(mSupervisor, never()).startHomeOnDisplay(anyInt(), any(), anyInt());
+        } finally {
+            mService.mAmInternal.setBooting(isBooting);
+            mService.mAmInternal.setBooted(isBooted);
+        }
+    }
+
+    /**
+     * Tests whether home can be started if being instrumented.
+     */
+    @Test
+    public void testCanStartHomeWhenInstrumented() {
+        final ActivityInfo info = new ActivityInfo();
+        info.applicationInfo = new ApplicationInfo();
+        final WindowProcessController app = mock(WindowProcessController.class);
+        doReturn(app).when(mService).getProcessController(any(), anyInt());
+
+        // Can not start home if we don't want to start home while home is being instrumented.
+        doReturn(true).when(app).isInstrumenting();
+        assertFalse(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+                false /* allowInstrumenting*/));
+
+        // Can start home for other cases.
+        assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+                true /* allowInstrumenting*/));
+
+        doReturn(false).when(app).isInstrumenting();
+        assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+                false /* allowInstrumenting*/));
+        assertTrue(mSupervisor.canStartHomeOnDisplay(info, DEFAULT_DISPLAY,
+                true /* allowInstrumenting*/));
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 974e285..62767e3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -457,7 +457,7 @@
         final TestActivityStack fullscreenStack2 = createStackForShouldBeVisibleTest(
                 mDefaultDisplay, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
                 true /* onTop */);
-        final TestActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
+        final ActivityStack pinnedStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
                 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
 
         homeStack.setIsTranslucent(false);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index f7d7ad6..88479ec 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -346,7 +346,7 @@
             doReturn(stack).when(mService.mStackSupervisor)
                     .getLaunchStack(any(), any(), any(), anyBoolean());
             doReturn(stack).when(mService.mStackSupervisor)
-                    .getLaunchStack(any(), any(), any(), anyBoolean(), anyInt());
+                    .getLaunchStack(any(), any(), any(), anyBoolean(), any());
         }
 
         // Set up mock package manager internal and make sure no unmocked methods are called
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 9d28c57..26286e2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -144,6 +144,10 @@
         return TestActivityDisplay.create(mSupervisor, sNextDisplayId++);
     }
 
+    TestActivityDisplay createNewActivityDisplay(DisplayInfo info) {
+        return TestActivityDisplay.create(mSupervisor, sNextDisplayId++, info);
+    }
+
     /** Creates and adds a {@link TestActivityDisplay} to supervisor at the given position. */
     TestActivityDisplay addNewActivityDisplayAt(int position) {
         final TestActivityDisplay display = createNewActivityDisplay();
@@ -153,8 +157,7 @@
 
     void setupActivityManagerService(
             TestActivityManagerService am, TestActivityTaskManagerService atm) {
-        atm.setActivityManagerService(am, am.mHandlerThread.getLooper(), am.mIntentFirewall,
-                am.mPendingIntentController);
+        atm.setActivityManagerService(am.mIntentFirewall, am.mPendingIntentController);
         atm.mAmInternal = am.getLocalService();
         am.mAtmInternal = atm.getLocalService();
         // Makes sure the supervisor is using with the spy object.
@@ -587,12 +590,17 @@
         private final ActivityStackSupervisor mSupervisor;
 
         static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId) {
+            return create(supervisor, displayId, new DisplayInfo());
+        }
+
+        static TestActivityDisplay create(ActivityStackSupervisor supervisor, int displayId,
+                DisplayInfo info) {
             if (displayId == DEFAULT_DISPLAY) {
                 return new TestActivityDisplay(supervisor,
                         supervisor.mDisplayManager.getDisplay(displayId));
             }
             final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
-                    new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
+                    info, DEFAULT_DISPLAY_ADJUSTMENTS);
             return new TestActivityDisplay(supervisor, display);
         }
 
@@ -629,7 +637,7 @@
     }
 
     private static WindowManagerService prepareMockWindowManager() {
-        final WindowManagerService service = WindowTestUtils.getMockWindowManagerService();
+        final WindowManagerService service = mock(WindowManagerService.class);
 
         doAnswer((InvocationOnMock invocationOnMock) -> {
             final Runnable runnable = invocationOnMock.<Runnable>getArgument(0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
index 40c20a4..f8d64e9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
@@ -17,6 +17,8 @@
 package com.android.server.wm;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 
@@ -37,8 +39,12 @@
 import static org.mockito.Mockito.verify;
 
 import android.app.ActivityOptions;
+import android.content.ComponentName;
 import android.content.pm.ActivityInfo.WindowLayout;
+import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
+import android.util.ArrayMap;
+import android.util.SparseArray;
 
 import androidx.test.filters.MediumTest;
 
@@ -48,6 +54,8 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import java.util.Map;
+
 /**
  * Tests for exercising {@link LaunchParamsController}.
  *
@@ -58,11 +66,13 @@
 @Presubmit
 public class LaunchParamsControllerTests extends ActivityTestsBase {
     private LaunchParamsController mController;
+    private TestLaunchParamsPersister mPersister;
 
     @Before
     public void setUp() throws Exception {
         mService = createActivityTaskManagerService();
-        mController = new LaunchParamsController(mService);
+        mPersister = new TestLaunchParamsPersister();
+        mController = new LaunchParamsController(mService, mPersister);
     }
 
     /**
@@ -86,6 +96,31 @@
     }
 
     /**
+     * Makes sure controller passes stored params to modifiers.
+     */
+    @Test
+    public void testStoredParamsRecovery() {
+        final LaunchParamsModifier positioner = mock(LaunchParamsModifier.class);
+        mController.registerModifier(positioner);
+
+        final ComponentName name = new ComponentName("com.android.foo", ".BarActivity");
+        final int userId = 0;
+        final ActivityRecord activity = new ActivityBuilder(mService).setComponent(name)
+                .setUid(userId).build();
+        final LaunchParams expected = new LaunchParams();
+        expected.mPreferredDisplayId = 3;
+        expected.mWindowingMode = WINDOWING_MODE_PINNED;
+        expected.mBounds.set(200, 300, 400, 500);
+
+        mPersister.putLaunchParams(userId, name, expected);
+
+        mController.calculate(activity.getTask(), null /*layout*/, activity, null /*source*/,
+                null /*options*/, new LaunchParams());
+        verify(positioner, times(1)).onCalculate(any(), any(), any(), any(), any(), eq(expected),
+                any());
+    }
+
+    /**
      * Ensures positioners further down the chain are not called when RESULT_DONE is returned.
      */
     @Test
@@ -254,6 +289,53 @@
         assertEquals(windowingMode, afterWindowMode);
     }
 
+    /**
+     * Ensures that {@link LaunchParamsModifier} requests specifying bounds during
+     * layout are honored if window is in freeform.
+     */
+    @Test
+    public void testLayoutTaskBoundsChangeFreeformWindow() {
+        final Rect expected = new Rect(10, 20, 30, 40);
+
+        final LaunchParams params = new LaunchParams();
+        params.mWindowingMode = WINDOWING_MODE_FREEFORM;
+        params.mBounds.set(expected);
+        final InstrumentedPositioner positioner = new InstrumentedPositioner(RESULT_DONE, params);
+        final TaskRecord task = new TaskBuilder(mService.mStackSupervisor).build();
+
+        mController.registerModifier(positioner);
+
+        assertNotEquals(expected, task.getBounds());
+
+        mController.layoutTask(task, null /* windowLayout */);
+
+        assertEquals(expected, task.getBounds());
+    }
+
+    /**
+     * Ensures that {@link LaunchParamsModifier} requests specifying bounds during
+     * layout are set to last non-fullscreen bounds.
+     */
+    @Test
+    public void testLayoutTaskBoundsChangeFixedWindow() {
+        final Rect expected = new Rect(10, 20, 30, 40);
+
+        final LaunchParams params = new LaunchParams();
+        params.mWindowingMode = WINDOWING_MODE_FULLSCREEN;
+        params.mBounds.set(expected);
+        final InstrumentedPositioner positioner = new InstrumentedPositioner(RESULT_DONE, params);
+        final TaskRecord task = new TaskBuilder(mService.mStackSupervisor).build();
+
+        mController.registerModifier(positioner);
+
+        assertNotEquals(expected, task.getBounds());
+
+        mController.layoutTask(task, null /* windowLayout */);
+
+        assertNotEquals(expected, task.getBounds());
+        assertEquals(expected, task.mLastNonFullscreenBounds);
+    }
+
     public static class InstrumentedPositioner implements LaunchParamsModifier {
 
         private final int mReturnVal;
@@ -276,4 +358,73 @@
             return mParams;
         }
     }
+
+    /**
+     * Test double for {@link LaunchParamsPersister}. This class only manages an in-memory storage
+     * of a mapping from user ID and component name to launch params.
+     */
+    static class TestLaunchParamsPersister extends LaunchParamsPersister {
+
+        private final SparseArray<Map<ComponentName, LaunchParams>> mMap =
+                new SparseArray<>();
+        private final LaunchParams mTmpParams = new LaunchParams();
+
+        TestLaunchParamsPersister() {
+            super(null, null, null);
+        }
+
+        void putLaunchParams(int userId, ComponentName name, LaunchParams params) {
+            Map<ComponentName, LaunchParams> map = mMap.get(userId);
+            if (map == null) {
+                map = new ArrayMap<>();
+                mMap.put(userId, map);
+            }
+
+            LaunchParams paramRecord = map.get(name);
+            if (paramRecord == null) {
+                paramRecord = new LaunchParams();
+                map.put(name, params);
+            }
+
+            paramRecord.set(params);
+        }
+
+        @Override
+        void onUnlockUser(int userId) {
+            if (mMap.get(userId) == null) {
+                mMap.put(userId, new ArrayMap<>());
+            }
+        }
+
+        @Override
+        void saveTask(TaskRecord task) {
+            final int userId = task.userId;
+            final ComponentName realActivity = task.realActivity;
+            mTmpParams.mPreferredDisplayId = task.getStack().mDisplayId;
+            mTmpParams.mWindowingMode = task.getWindowingMode();
+            if (task.mLastNonFullscreenBounds != null) {
+                mTmpParams.mBounds.set(task.mLastNonFullscreenBounds);
+            } else {
+                mTmpParams.mBounds.setEmpty();
+            }
+            putLaunchParams(userId, realActivity, mTmpParams);
+        }
+
+        @Override
+        void getLaunchParams(TaskRecord task, ActivityRecord activity, LaunchParams params) {
+            final int userId = task != null ? task.userId : activity.userId;
+            final ComponentName name = task != null ? task.realActivity : activity.realActivity;
+
+            params.reset();
+            final Map<ComponentName, LaunchParams> map = mMap.get(userId);
+            if (map == null) {
+                return;
+            }
+
+            final LaunchParams paramsRecord = map.get(name);
+            if (paramsRecord != null) {
+                params.set(paramsRecord);
+            }
+        }
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
new file mode 100644
index 0000000..59e9ce3
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2018 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.wm;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.Display.INVALID_DISPLAY;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.pm.PackageList;
+import android.content.pm.PackageManagerInternal;
+import android.graphics.Rect;
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+import android.view.DisplayInfo;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.MediumTest;
+
+import com.android.server.LocalServices;
+import com.android.server.wm.LaunchParamsController.LaunchParams;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.IntFunction;
+import java.util.function.Predicate;
+
+/**
+ * Unit tests for {@link LaunchParamsPersister}.
+ *
+ * Build/Install/Run:
+ *   atest WmTests:LaunchParamsPersisterTests
+ */
+@MediumTest
+@Presubmit
+@FlakyTest(detail = "Confirm stable in post-submit before removing")
+public class LaunchParamsPersisterTests extends ActivityTestsBase {
+    private static final int TEST_USER_ID = 3;
+    private static final int ALTERNATIVE_USER_ID = 0;
+    private static final ComponentName TEST_COMPONENT =
+            ComponentName.createRelative("com.android.foo", ".BarActivity");
+    private static final ComponentName ALTERNATIVE_COMPONENT =
+            ComponentName.createRelative("com.android.foo", ".AlternativeBarActivity");
+
+    private static final int TEST_WINDOWING_MODE = WINDOWING_MODE_FREEFORM;
+    private static final Rect TEST_BOUNDS = new Rect(100, 200, 300, 400);
+
+    private static int sNextUniqueId;
+
+    private TestPersisterQueue mPersisterQueue;
+    private File mFolder;
+    private ActivityDisplay mTestDisplay;
+    private String mDisplayUniqueId;
+    private TaskRecord mTestTask;
+    private TaskRecord mTaskWithDifferentUser;
+    private TaskRecord mTaskWithDifferentComponent;
+    private PackageManagerInternal mMockPmi;
+    private PackageManagerInternal.PackageListObserver mObserver;
+
+    private final IntFunction<File> mUserFolderGetter =
+            userId -> new File(mFolder, Integer.toString(userId));
+
+    private LaunchParamsPersister mTarget;
+
+    private LaunchParams mResult;
+
+    @Before
+    public void setUp() throws Exception {
+        mPersisterQueue = new TestPersisterQueue();
+
+        final File cacheFolder = InstrumentationRegistry.getContext().getCacheDir();
+        mFolder = new File(cacheFolder, "launch_params_tests");
+        deleteRecursively(mFolder);
+
+        setupActivityTaskManagerService();
+
+        mDisplayUniqueId = "test:" + Integer.toString(sNextUniqueId++);
+        final DisplayInfo info = new DisplayInfo();
+        info.uniqueId = mDisplayUniqueId;
+        mTestDisplay = createNewActivityDisplay(info);
+        mSupervisor.addChild(mTestDisplay, ActivityDisplay.POSITION_TOP);
+        when(mSupervisor.getActivityDisplay(eq(mDisplayUniqueId))).thenReturn(mTestDisplay);
+
+        ActivityStack stack = mTestDisplay.createStack(TEST_WINDOWING_MODE,
+                ACTIVITY_TYPE_STANDARD, /* onTop */ true);
+        mTestTask = new TaskBuilder(mSupervisor).setComponent(TEST_COMPONENT).setStack(stack)
+                .build();
+        mTestTask.userId = TEST_USER_ID;
+        mTestTask.mLastNonFullscreenBounds = TEST_BOUNDS;
+        mTestTask.hasBeenVisible = true;
+
+        mTaskWithDifferentComponent = new TaskBuilder(mSupervisor)
+                .setComponent(ALTERNATIVE_COMPONENT).build();
+        mTaskWithDifferentComponent.userId = TEST_USER_ID;
+
+        mTaskWithDifferentUser = new TaskBuilder(mSupervisor).setComponent(TEST_COMPONENT).build();
+        mTaskWithDifferentUser.userId = ALTERNATIVE_USER_ID;
+
+        mTarget = new LaunchParamsPersister(mPersisterQueue, mSupervisor, mUserFolderGetter);
+
+        LocalServices.removeServiceForTest(PackageManagerInternal.class);
+        mMockPmi = mock(PackageManagerInternal.class);
+        LocalServices.addService(PackageManagerInternal.class, mMockPmi);
+        when(mMockPmi.getPackageList(any())).thenReturn(new PackageList(
+                Collections.singletonList(TEST_COMPONENT.getPackageName()), /* observer */ null));
+        mTarget.onSystemReady();
+
+        final ArgumentCaptor<PackageManagerInternal.PackageListObserver> observerCaptor =
+                ArgumentCaptor.forClass(PackageManagerInternal.PackageListObserver.class);
+        verify(mMockPmi).getPackageList(observerCaptor.capture());
+        mObserver = observerCaptor.getValue();
+
+        mResult = new LaunchParams();
+        mResult.reset();
+    }
+
+    @Test
+    public void testReturnsEmptyLaunchParamsByDefault() {
+        mResult.mWindowingMode = WINDOWING_MODE_FULLSCREEN;
+
+        mTarget.getLaunchParams(mTestTask, null, mResult);
+
+        assertTrue("Default result should be empty.", mResult.isEmpty());
+    }
+
+    @Test
+    public void testSavesAndRestoresLaunchParamsInSameInstance() {
+        mTarget.saveTask(mTestTask);
+
+        mTarget.getLaunchParams(mTestTask, null, mResult);
+
+        assertEquals(mTestDisplay.mDisplayId, mResult.mPreferredDisplayId);
+        assertEquals(TEST_WINDOWING_MODE, mResult.mWindowingMode);
+        assertEquals(TEST_BOUNDS, mResult.mBounds);
+    }
+
+    @Test
+    public void testFetchesSameResultWithActivity() {
+        mTarget.saveTask(mTestTask);
+
+        final ActivityRecord activity = new ActivityBuilder(mService).setComponent(TEST_COMPONENT)
+                .setUid(TEST_USER_ID * UserHandle.PER_USER_RANGE).build();
+
+        mTarget.getLaunchParams(null, activity, mResult);
+
+        assertEquals(mTestDisplay.mDisplayId, mResult.mPreferredDisplayId);
+        assertEquals(TEST_WINDOWING_MODE, mResult.mWindowingMode);
+        assertEquals(TEST_BOUNDS, mResult.mBounds);
+    }
+
+    @Test
+    public void testReturnsEmptyDisplayIfDisplayIsNotFound() {
+        mTarget.saveTask(mTestTask);
+
+        when(mSupervisor.getActivityDisplay(eq(mDisplayUniqueId))).thenReturn(null);
+
+        mTarget.getLaunchParams(mTestTask, null, mResult);
+
+        assertEquals(INVALID_DISPLAY, mResult.mPreferredDisplayId);
+        assertEquals(TEST_WINDOWING_MODE, mResult.mWindowingMode);
+        assertEquals(TEST_BOUNDS, mResult.mBounds);
+    }
+
+    @Test
+    public void testReturnsEmptyLaunchParamsUserIdMismatch() {
+        mTarget.saveTask(mTestTask);
+
+        mResult.mWindowingMode = WINDOWING_MODE_FULLSCREEN;
+        mTarget.getLaunchParams(mTaskWithDifferentUser, null, mResult);
+
+        assertTrue("Result should be empty.", mResult.isEmpty());
+    }
+
+    @Test
+    public void testReturnsEmptyLaunchParamsComponentMismatch() {
+        mTarget.saveTask(mTestTask);
+
+        mResult.mWindowingMode = WINDOWING_MODE_FULLSCREEN;
+        mTarget.getLaunchParams(mTaskWithDifferentComponent, null, mResult);
+
+        assertTrue("Result should be empty.", mResult.isEmpty());
+    }
+
+    @Test
+    public void testSavesAndRestoresLaunchParamsAcrossInstances() {
+        mTarget.saveTask(mTestTask);
+        mPersisterQueue.flush();
+
+        final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
+                mUserFolderGetter);
+        target.onSystemReady();
+        target.onUnlockUser(TEST_USER_ID);
+
+        target.getLaunchParams(mTestTask, null, mResult);
+
+        assertEquals(mTestDisplay.mDisplayId, mResult.mPreferredDisplayId);
+        assertEquals(TEST_WINDOWING_MODE, mResult.mWindowingMode);
+        assertEquals(TEST_BOUNDS, mResult.mBounds);
+    }
+
+    @Test
+    public void testClearsRecordsOfTheUserOnUserCleanUp() {
+        mTarget.saveTask(mTestTask);
+
+        ActivityStack stack = mTestDisplay.createStack(TEST_WINDOWING_MODE,
+                ACTIVITY_TYPE_STANDARD, /* onTop */ true);
+        final TaskRecord anotherTaskOfTheSameUser = new TaskBuilder(mSupervisor)
+                .setComponent(ALTERNATIVE_COMPONENT)
+                .setUserId(TEST_USER_ID)
+                .setStack(stack)
+                .build();
+        anotherTaskOfTheSameUser.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        anotherTaskOfTheSameUser.setBounds(200, 300, 400, 500);
+        anotherTaskOfTheSameUser.hasBeenVisible = true;
+        mTarget.saveTask(anotherTaskOfTheSameUser);
+
+        stack = mTestDisplay.createStack(TEST_WINDOWING_MODE,
+                ACTIVITY_TYPE_STANDARD, /* onTop */ true);
+        final TaskRecord anotherTaskOfDifferentUser = new TaskBuilder(mSupervisor)
+                .setComponent(TEST_COMPONENT)
+                .setUserId(ALTERNATIVE_USER_ID)
+                .setStack(stack)
+                .build();
+        anotherTaskOfDifferentUser.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        anotherTaskOfDifferentUser.setBounds(300, 400, 500, 600);
+        anotherTaskOfDifferentUser.hasBeenVisible = true;
+        mTarget.saveTask(anotherTaskOfDifferentUser);
+
+        mTarget.onCleanupUser(TEST_USER_ID);
+
+        mTarget.getLaunchParams(anotherTaskOfDifferentUser, null, mResult);
+        assertFalse("Shouldn't clear record of a different user.", mResult.isEmpty());
+
+        mTarget.getLaunchParams(mTestTask, null, mResult);
+        assertTrue("Should have cleaned record for " + TEST_COMPONENT, mResult.isEmpty());
+
+        mTarget.getLaunchParams(anotherTaskOfTheSameUser, null, mResult);
+        assertTrue("Should have cleaned record for " + ALTERNATIVE_COMPONENT, mResult.isEmpty());
+    }
+
+    @Test
+    public void testClearsRecordInMemoryOnPackageUninstalled() {
+        mTarget.saveTask(mTestTask);
+
+        mObserver.onPackageRemoved(TEST_COMPONENT.getPackageName());
+
+        mTarget.getLaunchParams(mTestTask, null, mResult);
+
+        assertTrue("Result should be empty.", mResult.isEmpty());
+    }
+
+    @Test
+    public void testClearsWriteQueueItemOnPackageUninstalled() {
+        mTarget.saveTask(mTestTask);
+
+        mObserver.onPackageRemoved(TEST_COMPONENT.getPackageName());
+
+        final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
+                mUserFolderGetter);
+        target.onSystemReady();
+        target.onUnlockUser(TEST_USER_ID);
+
+        target.getLaunchParams(mTestTask, null, mResult);
+
+        assertTrue("Result should be empty.", mResult.isEmpty());
+    }
+
+    @Test
+    public void testClearsFileOnPackageUninstalled() {
+        mTarget.saveTask(mTestTask);
+        mPersisterQueue.flush();
+
+        mObserver.onPackageRemoved(TEST_COMPONENT.getPackageName());
+
+        final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
+                mUserFolderGetter);
+        target.onSystemReady();
+        target.onUnlockUser(TEST_USER_ID);
+
+        target.getLaunchParams(mTestTask, null, mResult);
+
+        assertTrue("Result should be empty.", mResult.isEmpty());
+    }
+
+    @Test
+    public void testClearsRemovedPackageFilesOnStartUp() {
+        mTarget.saveTask(mTestTask);
+        mPersisterQueue.flush();
+
+        when(mMockPmi.getPackageList(any())).thenReturn(
+                new PackageList(Collections.emptyList(), /* observer */ null));
+
+        final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
+                mUserFolderGetter);
+        target.onSystemReady();
+        target.onUnlockUser(TEST_USER_ID);
+
+        target.getLaunchParams(mTestTask, null, mResult);
+
+        assertTrue("Result should be empty.", mResult.isEmpty());
+    }
+
+    private static boolean deleteRecursively(File file) {
+        boolean result = true;
+        if (file.isDirectory()) {
+            for (File child : file.listFiles()) {
+                result &= deleteRecursively(child);
+            }
+        }
+
+        result &= file.delete();
+        return result;
+    }
+
+    /**
+     * Test double to {@link PersisterQueue}. This is not thread-safe and caller should always use
+     * {@link #flush()} to execute write items in it.
+     */
+    static class TestPersisterQueue extends PersisterQueue {
+        private List<WriteQueueItem> mWriteQueue = new ArrayList<>();
+        private List<Listener> mListeners = new ArrayList<>();
+
+        @Override
+        void flush() {
+            while (!mWriteQueue.isEmpty()) {
+                final WriteQueueItem item = mWriteQueue.remove(0);
+                final boolean queueEmpty = mWriteQueue.isEmpty();
+                for (Listener listener : mListeners) {
+                    listener.onPreProcessItem(queueEmpty);
+                }
+                item.process();
+            }
+        }
+
+        @Override
+        void startPersisting() {
+            // Do nothing. We're not using threading logic.
+        }
+
+        @Override
+        void stopPersisting() {
+            // Do nothing. We're not using threading logic.
+        }
+
+        @Override
+        void addItem(WriteQueueItem item, boolean flush) {
+            mWriteQueue.add(item);
+            if (flush) {
+                flush();
+            }
+        }
+
+        @Override
+        synchronized <T extends WriteQueueItem> T findLastItem(Predicate<T> predicate,
+                Class<T> clazz) {
+            for (int i = mWriteQueue.size() - 1; i >= 0; --i) {
+                WriteQueueItem writeQueueItem = mWriteQueue.get(i);
+                if (clazz.isInstance(writeQueueItem)) {
+                    T item = clazz.cast(writeQueueItem);
+                    if (predicate.test(item)) {
+                        return item;
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        @Override
+        synchronized <T extends WriteQueueItem> void removeItems(Predicate<T> predicate,
+                Class<T> clazz) {
+            for (int i = mWriteQueue.size() - 1; i >= 0; --i) {
+                WriteQueueItem writeQueueItem = mWriteQueue.get(i);
+                if (clazz.isInstance(writeQueueItem)) {
+                    T item = clazz.cast(writeQueueItem);
+                    if (predicate.test(item)) {
+                        mWriteQueue.remove(i);
+                    }
+                }
+            }
+        }
+
+        @Override
+        void addListener(Listener listener) {
+            mListeners.add(listener);
+        }
+
+        @Override
+        void yieldIfQueueTooDeep() {
+            // Do nothing. We're not using threading logic.
+        }
+    }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
index 20150b4..434ba93 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
@@ -185,7 +185,7 @@
                 mLatch.await(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE, TimeUnit.MILLISECONDS));
         assertEquals("Target didn't process all items.", 2, mItemCount.get());
         processDuration = SystemClock.uptimeMillis() - dispatchTime;
-        assertTrue("Target didn't wait enough time before processing item."
+        assertTrue("Target didn't wait enough time before processing item. Process time: "
                         + processDuration + "ms pre task delay: "
                         + PRE_TASK_DELAY_MS + "ms",
                 processDuration >= PRE_TASK_DELAY_MS);
@@ -246,6 +246,39 @@
     }
 
     @Test
+    public void testUpdateLastOrAddItemUpdatesMatchedItem() throws Exception {
+        mLatch = new CountDownLatch(1);
+        final MatchingTestItem scheduledItem = new MatchingTestItem(true);
+        final MatchingTestItem expected = new MatchingTestItem(true);
+        synchronized (mTarget) {
+            mTarget.addItem(scheduledItem, false);
+            mTarget.updateLastOrAddItem(expected, false);
+        }
+
+        assertSame(expected, scheduledItem.mUpdateFromItem);
+        assertTrue("Target didn't call callback enough times.",
+                mLatch.await(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE, TimeUnit.MILLISECONDS));
+        assertEquals("Target didn't process item.", 1, mItemCount.get());
+    }
+
+    @Test
+    public void testUpdateLastOrAddItemUpdatesAddItemWhenNoMatch() throws Exception {
+        mLatch = new CountDownLatch(2);
+        final MatchingTestItem scheduledItem = new MatchingTestItem(false);
+        final MatchingTestItem expected = new MatchingTestItem(true);
+        synchronized (mTarget) {
+            mTarget.addItem(scheduledItem, false);
+            mTarget.updateLastOrAddItem(expected, false);
+        }
+
+        assertNull(scheduledItem.mUpdateFromItem);
+        assertTrue("Target didn't call callback enough times.",
+                mLatch.await(PRE_TASK_DELAY_MS + INTER_WRITE_DELAY_MS + TIMEOUT_ALLOWANCE,
+                        TimeUnit.MILLISECONDS));
+        assertEquals("Target didn't process item.", 2, mItemCount.get());
+    }
+
+    @Test
     public void testRemoveItemsRemoveMatchedItem() throws Exception {
         mLatch = new CountDownLatch(1);
         synchronized (mTarget) {
@@ -283,18 +316,30 @@
         mSetUpLatch.countDown();
     }
 
-    private class TestItem implements PersisterQueue.WriteQueueItem {
+    private class TestItem<T extends TestItem<T>> implements PersisterQueue.WriteQueueItem<T> {
         @Override
         public void process() {
             mItemCount.getAndIncrement();
         }
     }
 
-    private class MatchingTestItem extends TestItem {
+    private class MatchingTestItem extends TestItem<MatchingTestItem> {
         private boolean mMatching;
 
+        private MatchingTestItem mUpdateFromItem;
+
         private MatchingTestItem(boolean matching) {
             mMatching = matching;
         }
+
+        @Override
+        public boolean matches(MatchingTestItem item) {
+            return item.mMatching;
+        }
+
+        @Override
+        public void updateFrom(MatchingTestItem item) {
+            mUpdateFromItem = item;
+        }
     }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 95965c8..2168fab 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -41,6 +41,7 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.platform.test.annotations.Presubmit;
+import android.view.Display;
 import android.view.Gravity;
 
 import androidx.test.filters.FlakyTest;
@@ -110,6 +111,16 @@
     }
 
     @Test
+    public void testUsesDefaultDisplayIfPreviousDisplayNotExists() {
+        mCurrent.mPreferredDisplayId = 19;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(DEFAULT_DISPLAY, mResult.mPreferredDisplayId);
+    }
+
+    @Test
     public void testUsesPreviousDisplayIdIfSet() {
         createNewActivityDisplay(WINDOWING_MODE_FREEFORM);
         final TestActivityDisplay display = createNewActivityDisplay(WINDOWING_MODE_FULLSCREEN);
@@ -856,30 +867,48 @@
     }
 
     @Test
-    public void testAdjustBoundsToFitDisplay_LargerThanDisplay() {
+    public void testAdjustBoundsToFitNewDisplay_LargerThanDisplay() {
         final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
                 WINDOWING_MODE_FREEFORM);
 
-        Configuration overrideConfig = new Configuration();
-        overrideConfig.setTo(mSupervisor.getOverrideConfiguration());
-        overrideConfig.setLayoutDirection(new Locale("ar"));
-        mSupervisor.onConfigurationChanged(overrideConfig);
-
         final ActivityOptions options = ActivityOptions.makeBasic();
         options.setLaunchDisplayId(freeformDisplay.mDisplayId);
 
-        final ActivityRecord source = createSourceActivity(freeformDisplay);
-        source.setBounds(1720, 680, 1920, 1080);
+        mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+        mCurrent.mBounds.set(100, 200, 2120, 1380);
 
         mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
 
         assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
-                mActivity, source, options, mCurrent, mResult));
+                mActivity, /* source */ null, options, mCurrent, mResult));
 
-        final Rect displayBounds = freeformDisplay.getBounds();
-        assertTrue("display bounds doesn't contain result. display bounds: "
-                        + displayBounds + " result: " + mResult.mBounds,
-                displayBounds.contains(mResult.mBounds));
+        assertTrue("Result bounds should start from origin, but it's " + mResult.mBounds,
+                mResult.mBounds.left == 0 && mResult.mBounds.top == 0);
+    }
+
+    @Test
+    public void testAdjustBoundsToFitNewDisplay_LargerThanDisplay_RTL() {
+        final Configuration overrideConfig = mSupervisor.getOverrideConfiguration();
+        // Egyptian Arabic is a RTL language.
+        overrideConfig.setLayoutDirection(new Locale("ar", "EG"));
+        mSupervisor.onOverrideConfigurationChanged(overrideConfig);
+
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+        mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+        mCurrent.mBounds.set(100, 200, 2120, 1380);
+
+        mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, options, mCurrent, mResult));
+
+        assertTrue("Result bounds should start from origin, but it's " + mResult.mBounds,
+                mResult.mBounds.left == -100 && mResult.mBounds.top == 0);
     }
 
     @Test
@@ -1021,6 +1050,41 @@
         assertEquals(new Rect(0, 0, 1680, 953), mResult.mBounds);
     }
 
+    @Test
+    public void testAdjustsBoundsToFitInDisplayFullyResolvedBounds() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        mCurrent.mPreferredDisplayId = Display.INVALID_DISPLAY;
+        mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+        mCurrent.mBounds.set(-100, -200, 200, 100);
+
+        final ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchDisplayId(freeformDisplay.mDisplayId);
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(new Rect(0, 0, 300, 300), mResult.mBounds);
+    }
+
+    @Test
+    public void testAdjustsBoundsToAvoidConflictFullyResolvedBounds() {
+        final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+                WINDOWING_MODE_FREEFORM);
+
+        addFreeformTaskTo(freeformDisplay, new Rect(0, 0, 200, 100));
+
+        mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+        mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
+        mCurrent.mBounds.set(0, 0, 200, 100);
+
+        assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
+                mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+
+        assertEquals(new Rect(120, 0, 320, 100), mResult.mBounds);
+    }
+
     private TestActivityDisplay createNewActivityDisplay(int windowingMode) {
         final TestActivityDisplay display = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
         display.setWindowingMode(windowingMode);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 4455630..72d7c90 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -19,9 +19,12 @@
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
 
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.sameInstance;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
 import android.app.ActivityManager;
@@ -92,6 +95,18 @@
         assertNotNull(TaskRecord.getTaskRecordFactory());
     }
 
+    /** Ensure we have no chance to modify the original intent. */
+    @Test
+    public void testCopyBaseIntentForTaskInfo() {
+        final TaskRecord task = createTaskRecord(1);
+        task.lastTaskDescription = new ActivityManager.TaskDescription();
+        final ActivityManager.RecentTaskInfo info = new ActivityManager.RecentTaskInfo();
+        task.fillTaskInfo(info, new TaskRecord.TaskActivitiesReport());
+
+        // The intent of info should be a copy so assert that they are different instances.
+        assertThat(info.baseIntent, not(sameInstance(task.getBaseIntent())));
+    }
+
     @Test
     public void testCreateTestRecordUsingCustomizedFactory() throws Exception {
         TestTaskRecordFactory factory = new TestTaskRecordFactory();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 115bcb1..3b4ab38 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -38,15 +38,6 @@
  * to WindowManager related test functionality.
  */
 public class WindowTestUtils {
-    private static int sNextTaskId = 0;
-
-    /** Retrieves an instance of a mock {@link WindowManagerService}. */
-    static WindowManagerService getMockWindowManagerService() {
-        final WindowManagerService service = mock(WindowManagerService.class);
-        final WindowManagerGlobalLock lock = new WindowManagerGlobalLock();
-        doReturn(lock).when(service).getWindowManagerLock();
-        return service;
-    }
 
     /** An extension of {@link DisplayContent} to gain package scoped access. */
     public static class TestDisplayContent extends DisplayContent {
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 6a74564..152831f 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -27,21 +27,24 @@
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_EXEMPTED_SYNC_START;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_FOREGROUND_SERVICE_START;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_FOREGROUND_SERVICE_STOP;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_NOTIFICATION_SEEN;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SLICE_PINNED;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SLICE_PINNED_PRIV;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYNC_ADAPTER;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYSTEM_INTERACTION;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYSTEM_UPDATE;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACTION;
-import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SLICE_PINNED;
-import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SLICE_PINNED_PRIV;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_NEVER;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+
 import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
 import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 
@@ -340,14 +343,21 @@
     }
 
     void setAppIdleEnabled(boolean enabled) {
-        mAppIdleEnabled = enabled;
+        synchronized (mAppIdleLock) {
+            if (mAppIdleEnabled != enabled) {
+                final boolean oldParoleState = isParoledOrCharging();
+                mAppIdleEnabled = enabled;
+                if (isParoledOrCharging() != oldParoleState) {
+                    postParoleStateChanged();
+                }
+            }
+        }
     }
 
     public void onBootPhase(int phase) {
         mInjector.onBootPhase(phase);
         if (phase == PHASE_SYSTEM_SERVICES_READY) {
             Slog.d(TAG, "Setting app idle enabled state");
-            setAppIdleEnabled(mInjector.isAppIdleEnabled());
             // Observe changes to the threshold
             SettingsObserver settingsObserver = new SettingsObserver(mHandler);
             settingsObserver.registerObserver();
@@ -836,6 +846,8 @@
             // Inform listeners if necessary
             if ((event.mEventType == UsageEvents.Event.MOVE_TO_FOREGROUND
                     || event.mEventType == UsageEvents.Event.MOVE_TO_BACKGROUND
+                    || event.mEventType == UsageEvents.Event.FOREGROUND_SERVICE_START
+                    || event.mEventType == UsageEvents.Event.FOREGROUND_SERVICE_STOP
                     || event.mEventType == UsageEvents.Event.SYSTEM_INTERACTION
                     || event.mEventType == UsageEvents.Event.USER_INTERACTION
                     || event.mEventType == UsageEvents.Event.NOTIFICATION_SEEN
@@ -888,6 +900,10 @@
         switch (eventType) {
             case UsageEvents.Event.MOVE_TO_FOREGROUND: return REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
             case UsageEvents.Event.MOVE_TO_BACKGROUND: return REASON_SUB_USAGE_MOVE_TO_BACKGROUND;
+            case UsageEvents.Event.FOREGROUND_SERVICE_START:
+                return REASON_SUB_USAGE_FOREGROUND_SERVICE_START;
+            case UsageEvents.Event.FOREGROUND_SERVICE_STOP:
+                return REASON_SUB_USAGE_FOREGROUND_SERVICE_STOP;
             case UsageEvents.Event.SYSTEM_INTERACTION: return REASON_SUB_USAGE_SYSTEM_INTERACTION;
             case UsageEvents.Event.USER_INTERACTION: return REASON_SUB_USAGE_USER_INTERACTION;
             case UsageEvents.Event.NOTIFICATION_SEEN: return REASON_SUB_USAGE_NOTIFICATION_SEEN;
@@ -1842,8 +1858,6 @@
                         mContext.getContentResolver(),
                         Global.APP_IDLE_CONSTANTS));
             }
-            // Check if app_idle_enabled has changed
-            setAppIdleEnabled(mInjector.isAppIdleEnabled());
 
             // Look at global settings for this.
             // TODO: Maybe apply different thresholds for different users.
@@ -1915,6 +1929,10 @@
                         (KEY_STABLE_CHARGING_THRESHOLD,
                                 COMPRESS_TIME ? ONE_MINUTE : DEFAULT_STABLE_CHARGING_THRESHOLD);
             }
+
+            // Check if app_idle_enabled has changed. Do this after getting the rest of the settings
+            // in case we need to change something based on the new values.
+            setAppIdleEnabled(mInjector.isAppIdleEnabled());
         }
 
         long[] parseLongArray(String values, long[] defaults) {
diff --git a/services/usage/java/com/android/server/usage/AppTimeLimitController.java b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
index eaaf9b2..8e1ede1 100644
--- a/services/usage/java/com/android/server/usage/AppTimeLimitController.java
+++ b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
@@ -118,9 +118,14 @@
         void removeUsageGroup(UsageGroup group) {
             final int size = group.mObserved.length;
             for (int i = 0; i < size; i++) {
-                final ArrayList<UsageGroup> list = observedMap.get(group.mObserved[i]);
+                final String observed = group.mObserved[i];
+                final ArrayList<UsageGroup> list = observedMap.get(observed);
                 if (list != null) {
                     list.remove(group);
+                    if (list.isEmpty()) {
+                        // No more observers for this observed entity, remove from map
+                        observedMap.remove(observed);
+                    }
                 }
             }
         }
@@ -137,7 +142,7 @@
             }
             pw.println();
             pw.print(" Observed Entities:");
-            final int nEntities = currentlyActive.size();
+            final int nEntities = observedMap.size();
             for (int i = 0; i < nEntities; i++) {
                 pw.print(observedMap.keyAt(i));
                 pw.print(", ");
@@ -183,7 +188,7 @@
                 pw.println();
             }
             pw.println("    Session Usage Groups:");
-            final int nSessionUsageGroups = appUsageGroups.size();
+            final int nSessionUsageGroups = sessionUsageGroups.size();
             for (int i = 0; i < nSessionUsageGroups; i++) {
                 sessionUsageGroups.valueAt(i).dump(pw);
                 pw.println();
@@ -616,7 +621,7 @@
             AppUsageGroup group = observerApp.appUsageGroups.get(observerId);
             if (group != null) {
                 // Remove previous app usage group associated with observerId
-                observerApp.appUsageGroups.get(observerId).remove();
+                group.remove();
             }
 
             final int observerIdCount = observerApp.appUsageGroups.size();
@@ -646,8 +651,12 @@
      */
     public void removeAppUsageObserver(int requestingUid, int observerId, @UserIdInt int userId) {
         synchronized (mLock) {
-            ObserverAppData observerApp = getOrCreateObserverAppDataLocked(requestingUid);
-            observerApp.appUsageGroups.get(observerId).remove();
+            final ObserverAppData observerApp = getOrCreateObserverAppDataLocked(requestingUid);
+            final AppUsageGroup group = observerApp.appUsageGroups.get(observerId);
+            if (group != null) {
+                // Remove previous app usage group associated with observerId
+                group.remove();
+            }
         }
     }
 
@@ -668,8 +677,8 @@
             ObserverAppData observerApp = getOrCreateObserverAppDataLocked(requestingUid);
             SessionUsageGroup group = observerApp.sessionUsageGroups.get(observerId);
             if (group != null) {
-                // Remove previous app usage group associated with observerId
-                observerApp.sessionUsageGroups.get(observerId).remove();
+                // Remove previous session usage group associated with observerId
+                group.remove();
             }
 
             final int observerIdCount = observerApp.sessionUsageGroups.size();
@@ -696,8 +705,12 @@
     public void removeUsageSessionObserver(int requestingUid, int observerId,
             @UserIdInt int userId) {
         synchronized (mLock) {
-            ObserverAppData observerApp = getOrCreateObserverAppDataLocked(requestingUid);
-            observerApp.sessionUsageGroups.get(observerId).remove();
+            final ObserverAppData observerApp = getOrCreateObserverAppDataLocked(requestingUid);
+            final SessionUsageGroup group = observerApp.sessionUsageGroups.get(observerId);
+            if (group != null) {
+                // Remove previous app usage group associated with observerId
+                group.remove();
+            }
         }
     }
 
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index db9972f..8405267 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -18,7 +18,6 @@
 import android.app.usage.ConfigurationStats;
 import android.app.usage.EventList;
 import android.app.usage.EventStats;
-import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.content.res.Configuration;
@@ -26,12 +25,16 @@
 import android.util.ArraySet;
 import android.util.proto.ProtoInputStream;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.IOException;
 import java.util.List;
 
-import com.android.internal.annotations.VisibleForTesting;
-
 public class IntervalStats {
+    public static final int CURRENT_MAJOR_VERSION = 1;
+    public static final int CURRENT_MINOR_VERSION = 1;
+    public int majorVersion = CURRENT_MAJOR_VERSION;
+    public int minorVersion = CURRENT_MINOR_VERSION;
     public long beginTime;
     public long endTime;
     public long lastTimeSaved;
@@ -219,8 +222,12 @@
         switch (eventType) {
             case UsageEvents.Event.MOVE_TO_FOREGROUND:
             case UsageEvents.Event.MOVE_TO_BACKGROUND:
+            case UsageEvents.Event.FOREGROUND_SERVICE_START:
+            case UsageEvents.Event.FOREGROUND_SERVICE_STOP:
             case UsageEvents.Event.END_OF_DAY:
+            case UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE:
             case UsageEvents.Event.CONTINUE_PREVIOUS_DAY:
+            case UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE:
                 return true;
         }
         return false;
@@ -239,32 +246,9 @@
      * @hide
      */
     @VisibleForTesting
-    public void update(String packageName, long timeStamp, int eventType) {
+    public void update(String packageName, String className, long timeStamp, int eventType) {
         UsageStats usageStats = getOrCreateUsageStats(packageName);
-
-        // TODO(adamlesinski): Ensure that we recover from incorrect event sequences
-        // like double MOVE_TO_BACKGROUND, etc.
-        if (eventType == UsageEvents.Event.MOVE_TO_BACKGROUND ||
-                eventType == UsageEvents.Event.END_OF_DAY) {
-            if (usageStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
-                    usageStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
-                usageStats.mTotalTimeInForeground += timeStamp - usageStats.mLastTimeUsed;
-            }
-        }
-
-        if (isStatefulEvent(eventType)) {
-            usageStats.mLastEvent = eventType;
-        }
-
-        if (isUserVisibleEvent(eventType)) {
-            usageStats.mLastTimeUsed = timeStamp;
-        }
-        usageStats.mEndTimeStamp = timeStamp;
-
-        if (eventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {
-            usageStats.mLaunchCount += 1;
-        }
-
+        usageStats.update(className, timeStamp, eventType);
         endTime = timeStamp;
     }
 
@@ -372,4 +356,19 @@
         }
         return mStringCache.valueAt(index);
     }
+
+    /**
+     * When an IntervalStats object is deserialized, if the object's version number
+     * is lower than current version number, optionally perform a upgrade.
+     */
+    void upgradeIfNeeded() {
+        // We only uprade on majorVersion change, no need to upgrade on minorVersion change.
+        if (!(majorVersion < CURRENT_MAJOR_VERSION)) {
+            return;
+        }
+        /*
+          Optional upgrade code here.
+        */
+        majorVersion = CURRENT_MAJOR_VERSION;
+    }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProto.java b/services/usage/java/com/android/server/usage/UsageStatsProto.java
index 30d303f..8e1c060 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProto.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProto.java
@@ -21,13 +21,12 @@
 import android.app.usage.UsageStats;
 import android.content.res.Configuration;
 import android.util.ArrayMap;
-
 import android.util.Slog;
 import android.util.proto.ProtoInputStream;
 import android.util.proto.ProtoOutputStream;
 
-import java.io.InputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.ProtocolException;
 import java.util.ArrayList;
@@ -105,6 +104,7 @@
                     stats = tempPackageIndex;
                     break;
                 case (int) IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS:
+                    // Time attributes stored is an offset of the beginTime.
                     stats.mLastTimeUsed = statsOut.beginTime + proto.readLong(
                             IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS);
                     break;
@@ -113,7 +113,8 @@
                             IntervalStatsProto.UsageStats.TOTAL_TIME_ACTIVE_MS);
                     break;
                 case (int) IntervalStatsProto.UsageStats.LAST_EVENT:
-                    stats.mLastEvent = proto.readInt(IntervalStatsProto.UsageStats.LAST_EVENT);
+                    stats.mLastEvent =
+                            proto.readInt(IntervalStatsProto.UsageStats.LAST_EVENT);
                     break;
                 case (int) IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT:
                     stats.mAppLaunchCount = proto.readInt(
@@ -125,6 +126,15 @@
                     loadChooserCounts(proto, stats);
                     proto.end(chooserToken);
                     break;
+                case (int) IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS:
+                    // Time attributes stored is an offset of the beginTime.
+                    stats.mLastTimeForegroundServiceUsed = statsOut.beginTime + proto.readLong(
+                            IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS);
+                    break;
+                case (int) IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS:
+                    stats.mTotalTimeForegroundServiceUsed = proto.readLong(
+                            IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS);
+                    break;
             }
         }
         if (stats.mLastTimeUsed == 0) {
@@ -315,11 +325,18 @@
                     + ") not found in IntervalStats string cache");
             proto.write(IntervalStatsProto.UsageStats.PACKAGE, usageStats.mPackageName);
         }
+        // Time attributes stored as an offset of the beginTime.
         proto.write(IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS,
                 usageStats.mLastTimeUsed - stats.beginTime);
         proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_ACTIVE_MS,
                 usageStats.mTotalTimeInForeground);
-        proto.write(IntervalStatsProto.UsageStats.LAST_EVENT, usageStats.mLastEvent);
+        proto.write(IntervalStatsProto.UsageStats.LAST_EVENT,
+                usageStats.mLastEvent);
+        // Time attributes stored as an offset of the beginTime.
+        proto.write(IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS,
+                usageStats.mLastTimeForegroundServiceUsed - stats.beginTime);
+        proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS,
+                usageStats.mTotalTimeForegroundServiceUsed);
         proto.write(IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT, usageStats.mAppLaunchCount);
         writeChooserCounts(proto, usageStats);
         proto.end(token);
@@ -471,6 +488,14 @@
                     statsOut.endTime = statsOut.beginTime + proto.readLong(
                             IntervalStatsProto.END_TIME_MS);
                     break;
+                case (int) IntervalStatsProto.MAJOR_VERSION:
+                    statsOut.majorVersion = proto.readInt(
+                            IntervalStatsProto.MAJOR_VERSION);
+                    break;
+                case (int) IntervalStatsProto.MINOR_VERSION:
+                    statsOut.minorVersion = proto.readInt(
+                            IntervalStatsProto.MINOR_VERSION);
+                    break;
                 case (int) IntervalStatsProto.INTERACTIVE:
                     loadCountAndTime(proto, IntervalStatsProto.INTERACTIVE,
                             statsOut.interactiveTracker);
@@ -505,6 +530,7 @@
                         // endTime not assigned, assume default value of 0 plus beginTime
                         statsOut.endTime = statsOut.beginTime;
                     }
+                    statsOut.upgradeIfNeeded();
                     return;
             }
         }
@@ -519,6 +545,8 @@
     public static void write(OutputStream out, IntervalStats stats) throws IOException {
         final ProtoOutputStream proto = new ProtoOutputStream(out);
         proto.write(IntervalStatsProto.END_TIME_MS, stats.endTime - stats.beginTime);
+        proto.write(IntervalStatsProto.MAJOR_VERSION, stats.majorVersion);
+        proto.write(IntervalStatsProto.MINOR_VERSION, stats.minorVersion);
         // String pool should be written before the rest of the usage stats
         writeStringPool(proto, stats);
 
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index a68f9d3..d940620 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -15,19 +15,18 @@
  */
 package com.android.server.usage;
 
+import android.app.usage.ConfigurationStats;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStats;
+import android.content.res.Configuration;
+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;
 
-import android.app.usage.ConfigurationStats;
-import android.app.usage.EventList;
-import android.app.usage.UsageEvents;
-import android.app.usage.UsageStats;
-import android.content.res.Configuration;
-import android.util.ArrayMap;
-
 import java.io.IOException;
 import java.net.ProtocolException;
 
@@ -61,6 +60,7 @@
     private static final String FLAGS_ATTR = "flags";
     private static final String CLASS_ATTR = "class";
     private static final String TOTAL_TIME_ACTIVE_ATTR = "timeActive";
+    private static final String TOTAL_TIME_SERVICE_USED_ATTR = "timeServiceUsed";
     private static final String COUNT_ATTR = "count";
     private static final String ACTIVE_ATTR = "active";
     private static final String LAST_EVENT_ATTR = "lastEvent";
@@ -69,9 +69,12 @@
     private static final String STANDBY_BUCKET_ATTR = "standbyBucket";
     private static final String APP_LAUNCH_COUNT_ATTR = "appLaunchCount";
     private static final String NOTIFICATION_CHANNEL_ATTR = "notificationChannel";
+    private static final String MAJOR_VERSION_ATTR = "majorVersion";
+    private static final String MINOR_VERSION_ATTR = "minorVersion";
 
     // Time attributes stored as an offset of the beginTime.
     private static final String LAST_TIME_ACTIVE_ATTR = "lastTimeActive";
+    private static final String LAST_TIME_SERVICE_USED_ATTR = "lastTimeServiceUsed";
     private static final String END_TIME_ATTR = "endTime";
     private static final String TIME_ATTR = "time";
 
@@ -86,9 +89,14 @@
         // Apply the offset to the beginTime to find the absolute time.
         stats.mLastTimeUsed = statsOut.beginTime + XmlUtils.readLongAttribute(
                 parser, LAST_TIME_ACTIVE_ATTR);
+        stats.mLastTimeForegroundServiceUsed = statsOut.beginTime + XmlUtils.readLongAttribute(
+                parser, LAST_TIME_SERVICE_USED_ATTR);
         stats.mTotalTimeInForeground = XmlUtils.readLongAttribute(parser, TOTAL_TIME_ACTIVE_ATTR);
+        stats.mTotalTimeForegroundServiceUsed = XmlUtils.readLongAttribute(parser,
+                TOTAL_TIME_SERVICE_USED_ATTR);
         stats.mLastEvent = XmlUtils.readIntAttribute(parser, LAST_EVENT_ATTR);
-        stats.mAppLaunchCount = XmlUtils.readIntAttribute(parser, APP_LAUNCH_COUNT_ATTR, 0);
+        stats.mAppLaunchCount = XmlUtils.readIntAttribute(parser, APP_LAUNCH_COUNT_ATTR,
+                0);
         int eventCode;
         while ((eventCode = parser.next()) != XmlPullParser.END_DOCUMENT) {
             final String tag = parser.getName();
@@ -206,9 +214,12 @@
         // Write the time offset.
         XmlUtils.writeLongAttribute(xml, LAST_TIME_ACTIVE_ATTR,
                 usageStats.mLastTimeUsed - stats.beginTime);
-
+        XmlUtils.writeLongAttribute(xml, LAST_TIME_SERVICE_USED_ATTR,
+                usageStats.mLastTimeForegroundServiceUsed - stats.beginTime);
         XmlUtils.writeStringAttribute(xml, PACKAGE_ATTR, usageStats.mPackageName);
         XmlUtils.writeLongAttribute(xml, TOTAL_TIME_ACTIVE_ATTR, usageStats.mTotalTimeInForeground);
+        XmlUtils.writeLongAttribute(xml, TOTAL_TIME_SERVICE_USED_ATTR,
+                usageStats.mTotalTimeForegroundServiceUsed);
         XmlUtils.writeIntAttribute(xml, LAST_EVENT_ATTR, usageStats.mLastEvent);
         if (usageStats.mAppLaunchCount > 0) {
             XmlUtils.writeIntAttribute(xml, APP_LAUNCH_COUNT_ATTR, usageStats.mAppLaunchCount);
@@ -339,6 +350,8 @@
         }
 
         statsOut.endTime = statsOut.beginTime + XmlUtils.readLongAttribute(parser, END_TIME_ATTR);
+        statsOut.majorVersion = XmlUtils.readIntAttribute(parser, MAJOR_VERSION_ATTR);
+        statsOut.minorVersion = XmlUtils.readIntAttribute(parser, MINOR_VERSION_ATTR);
 
         int eventCode;
         int outerDepth = parser.getDepth();
@@ -391,6 +404,8 @@
      */
     public static void write(XmlSerializer xml, IntervalStats stats) throws IOException {
         XmlUtils.writeLongAttribute(xml, END_TIME_ATTR, stats.endTime - stats.beginTime);
+        XmlUtils.writeIntAttribute(xml, MAJOR_VERSION_ATTR, stats.majorVersion);
+        XmlUtils.writeIntAttribute(xml, MINOR_VERSION_ATTR, stats.minorVersion);
 
         writeCountAndTime(xml, INTERACTIVE_TAG, stats.interactiveTracker.count,
                 stats.interactiveTracker.duration);
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 1a8aba0..94d7dbb 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -22,9 +22,9 @@
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
+import android.content.Context;
 import android.content.res.Configuration;
 import android.os.SystemClock;
-import android.content.Context;
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -129,11 +129,17 @@
         for (IntervalStats stat : mCurrentStats) {
             final int pkgCount = stat.packageStats.size();
             for (int i = 0; i < pkgCount; i++) {
-                UsageStats pkgStats = stat.packageStats.valueAt(i);
-                if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
-                        pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
-                    stat.update(pkgStats.mPackageName, stat.lastTimeSaved,
-                            UsageEvents.Event.END_OF_DAY);
+                final UsageStats pkgStats = stat.packageStats.valueAt(i);
+                if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()
+                        || !pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
+                    if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()) {
+                        stat.update(pkgStats.mPackageName, null, stat.lastTimeSaved,
+                                UsageEvents.Event.END_OF_DAY);
+                    }
+                    if (!pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
+                        stat.update(pkgStats.mPackageName, null , stat.lastTimeSaved,
+                                UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE);
+                    }
                     notifyStatsChanged();
                 }
             }
@@ -218,7 +224,8 @@
                     stats.updateKeyguardHidden(event.mTimeStamp);
                 } break;
                 default: {
-                    stats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+                    stats.update(event.mPackage, event.getClassName(),
+                            event.mTimeStamp, event.mEventType);
                     if (incrementAppLaunch) {
                         stats.incrementAppLaunchCount(event.mPackage);
                     }
@@ -481,25 +488,43 @@
         final long startTime = SystemClock.elapsedRealtime();
         Slog.i(TAG, mLogPrefix + "Rolling over usage stats");
 
-        // Finish any ongoing events with an END_OF_DAY event. Make a note of which components
-        // need a new CONTINUE_PREVIOUS_DAY entry.
+        // Finish any ongoing events with an END_OF_DAY or ROLLOVER_FOREGROUND_SERVICE event.
+        // Make a note of which components need a new CONTINUE_PREVIOUS_DAY or
+        // CONTINUING_FOREGROUND_SERVICE entry.
         final Configuration previousConfig =
                 mCurrentStats[UsageStatsManager.INTERVAL_DAILY].activeConfiguration;
         ArraySet<String> continuePreviousDay = new ArraySet<>();
+        ArrayMap<String, ArrayMap<String, Integer>> continuePreviousDayForegroundActivity =
+                new ArrayMap<>();
+        ArrayMap<String, ArrayMap<String, Integer>> continuePreviousDayForegroundService =
+                new ArrayMap<>();
         for (IntervalStats stat : mCurrentStats) {
             final int pkgCount = stat.packageStats.size();
             for (int i = 0; i < pkgCount; i++) {
-                UsageStats pkgStats = stat.packageStats.valueAt(i);
-                if (pkgStats.mLastEvent == UsageEvents.Event.MOVE_TO_FOREGROUND ||
-                        pkgStats.mLastEvent == UsageEvents.Event.CONTINUE_PREVIOUS_DAY) {
+                final UsageStats pkgStats = stat.packageStats.valueAt(i);
+                if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()
+                        || !pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
+                    if (!pkgStats.mLastForegroundActivityEventMap.isEmpty()) {
+                        continuePreviousDayForegroundActivity.put(pkgStats.mPackageName,
+                                pkgStats.mLastForegroundActivityEventMap);
+                        stat.update(pkgStats.mPackageName, null,
+                                mDailyExpiryDate.getTimeInMillis() - 1,
+                                UsageEvents.Event.END_OF_DAY);
+                    }
+                    if (!pkgStats.mLastForegroundServiceEventMap.isEmpty()) {
+                        continuePreviousDayForegroundService.put(pkgStats.mPackageName,
+                                pkgStats.mLastForegroundServiceEventMap);
+                        stat.update(pkgStats.mPackageName, null,
+                                mDailyExpiryDate.getTimeInMillis() - 1,
+                                UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE);
+                    }
                     continuePreviousDay.add(pkgStats.mPackageName);
-                    stat.update(pkgStats.mPackageName, mDailyExpiryDate.getTimeInMillis() - 1,
-                            UsageEvents.Event.END_OF_DAY);
                     notifyStatsChanged();
                 }
             }
 
-            stat.updateConfigurationStats(null, mDailyExpiryDate.getTimeInMillis() - 1);
+            stat.updateConfigurationStats(null,
+                    mDailyExpiryDate.getTimeInMillis() - 1);
             stat.commitTime(mDailyExpiryDate.getTimeInMillis() - 1);
         }
 
@@ -509,10 +534,27 @@
 
         final int continueCount = continuePreviousDay.size();
         for (int i = 0; i < continueCount; i++) {
-            String name = continuePreviousDay.valueAt(i);
+            String pkgName = continuePreviousDay.valueAt(i);
             final long beginTime = mCurrentStats[UsageStatsManager.INTERVAL_DAILY].beginTime;
             for (IntervalStats stat : mCurrentStats) {
-                stat.update(name, beginTime, UsageEvents.Event.CONTINUE_PREVIOUS_DAY);
+                if (continuePreviousDayForegroundActivity.containsKey(pkgName)) {
+                    final ArrayMap<String, Integer> foregroundActivityEventMap =
+                            continuePreviousDayForegroundActivity.get(pkgName);
+                    final int size = foregroundActivityEventMap.size();
+                    for (int j = 0; j < size; j++) {
+                        stat.update(pkgName, foregroundActivityEventMap.keyAt(j), beginTime,
+                                UsageEvents.Event.CONTINUE_PREVIOUS_DAY);
+                    }
+                }
+                if (continuePreviousDayForegroundService.containsKey(pkgName)) {
+                    final ArrayMap<String, Integer> foregroundServiceEventMap =
+                            continuePreviousDayForegroundService.get(pkgName);
+                    final int size = foregroundServiceEventMap.size();
+                    for (int j = 0; j < size; j++) {
+                        stat.update(pkgName, foregroundServiceEventMap.keyAt(j), beginTime,
+                                UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE);
+                    }
+                }
                 stat.updateConfigurationStats(previousConfig, beginTime);
                 notifyStatsChanged();
             }
@@ -837,10 +879,18 @@
                 return "MOVE_TO_BACKGROUND";
             case UsageEvents.Event.MOVE_TO_FOREGROUND:
                 return "MOVE_TO_FOREGROUND";
+            case UsageEvents.Event.FOREGROUND_SERVICE_START:
+                return "FOREGROUND_SERVICE_START";
+            case UsageEvents.Event.FOREGROUND_SERVICE_STOP:
+                return "FOREGROUND_SERVICE_STOP";
             case UsageEvents.Event.END_OF_DAY:
                 return "END_OF_DAY";
+            case UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE:
+                return "ROLLOVER_FOREGROUND_SERVICE";
             case UsageEvents.Event.CONTINUE_PREVIOUS_DAY:
                 return "CONTINUE_PREVIOUS_DAY";
+            case UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE:
+                return "CONTINUING_FOREGROUND_SERVICE";
             case UsageEvents.Event.CONFIGURATION_CHANGE:
                 return "CONFIGURATION_CHANGE";
             case UsageEvents.Event.SYSTEM_INTERACTION:
@@ -865,8 +915,12 @@
                 return "SCREEN_INTERACTIVE";
             case UsageEvents.Event.SCREEN_NON_INTERACTIVE:
                 return "SCREEN_NON_INTERACTIVE";
+            case UsageEvents.Event.KEYGUARD_SHOWN:
+                return "KEYGUARD_SHOWN";
+            case UsageEvents.Event.KEYGUARD_HIDDEN:
+                return "KEYGUARD_HIDDEN";
             default:
-                return "UNKNOWN";
+                return "UNKNOWN_TYPE_" + eventType;
         }
     }
 
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 27b8cdf..60cb08f 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -153,6 +153,7 @@
     private static final int MSG_SET_FUNCTIONS_TIMEOUT = 15;
     private static final int MSG_GET_CURRENT_USB_FUNCTIONS = 16;
     private static final int MSG_FUNCTION_SWITCH_TIMEOUT = 17;
+    private static final int MSG_GADGET_HAL_REGISTERED = 18;
 
     private static final int AUDIO_MODE_SOURCE = 1;
 
@@ -1708,10 +1709,16 @@
         protected static final String CTL_STOP = "ctl.stop";
 
         /**
-         * Adb natvie daemon
+         * Adb native daemon.
          */
         protected static final String ADBD = "adbd";
 
+        /**
+         * Gadget HAL fully qualified instance name for registering for ServiceNotification.
+         */
+        protected static final String GADGET_HAL_FQ_NAME =
+                "android.hardware.usb.gadget@1.0::IUsbGadget";
+
         protected boolean mCurrentUsbFunctionsRequested;
 
         UsbHandlerHal(Looper looper, Context context, UsbDeviceManager deviceManager,
@@ -1721,8 +1728,7 @@
                 ServiceNotification serviceNotification = new ServiceNotification();
 
                 boolean ret = IServiceManager.getService()
-                        .registerForNotifications("android.hardware.usb.gadget@1.0::IUsbGadget",
-                                "", serviceNotification);
+                        .registerForNotifications(GADGET_HAL_FQ_NAME, "", serviceNotification);
                 if (!ret) {
                     Slog.e(TAG, "Failed to register usb gadget service start notification");
                     return;
@@ -1764,20 +1770,12 @@
             @Override
             public void onRegistration(String fqName, String name, boolean preexisting) {
                 Slog.i(TAG, "Usb gadget hal service started " + fqName + " " + name);
-                synchronized (mGadgetProxyLock) {
-                    try {
-                        mGadgetProxy = IUsbGadget.getService();
-                        mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
-                                USB_GADGET_HAL_DEATH_COOKIE);
-                        if (!mCurrentFunctionsApplied && !mCurrentUsbFunctionsRequested) {
-                            setEnabledFunctions(mCurrentFunctions, false);
-                        }
-                    } catch (NoSuchElementException e) {
-                        Slog.e(TAG, "Usb gadget hal not found", e);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Usb Gadget hal not responding", e);
-                    }
+                if (!fqName.equals(GADGET_HAL_FQ_NAME)) {
+                    Slog.e(TAG, "fqName does not match");
+                    return;
                 }
+
+                sendMessage(MSG_GADGET_HAL_REGISTERED, preexisting);
             }
         }
 
@@ -1815,6 +1813,23 @@
                         setEnabledFunctions(UsbManager.FUNCTION_NONE, !isAdbEnabled());
                     }
                     break;
+                case MSG_GADGET_HAL_REGISTERED:
+                    boolean preexisting = msg.arg1 == 1;
+                    synchronized (mGadgetProxyLock) {
+                        try {
+                            mGadgetProxy = IUsbGadget.getService();
+                            mGadgetProxy.linkToDeath(new UsbGadgetDeathRecipient(),
+                                    USB_GADGET_HAL_DEATH_COOKIE);
+                            if (!mCurrentFunctionsApplied && !preexisting) {
+                                setEnabledFunctions(mCurrentFunctions, false);
+                            }
+                        } catch (NoSuchElementException e) {
+                            Slog.e(TAG, "Usb gadget hal not found", e);
+                        } catch (RemoteException e) {
+                            Slog.e(TAG, "Usb Gadget hal not responding", e);
+                        }
+                    }
+                    break;
                 default:
                     super.handleMessage(msg);
             }
diff --git a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
index 0121d30..84add88 100644
--- a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
@@ -40,7 +40,6 @@
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbInterface;
 import android.hardware.usb.UsbManager;
-import android.os.Binder;
 import android.os.UserHandle;
 import android.service.usb.UsbAccessoryAttachedActivities;
 import android.service.usb.UsbDeviceAttachedActivities;
@@ -190,9 +189,8 @@
                                          @Nullable UsbAccessory accessory,
                                          boolean canBeDefault,
                                          String packageName,
-                                         PendingIntent pi) {
-        final int uid = Binder.getCallingUid();
-
+                                         PendingIntent pi,
+                                         int uid) {
         // compare uid with packageName to foil apps pretending to be someone else
         try {
             ApplicationInfo aInfo = mPackageManager.getApplicationInfo(packageName, 0);
@@ -235,7 +233,8 @@
             }
         }
 
-        requestPermissionDialog(device, null, canBeDefault(device, packageName), packageName, pi);
+        requestPermissionDialog(device, null, canBeDefault(device, packageName), packageName, pi,
+                uid);
     }
 
     public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi,
@@ -253,8 +252,8 @@
             return;
         }
 
-        requestPermissionDialog(null, accessory,
-                canBeDefault(accessory, packageName), packageName, pi);
+        requestPermissionDialog(null, accessory, canBeDefault(accessory, packageName), packageName,
+                pi, uid);
     }
 
     public void grantDevicePermission(UsbDevice device, int uid) {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index ad2501d..d6b40ae 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -42,6 +42,7 @@
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
 import android.util.Slog;
+
 import com.android.internal.logging.MetricsLogger;
 
 import java.io.FileDescriptor;
@@ -566,38 +567,34 @@
         }
     }
 
-    SoundTrigger.RecognitionEvent getGenericModelState(UUID modelId) {
+    int getGenericModelState(UUID modelId) {
         synchronized (mLock) {
             MetricsLogger.count(mContext, "sth_get_generic_model_state", 1);
             if (modelId == null || mModule == null) {
-                return null;
+                return STATUS_ERROR;
             }
             ModelData modelData = mModelDataMap.get(modelId);
             if (modelData == null || !modelData.isGenericModel()) {
                 Slog.w(TAG, "GetGenericModelState error: Invalid generic model id:" +
                         modelId);
-                return null;
+                return STATUS_ERROR;
             }
             if (!modelData.isModelLoaded()) {
                 Slog.i(TAG, "GetGenericModelState: Given generic model is not loaded:" + modelId);
-                return null;
+                return STATUS_ERROR;
             }
             if (!modelData.isModelStarted()) {
                 Slog.i(TAG, "GetGenericModelState: Given generic model is not started:" + modelId);
-                return null;
+                return STATUS_ERROR;
             }
 
-            SoundTrigger.RecognitionEvent ret = mModule.getModelState(modelData.getHandle());
-            if (ret == null) {
-                Slog.w(TAG, "GetGenericModelState() call failed");
-            }
-            return ret;
+            return mModule.getModelState(modelData.getHandle());
         }
     }
 
-    SoundTrigger.RecognitionEvent getKeyphraseModelState(UUID modelId) {
+    int getKeyphraseModelState(UUID modelId) {
         Slog.w(TAG, "GetKeyphraseModelState error: Not implemented");
-        return null;
+        return STATUS_ERROR;
     }
 
     //---- SoundTrigger.StatusListener methods
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index d57fcb1..8c82cc8 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -436,9 +436,10 @@
         }
 
         @Override
-        public SoundTrigger.RecognitionEvent getModelState(ParcelUuid soundModelId) {
+        public int getModelState(ParcelUuid soundModelId) {
             enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
-            if (!isInitialized()) return null;
+            int ret = STATUS_ERROR;
+            if (!isInitialized()) return ret;
             if (DEBUG) {
                 Slog.i(TAG, "getModelState(): id = " + soundModelId);
             }
@@ -447,9 +448,8 @@
                 SoundModel soundModel = mLoadedModels.get(soundModelId.getUuid());
                 if (soundModel == null) {
                     Slog.e(TAG, soundModelId + " is not loaded");
-                    return null;
+                    return ret;
                 }
-                SoundTrigger.RecognitionEvent ret = null;
                 switch (soundModel.type) {
                     case SoundModel.TYPE_KEYPHRASE:
                         ret = mSoundTriggerHelper.getKeyphraseModelState(soundModel.uuid);
@@ -461,9 +461,6 @@
                         Slog.e(TAG, "Unknown model type");
                         break;
                 }
-                if (ret == null) {
-                    Slog.e(TAG, "Failed to get model state");
-                }
 
                 return ret;
             }
@@ -942,7 +939,11 @@
             runOrAddOperation(new Operation(
                     // always execute:
                     () -> {
-                        if (!mRecognitionConfig.allowMultipleTriggers) {
+                        // Don't remove the callback if multiple triggers are allowed or
+                        // if this event was triggered by a getModelState request
+                        if (!mRecognitionConfig.allowMultipleTriggers
+                                && event.status
+                                    != SoundTrigger.RECOGNITION_STATUS_GET_STATE_RESPONSE) {
                             // Unregister this remoteService once op is done
                             synchronized (mCallbacksLock) {
                                 mCallbacks.remove(mPuuid.getUuid());
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index 3681529..0c40a6b 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -16,10 +16,15 @@
 
 cc_defaults {
     name: "viewcompiler_defaults",
+    header_libs: [
+        "libbase_headers",
+    ],
     shared_libs: [
+        "libbase",
         "libdexfile",
         "slicer",
     ],
+    cppflags: ["-std=c++17"],
 }
 
 cc_library_host_static {
@@ -30,9 +35,6 @@
         "java_lang_builder.cc",
         "util.cc",
     ],
-    static_libs: [
-        "libbase",
-    ],
 }
 
 cc_binary_host {
@@ -42,7 +44,6 @@
         "main.cc",
     ],
     static_libs: [
-        "libbase",
         "libtinyxml2",
         "libgflags",
         "libviewcompiler",
@@ -59,4 +60,24 @@
     static_libs: [
         "libviewcompiler",
     ],
+    test_suites: ["general-tests"],
+}
+
+cc_binary_host {
+    name: "dex_testcase_generator",
+    defaults: ["viewcompiler_defaults"],
+    srcs: ["dex_testcase_generator.cc"],
+    static_libs: [
+        "libviewcompiler",
+    ],
+}
+
+genrule {
+    name: "generate_dex_testcases",
+    tools: [":dex_testcase_generator"],
+    cmd: "$(location :dex_testcase_generator) $(genDir)",
+    out: [
+        "simple.dex",
+        "trivial.dex",
+    ],
 }
diff --git a/startop/view_compiler/README.md b/startop/view_compiler/README.md
index 5659501..f8da02b 100644
--- a/startop/view_compiler/README.md
+++ b/startop/view_compiler/README.md
@@ -23,3 +23,31 @@
   application.
 * This only works for apps that do not use a custom layout inflater.
 * Other limitations yet to be discovered.
+
+## DexBuilder Tests
+
+The DexBuilder has several low-level end to end tests to verify generated DEX
+code validates, runs, and has the correct behavior. There are, unfortunately, a
+number of pieces that must be added to generate new tests. Here are the
+components:
+
+* `dex_testcase_generator` - Written in C++ using `DexBuilder`. This runs as a
+  build step produce the DEX files that will be tested on device. See the
+  `genrule` named `generate_dex_testcases` in `Android.bp`. These files are then
+  copied over to the device by TradeFed when running tests.
+* `DexBuilderTest` - This is a Java Language test harness that loads the
+  generated DEX files and exercises methods in the file.
+
+To add a new DEX file test, follow these steps:
+1. Modify `dex_testcase_generator` to produce the DEX file.
+2. Add the filename to the `out` list of the `generate_dex_testcases` rule in
+   `Android.bp`.
+3. Add a new `push` option to `AndroidTest.xml` to copy the DEX file to the
+   device.
+4. Modify `DexBuilderTest.java` to load and exercise the new test.
+
+In each case, you should be able to cargo-cult the existing test cases.
+
+In general, you can probably get by without adding a new generated DEX file, and
+instead add more methods to the files that are already generated. In this case,
+you can skip all of steps 2 and 3 above, and simplify steps 1 and 4.
diff --git a/startop/view_compiler/TEST_MAPPING b/startop/view_compiler/TEST_MAPPING
index cc4b17a..5d675b7 100644
--- a/startop/view_compiler/TEST_MAPPING
+++ b/startop/view_compiler/TEST_MAPPING
@@ -1,7 +1,7 @@
 {
   "presubmit": [
     {
-      "name": "view-compiler-tests"
+      "name": "dex-builder-test"
     }
   ]
 }
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index 7a9f41f..906d64c 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -17,19 +17,20 @@
 #include "dex_builder.h"
 
 #include "dex/descriptors_names.h"
-#include "dex/dex_instruction.h"
 
 #include <fstream>
 #include <memory>
 
+#define DCHECK_NOT_NULL(p) DCHECK((p) != nullptr)
+
 namespace startop {
 namespace dex {
 
 using std::shared_ptr;
 using std::string;
 
-using art::Instruction;
 using ::dex::kAccPublic;
+using Op = Instruction::Op;
 
 const TypeDescriptor TypeDescriptor::Int() { return TypeDescriptor{"I"}; };
 const TypeDescriptor TypeDescriptor::Void() { return TypeDescriptor{"V"}; };
@@ -43,6 +44,35 @@
 
 }  // namespace
 
+std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode) {
+  switch (opcode) {
+    case Instruction::Op::kReturn:
+      out << "kReturn";
+      return out;
+    case Instruction::Op::kReturnObject:
+      out << "kReturnObject";
+      return out;
+    case Instruction::Op::kMove:
+      out << "kMove";
+      return out;
+    case Instruction::Op::kInvokeVirtual:
+      out << "kInvokeVirtual";
+      return out;
+    case Instruction::Op::kInvokeDirect:
+      out << "kInvokeDirect";
+      return out;
+    case Instruction::Op::kBindLabel:
+      out << "kBindLabel";
+      return out;
+    case Instruction::Op::kBranchEqz:
+      out << "kBranchEqz";
+      return out;
+    case Instruction::Op::kNew:
+      out << "kNew";
+      return out;
+  }
+}
+
 void* TrackingAllocator::Allocate(size_t size) {
   std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(size);
   void* raw_buffer = buffer.get();
@@ -56,7 +86,7 @@
 //
 // package dextest;
 // public class DexTest {
-//     public static int foo() { return 5; }
+//     public static int foo(String s) { return s.length(); }
 // }
 void WriteTestDexFile(const string& filename) {
   DexBuilder dex_file;
@@ -64,11 +94,17 @@
   ClassBuilder cbuilder{dex_file.MakeClass("dextest.DexTest")};
   cbuilder.set_source_file("dextest.java");
 
-  MethodBuilder method{cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Int()})};
+  TypeDescriptor string_type = TypeDescriptor::FromClassname("java.lang.String");
 
-  MethodBuilder::Register r = method.MakeRegister();
-  method.BuildConst4(r, 5);
-  method.BuildReturn(r);
+  MethodBuilder method{cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Int(), string_type})};
+
+  Value result = method.MakeRegister();
+
+  MethodDeclData string_length =
+      dex_file.GetOrDeclareMethod(string_type, "length", Prototype{TypeDescriptor::Int()});
+
+  method.AddInstruction(Instruction::InvokeVirtual(string_length.id, result, Value::Parameter(0)));
+  method.BuildReturn(result);
 
   method.Encode();
 
@@ -78,6 +114,10 @@
   out_file.write(image.ptr<const char>(), image.size());
 }
 
+TypeDescriptor TypeDescriptor::FromClassname(const std::string& name) {
+  return TypeDescriptor{art::DotToDescriptor(name.c_str())};
+}
+
 DexBuilder::DexBuilder() : dex_file_{std::make_shared<ir::DexFile>()} {
   dex_file_->magic = slicer::MemView{kDexFileMagic, sizeof(kDexFileMagic)};
 }
@@ -106,6 +146,9 @@
     entry = Alloc<ir::String>();
     // +1 for null terminator
     entry->data = slicer::MemView{buffer.get(), header_length + string.size() + 1};
+    ::dex::u4 const new_index = dex_file_->strings_indexes.AllocateIndex();
+    dex_file_->strings_map[new_index] = entry;
+    entry->orig_index = new_index;
     string_data_.push_back(std::move(buffer));
   }
   return entry;
@@ -119,10 +162,9 @@
   class_def->type = type_def;
   class_def->super_class = GetOrAddType(art::DotToDescriptor("java.lang.Object"));
   class_def->access_flags = kAccPublic;
-  return ClassBuilder{this, class_def};
+  return ClassBuilder{this, name, class_def};
 }
 
-// TODO(eholk): we probably want GetOrAddString() also
 ir::Type* DexBuilder::GetOrAddType(const std::string& descriptor) {
   if (types_by_descriptor_.find(descriptor) != types_by_descriptor_.end()) {
     return types_by_descriptor_[descriptor];
@@ -131,6 +173,8 @@
   ir::Type* type = Alloc<ir::Type>();
   type->descriptor = GetOrAddString(descriptor);
   types_by_descriptor_[descriptor] = type;
+  type->orig_index = dex_file_->types_indexes.AllocateIndex();
+  dex_file_->types_map[type->orig_index] = type;
   return type;
 }
 
@@ -158,16 +202,11 @@
   return shorty;
 }
 
-ClassBuilder::ClassBuilder(DexBuilder* parent, ir::Class* class_def)
-    : parent_(parent), class_(class_def) {}
+ClassBuilder::ClassBuilder(DexBuilder* parent, const std::string& name, ir::Class* class_def)
+    : parent_(parent), type_descriptor_{TypeDescriptor::FromClassname(name)}, class_(class_def) {}
 
 MethodBuilder ClassBuilder::CreateMethod(const std::string& name, Prototype prototype) {
-  ir::String* dex_name{parent_->GetOrAddString(name)};
-
-  auto* decl = parent_->Alloc<ir::MethodDecl>();
-  decl->name = dex_name;
-  decl->parent = class_->type;
-  decl->prototype = prototype.Encode(parent_);
+  ir::MethodDecl* decl = parent_->GetOrDeclareMethod(type_descriptor_, name, prototype).decl;
 
   return MethodBuilder{parent_, class_, decl};
 }
@@ -187,9 +226,15 @@
   method->access_flags = kAccPublic | ::dex::kAccStatic;
 
   auto* code = dex_->Alloc<ir::Code>();
-  code->registers = num_registers_;
-  // TODO: support ins and outs
+  DCHECK_NOT_NULL(decl_->prototype);
+  size_t const num_args =
+      decl_->prototype->param_types != nullptr ? decl_->prototype->param_types->types.size() : 0;
+  code->registers = num_registers_ + num_args;
+  code->ins_count = num_args;
+  EncodeInstructions();
   code->instructions = slicer::ArrayView<const ::dex::u2>(buffer_.data(), buffer_.size());
+  size_t const return_count = decl_->prototype->return_type == dex_->GetOrAddType("V") ? 0 : 1;
+  code->outs_count = std::max(return_count, max_args_);
   method->code = code;
 
   class_->direct_methods.push_back(method);
@@ -197,17 +242,225 @@
   return method;
 }
 
-MethodBuilder::Register MethodBuilder::MakeRegister() { return num_registers_++; }
+Value MethodBuilder::MakeRegister() { return Value::Local(num_registers_++); }
 
-void MethodBuilder::BuildReturn() { buffer_.push_back(Instruction::RETURN_VOID); }
+Value MethodBuilder::MakeLabel() {
+  labels_.push_back({});
+  return Value::Label(labels_.size() - 1);
+}
 
-void MethodBuilder::BuildReturn(Register src) { buffer_.push_back(Instruction::RETURN | src << 8); }
+void MethodBuilder::AddInstruction(Instruction instruction) {
+  instructions_.push_back(instruction);
+}
 
-void MethodBuilder::BuildConst4(Register target, int value) {
+void MethodBuilder::BuildReturn() { AddInstruction(Instruction::OpNoArgs(Op::kReturn)); }
+
+void MethodBuilder::BuildReturn(Value src, bool is_object) {
+  AddInstruction(Instruction::OpWithArgs(
+      is_object ? Op::kReturnObject : Op::kReturn, /*destination=*/{}, src));
+}
+
+void MethodBuilder::BuildConst4(Value target, int value) {
   DCHECK_LT(value, 16);
-  // TODO: support more registers
-  DCHECK_LT(target, 16);
-  buffer_.push_back(Instruction::CONST_4 | (value << 12) | (target << 8));
+  AddInstruction(Instruction::OpWithArgs(Op::kMove, target, Value::Immediate(value)));
+}
+
+void MethodBuilder::BuildConstString(Value target, const std::string& value) {
+  const ir::String* const dex_string = dex_->GetOrAddString(value);
+  AddInstruction(Instruction::OpWithArgs(Op::kMove, target, Value::String(dex_string->orig_index)));
+}
+
+void MethodBuilder::EncodeInstructions() {
+  buffer_.clear();
+  for (const auto& instruction : instructions_) {
+    EncodeInstruction(instruction);
+  }
+}
+
+void MethodBuilder::EncodeInstruction(const Instruction& instruction) {
+  switch (instruction.opcode()) {
+    case Instruction::Op::kReturn:
+      return EncodeReturn(instruction, ::art::Instruction::RETURN);
+    case Instruction::Op::kReturnObject:
+      return EncodeReturn(instruction, ::art::Instruction::RETURN_OBJECT);
+    case Instruction::Op::kMove:
+      return EncodeMove(instruction);
+    case Instruction::Op::kInvokeVirtual:
+      return EncodeInvoke(instruction, art::Instruction::INVOKE_VIRTUAL);
+    case Instruction::Op::kInvokeDirect:
+      return EncodeInvoke(instruction, art::Instruction::INVOKE_DIRECT);
+    case Instruction::Op::kBindLabel:
+      return BindLabel(instruction.args()[0]);
+    case Instruction::Op::kBranchEqz:
+      return EncodeBranch(art::Instruction::IF_EQZ, instruction);
+    case Instruction::Op::kNew:
+      return EncodeNew(instruction);
+  }
+}
+
+void MethodBuilder::EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode) {
+  DCHECK(!instruction.dest().has_value());
+  if (instruction.args().size() == 0) {
+    Encode10x(art::Instruction::RETURN_VOID);
+  } else {
+    DCHECK_EQ(1, instruction.args().size());
+    size_t source = RegisterValue(instruction.args()[0]);
+    Encode11x(opcode, source);
+  }
+}
+
+void MethodBuilder::EncodeMove(const Instruction& instruction) {
+  DCHECK_EQ(Instruction::Op::kMove, instruction.opcode());
+  DCHECK(instruction.dest().has_value());
+  DCHECK(instruction.dest()->is_register() || instruction.dest()->is_parameter());
+  DCHECK_EQ(1, instruction.args().size());
+
+  const Value& source = instruction.args()[0];
+
+  if (source.is_immediate()) {
+    // TODO: support more registers
+    DCHECK_LT(RegisterValue(*instruction.dest()), 16);
+    Encode11n(art::Instruction::CONST_4, RegisterValue(*instruction.dest()), source.value());
+  } else if (source.is_string()) {
+    constexpr size_t kMaxRegisters = 256;
+    DCHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters);
+    DCHECK_LT(source.value(), 65536);  // make sure we don't need a jumbo string
+    Encode21c(::art::Instruction::CONST_STRING, RegisterValue(*instruction.dest()), source.value());
+  } else {
+    UNIMPLEMENTED(FATAL);
+  }
+}
+
+void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode) {
+  constexpr size_t kMaxArgs = 5;
+
+  CHECK_LE(instruction.args().size(), kMaxArgs);
+
+  uint8_t arguments[kMaxArgs]{};
+  for (size_t i = 0; i < instruction.args().size(); ++i) {
+    CHECK(instruction.args()[i].is_variable());
+    arguments[i] = RegisterValue(instruction.args()[i]);
+  }
+
+  Encode35c(opcode,
+            instruction.args().size(),
+            instruction.method_id(),
+            arguments[0],
+            arguments[1],
+            arguments[2],
+            arguments[3],
+            arguments[4]);
+
+  // If there is a return value, add a move-result instruction
+  if (instruction.dest().has_value()) {
+    Encode11x(art::Instruction::MOVE_RESULT, RegisterValue(*instruction.dest()));
+  }
+
+  max_args_ = std::max(max_args_, instruction.args().size());
+}
+
+// Encodes a conditional branch that tests a single argument.
+void MethodBuilder::EncodeBranch(art::Instruction::Code op, const Instruction& instruction) {
+  const auto& args = instruction.args();
+  const auto& test_value = args[0];
+  const auto& branch_target = args[1];
+  CHECK_EQ(2, args.size());
+  CHECK(test_value.is_variable());
+  CHECK(branch_target.is_label());
+
+  size_t instruction_offset = buffer_.size();
+  size_t field_offset = buffer_.size() + 1;
+  Encode21c(
+      op, RegisterValue(test_value), LabelValue(branch_target, instruction_offset, field_offset));
+}
+
+void MethodBuilder::EncodeNew(const Instruction& instruction) {
+  DCHECK_EQ(Instruction::Op::kNew, instruction.opcode());
+  DCHECK(instruction.dest().has_value());
+  DCHECK(instruction.dest()->is_variable());
+  DCHECK_EQ(1, instruction.args().size());
+
+  const Value& type = instruction.args()[0];
+  DCHECK_LT(RegisterValue(*instruction.dest()), 256);
+  DCHECK(type.is_type());
+  Encode21c(::art::Instruction::NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value());
+}
+
+size_t MethodBuilder::RegisterValue(const Value& value) const {
+  if (value.is_register()) {
+    return value.value();
+  } else if (value.is_parameter()) {
+    return value.value() + num_registers_;
+  }
+  DCHECK(false && "Must be either a parameter or a register");
+  return 0;
+}
+
+void MethodBuilder::BindLabel(const Value& label_id) {
+  CHECK(label_id.is_label());
+
+  LabelData& label = labels_[label_id.value()];
+  CHECK(!label.bound_address.has_value());
+
+  label.bound_address = buffer_.size();
+
+  // patch any forward references to this label.
+  for (const auto& ref : label.references) {
+    buffer_[ref.field_offset] = *label.bound_address - ref.instruction_offset;
+  }
+  // No point keeping these around anymore.
+  label.references.clear();
+}
+
+::dex::u2 MethodBuilder::LabelValue(const Value& label_id, size_t instruction_offset,
+                                    size_t field_offset) {
+  CHECK(label_id.is_label());
+  LabelData& label = labels_[label_id.value()];
+
+  // Short-circuit if the label is already bound.
+  if (label.bound_address.has_value()) {
+    return *label.bound_address - instruction_offset;
+  }
+
+  // Otherwise, save a reference to where we need to back-patch later.
+  label.references.push_front(LabelReference{instruction_offset, field_offset});
+  return 0;
+}
+
+const MethodDeclData& DexBuilder::GetOrDeclareMethod(TypeDescriptor type, const std::string& name,
+                                                     Prototype prototype) {
+  MethodDeclData& entry = method_id_map_[{type, name, prototype}];
+
+  if (entry.decl == nullptr) {
+    // This method has not already been declared, so declare it.
+    ir::MethodDecl* decl = dex_file_->Alloc<ir::MethodDecl>();
+    // The method id is the last added method.
+    size_t id = dex_file_->methods.size() - 1;
+
+    ir::String* dex_name{GetOrAddString(name)};
+    decl->name = dex_name;
+    decl->parent = GetOrAddType(type.descriptor());
+    decl->prototype = GetOrEncodeProto(prototype);
+
+    // update the index -> ir node map (see tools/dexter/slicer/dex_ir_builder.cc)
+    auto new_index = dex_file_->methods_indexes.AllocateIndex();
+    auto& ir_node = dex_file_->methods_map[new_index];
+    SLICER_CHECK(ir_node == nullptr);
+    ir_node = decl;
+    decl->orig_index = new_index;
+
+    entry = {id, decl};
+  }
+
+  return entry;
+}
+
+ir::Proto* DexBuilder::GetOrEncodeProto(Prototype prototype) {
+  ir::Proto*& ir_proto = proto_map_[prototype];
+  if (ir_proto == nullptr) {
+    ir_proto = prototype.Encode(this);
+  }
+  return ir_proto;
 }
 
 }  // namespace dex
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index d280abc..adf82bf 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -16,10 +16,14 @@
 #ifndef DEX_BUILDER_H_
 #define DEX_BUILDER_H_
 
+#include <forward_list>
 #include <map>
+#include <optional>
 #include <string>
+#include <unordered_map>
 #include <vector>
 
+#include "dex/dex_instruction.h"
 #include "slicer/dex_ir.h"
 #include "slicer/writer.h"
 
@@ -45,7 +49,7 @@
   virtual void Free(void* ptr);
 
  private:
-  std::map<void*, std::unique_ptr<uint8_t[]>> allocations_;
+  std::unordered_map<void*, std::unique_ptr<uint8_t[]>> allocations_;
 };
 
 // Represents a DEX type descriptor.
@@ -57,11 +61,17 @@
   static const TypeDescriptor Int();
   static const TypeDescriptor Void();
 
+  // Creates a type descriptor from a fully-qualified class name. For example, it turns the class
+  // name java.lang.Object into the descriptor Ljava/lang/Object.
+  static TypeDescriptor FromClassname(const std::string& name);
+
   // Return the full descriptor, such as I or Ljava/lang/Object
   const std::string& descriptor() const { return descriptor_; }
   // Return the shorty descriptor, such as I or L
   std::string short_descriptor() const { return descriptor().substr(0, 1); }
 
+  bool operator<(const TypeDescriptor& rhs) const { return descriptor_ < rhs.descriptor_; }
+
  private:
   TypeDescriptor(std::string descriptor) : descriptor_{descriptor} {}
 
@@ -82,11 +92,126 @@
   // Get the shorty descriptor, such as VII for (Int, Int) -> Void
   std::string Shorty() const;
 
+  bool operator<(const Prototype& rhs) const {
+    return std::make_tuple(return_type_, param_types_) <
+           std::make_tuple(rhs.return_type_, rhs.param_types_);
+  }
+
  private:
   const TypeDescriptor return_type_;
   const std::vector<TypeDescriptor> param_types_;
 };
 
+// Represents a DEX register or constant. We separate regular registers and parameters
+// because we will not know the real parameter id until after all instructions
+// have been generated.
+class Value {
+ public:
+  static constexpr Value Local(size_t id) { return Value{id, Kind::kLocalRegister}; }
+  static constexpr Value Parameter(size_t id) { return Value{id, Kind::kParameter}; }
+  static constexpr Value Immediate(size_t value) { return Value{value, Kind::kImmediate}; }
+  static constexpr Value String(size_t value) { return Value{value, Kind::kString}; }
+  static constexpr Value Label(size_t id) { return Value{id, Kind::kLabel}; }
+  static constexpr Value Type(size_t id) { return Value{id, Kind::kType}; }
+
+  bool is_register() const { return kind_ == Kind::kLocalRegister; }
+  bool is_parameter() const { return kind_ == Kind::kParameter; }
+  bool is_variable() const { return is_register() || is_parameter(); }
+  bool is_immediate() const { return kind_ == Kind::kImmediate; }
+  bool is_string() const { return kind_ == Kind::kString; }
+  bool is_label() const { return kind_ == Kind::kLabel; }
+  bool is_type() const { return kind_ == Kind::kType; }
+
+  size_t value() const { return value_; }
+
+ private:
+  enum class Kind { kLocalRegister, kParameter, kImmediate, kString, kLabel, kType };
+
+  const size_t value_;
+  const Kind kind_;
+
+  constexpr Value(size_t value, Kind kind) : value_{value}, kind_{kind} {}
+};
+
+// A virtual instruction. We convert these to real instructions in MethodBuilder::Encode.
+// Virtual instructions are needed to keep track of information that is not known until all of the
+// code is generated. This information includes things like how many local registers are created and
+// branch target locations.
+class Instruction {
+ public:
+  // The operation performed by this instruction. These are virtual instructions that do not
+  // correspond exactly to DEX instructions.
+  enum class Op {
+    kReturn,
+    kReturnObject,
+    kMove,
+    kInvokeVirtual,
+    kInvokeDirect,
+    kBindLabel,
+    kBranchEqz,
+    kNew
+  };
+
+  ////////////////////////
+  // Named Constructors //
+  ////////////////////////
+
+  // For instructions with no return value and no arguments.
+  static inline Instruction OpNoArgs(Op opcode) {
+    return Instruction{opcode, /*method_id*/ 0, /*dest*/ {}};
+  }
+  // For most instructions, which take some number of arguments and have an optional return value.
+  template <typename... T>
+  static inline Instruction OpWithArgs(Op opcode, std::optional<const Value> dest, T... args) {
+    return Instruction{opcode, /*method_id*/ 0, dest, args...};
+  }
+  // For method calls.
+  template <typename... T>
+  static inline Instruction InvokeVirtual(size_t method_id, std::optional<const Value> dest,
+                                          Value this_arg, T... args) {
+    return Instruction{Op::kInvokeVirtual, method_id, dest, this_arg, args...};
+  }
+  // For direct calls (basically, constructors).
+  template <typename... T>
+  static inline Instruction InvokeDirect(size_t method_id, std::optional<const Value> dest,
+                                         Value this_arg, T... args) {
+    return Instruction{Op::kInvokeDirect, method_id, dest, this_arg, args...};
+  }
+
+  ///////////////
+  // Accessors //
+  ///////////////
+
+  Op opcode() const { return opcode_; }
+  size_t method_id() const { return method_id_; }
+  const std::optional<const Value>& dest() const { return dest_; }
+  const std::vector<const Value>& args() const { return args_; }
+
+ private:
+  inline Instruction(Op opcode, size_t method_id, std::optional<const Value> dest)
+      : opcode_{opcode}, method_id_{method_id}, dest_{dest}, args_{} {}
+
+  template <typename... T>
+  inline constexpr Instruction(Op opcode, size_t method_id, std::optional<const Value> dest,
+                               T... args)
+      : opcode_{opcode}, method_id_{method_id}, dest_{dest}, args_{args...} {}
+
+  const Op opcode_;
+  // The index of the method to invoke, for kInvokeVirtual and similar opcodes.
+  const size_t method_id_{0};
+  const std::optional<const Value> dest_;
+  const std::vector<const Value> args_;
+};
+
+// Needed for CHECK_EQ, DCHECK_EQ, etc.
+std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode);
+
+// Keeps track of information needed to manipulate or call a method.
+struct MethodDeclData {
+  size_t id;
+  ir::MethodDecl* decl;
+};
+
 // Tools to help build methods and their bodies.
 class MethodBuilder {
  public:
@@ -95,42 +220,138 @@
   // Encode the method into DEX format.
   ir::EncodedMethod* Encode();
 
-  // Registers are just represented by their number.
-  using Register = size_t;
-
   // Create a new register to be used to storing values. Note that these are not SSA registers, like
   // might be expected in similar code generators. This does no liveness tracking or anything, so
   // it's up to the caller to reuse registers as appropriate.
-  Register MakeRegister();
+  Value MakeRegister();
+
+  Value MakeLabel();
 
   /////////////////////////////////
   // Instruction builder methods //
   /////////////////////////////////
 
+  void AddInstruction(Instruction instruction);
+
   // return-void
   void BuildReturn();
-  void BuildReturn(Register src);
+  void BuildReturn(Value src, bool is_object = false);
   // const/4
-  void BuildConst4(Register target, int value);
+  void BuildConst4(Value target, int value);
+  void BuildConstString(Value target, const std::string& value);
+  template <typename... T>
+  void BuildNew(Value target, TypeDescriptor type, Prototype constructor, T... args);
 
   // TODO: add builders for more instructions
 
  private:
+  void EncodeInstructions();
+  void EncodeInstruction(const Instruction& instruction);
+
+  // Encodes a return instruction. For instructions with no return value, the opcode field is
+  // ignored. Otherwise, this specifies which return instruction will be used (return,
+  // return-object, etc.)
+  void EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode);
+
+  void EncodeMove(const Instruction& instruction);
+  void EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode);
+  void EncodeBranch(art::Instruction::Code op, const Instruction& instruction);
+  void EncodeNew(const Instruction& instruction);
+
+  // Low-level instruction format encoding. See
+  // https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of
+  // formats.
+
+  inline void Encode10x(art::Instruction::Code opcode) {
+    // 00|op
+    buffer_.push_back(opcode);
+  }
+
+  inline void Encode11x(art::Instruction::Code opcode, uint8_t a) {
+    // aa|op
+    buffer_.push_back((a << 8) | opcode);
+  }
+
+  inline void Encode11n(art::Instruction::Code opcode, uint8_t a, int8_t b) {
+    // b|a|op
+
+    // Make sure the fields are in bounds (4 bits for a, 4 bits for b).
+    CHECK_LT(a, 16);
+    CHECK_LE(-8, b);
+    CHECK_LT(b, 8);
+
+    buffer_.push_back(((b & 0xf) << 12) | (a << 8) | opcode);
+  }
+
+  inline void Encode21c(art::Instruction::Code opcode, uint8_t a, uint16_t b) {
+    // aa|op|bbbb
+    buffer_.push_back((a << 8) | opcode);
+    buffer_.push_back(b);
+  }
+
+  inline void Encode35c(art::Instruction::Code opcode, size_t a, uint16_t b, uint8_t c, uint8_t d,
+                        uint8_t e, uint8_t f, uint8_t g) {
+    // a|g|op|bbbb|f|e|d|c
+
+    CHECK_LE(a, 5);
+    CHECK_LT(c, 16);
+    CHECK_LT(d, 16);
+    CHECK_LT(e, 16);
+    CHECK_LT(f, 16);
+    CHECK_LT(g, 16);
+    buffer_.push_back((a << 12) | (g << 8) | opcode);
+    buffer_.push_back(b);
+    buffer_.push_back((f << 12) | (e << 8) | (d << 4) | c);
+  }
+
+  // Converts a register or parameter to its DEX register number.
+  size_t RegisterValue(const Value& value) const;
+
+  // Sets a label's address to the current position in the instruction buffer. If there are any
+  // forward references to the label, this function will back-patch them.
+  void BindLabel(const Value& label);
+
+  // Returns the offset of the label relative to the given instruction offset. If the label is not
+  // bound, a reference will be saved and it will automatically be patched when the label is bound.
+  ::dex::u2 LabelValue(const Value& label, size_t instruction_offset, size_t field_offset);
+
   DexBuilder* dex_;
   ir::Class* class_;
   ir::MethodDecl* decl_;
 
-  // A buffer to hold instructions we are generating.
+  // A list of the instructions we will eventually encode.
+  std::vector<Instruction> instructions_;
+
+  // A buffer to hold instructions that have been encoded.
   std::vector<::dex::u2> buffer_;
 
   // How many registers we've allocated
-  size_t num_registers_;
+  size_t num_registers_{0};
+
+  // Stores information needed to back-patch a label once it is bound. We need to know the start of
+  // the instruction that refers to the label, and the offset to where the actual label value should
+  // go.
+  struct LabelReference {
+    size_t instruction_offset;
+    size_t field_offset;
+  };
+
+  struct LabelData {
+    std::optional<size_t> bound_address;
+    std::forward_list<LabelReference> references;
+  };
+
+  std::vector<LabelData> labels_;
+
+  // During encoding, keep track of the largest number of arguments needed, so we can use it for our
+  // outs count
+  size_t max_args_{0};
 };
 
 // A helper to build class definitions.
 class ClassBuilder {
  public:
-  ClassBuilder(DexBuilder* parent, ir::Class* class_def);
+  ClassBuilder(DexBuilder* parent, const std::string& name, ir::Class* class_def);
 
   void set_source_file(const std::string& source);
 
@@ -139,8 +360,9 @@
   MethodBuilder CreateMethod(const std::string& name, Prototype prototype);
 
  private:
-  DexBuilder* parent_;
-  ir::Class* class_;
+  DexBuilder* const parent_;
+  const TypeDescriptor type_descriptor_;
+  ir::Class* const class_;
 };
 
 // Builds Dex files from scratch.
@@ -163,10 +385,19 @@
   ClassBuilder MakeClass(const std::string& name);
 
   // Add a type for the given descriptor, or return the existing one if it already exists.
-  // See the TypeDescriptor class for help generating these.
+  // See the TypeDescriptor class for help generating these. GetOrAddType can be used to declare
+  // imported classes.
   ir::Type* GetOrAddType(const std::string& descriptor);
 
+  // Returns the method id for the method, creating it if it has not been created yet.
+  const MethodDeclData& GetOrDeclareMethod(TypeDescriptor type, const std::string& name,
+                                           Prototype prototype);
+
  private:
+  // Looks up the ir::Proto* corresponding to this given prototype, or creates one if it does not
+  // exist.
+  ir::Proto* GetOrEncodeProto(Prototype prototype);
+
   std::shared_ptr<ir::DexFile> dex_file_;
 
   // allocator_ is needed to be able to encode the image.
@@ -177,10 +408,40 @@
   std::vector<std::unique_ptr<uint8_t[]>> string_data_;
 
   // Keep track of what types we've defined so we can look them up later.
-  std::map<std::string, ir::Type*> types_by_descriptor_;
+  std::unordered_map<std::string, ir::Type*> types_by_descriptor_;
+
+  struct MethodDescriptor {
+    TypeDescriptor type;
+    std::string name;
+    Prototype prototype;
+
+    inline bool operator<(const MethodDescriptor& rhs) const {
+      return std::make_tuple(type, name, prototype) <
+             std::make_tuple(rhs.type, rhs.name, rhs.prototype);
+    }
+  };
+
+  // Maps method declarations to their method index. This is needed to encode references to them.
+  // When we go to actually write the DEX file, slicer will re-assign these after correctly sorting
+  // the methods list.
+  std::map<MethodDescriptor, MethodDeclData> method_id_map_;
 
   // Keep track of what strings we've defined so we can look them up later.
-  std::map<std::string, ir::String*> strings_;
+  std::unordered_map<std::string, ir::String*> strings_;
+
+  // Keep track of already-encoded protos.
+  std::map<Prototype, ir::Proto*> proto_map_;
+};
+
+template <typename... T>
+void MethodBuilder::BuildNew(Value target, TypeDescriptor type, Prototype constructor, T... args) {
+  MethodDeclData constructor_data{dex_->GetOrDeclareMethod(type, "<init>", constructor)};
+  // allocate the object
+  ir::Type* type_def = dex_->GetOrAddType(type.descriptor());
+  AddInstruction(
+      Instruction::OpWithArgs(Instruction::Op::kNew, target, Value::Type(type_def->orig_index)));
+  // call the constructor
+  AddInstruction(Instruction::InvokeDirect(constructor_data.id, /*dest=*/{}, target, args...));
 };
 
 }  // namespace dex
diff --git a/startop/view_compiler/dex_builder_test.cc b/startop/view_compiler/dex_builder_test.cc
index 0d8b854..61c86b4 100644
--- a/startop/view_compiler/dex_builder_test.cc
+++ b/startop/view_compiler/dex_builder_test.cc
@@ -40,6 +40,12 @@
   return loaded_dex_file != nullptr;
 }
 
+// Write out and verify a DEX file that corresponds to:
+//
+// package dextest;
+// public class DexTest {
+//     public static void foo() {}
+// }
 TEST(DexBuilderTest, VerifyDexWithClassMethod) {
   DexBuilder dex_file;
 
@@ -67,6 +73,12 @@
   EXPECT_FALSE(EncodeAndVerify(&dex_file));
 }
 
+// Write out and verify a DEX file that corresponds to:
+//
+// package dextest;
+// public class DexTest {
+//     public static int foo() { return 5; }
+// }
 TEST(DexBuilderTest, VerifyDexReturn5) {
   DexBuilder dex_file;
 
@@ -80,3 +92,51 @@
 
   EXPECT_TRUE(EncodeAndVerify(&dex_file));
 }
+
+// Write out and verify a DEX file that corresponds to:
+//
+// package dextest;
+// public class DexTest {
+//     public static int foo(int x) { return x; }
+// }
+TEST(DexBuilderTest, VerifyDexReturnIntParam) {
+  DexBuilder dex_file;
+
+  auto cbuilder{dex_file.MakeClass("dextest.DexTest")};
+
+  auto method{
+      cbuilder.CreateMethod("foo", Prototype{TypeDescriptor::Int(), TypeDescriptor::Int()})};
+  method.BuildReturn(Value::Parameter(0));
+  method.Encode();
+
+  EXPECT_TRUE(EncodeAndVerify(&dex_file));
+}
+
+// Write out and verify a DEX file that corresponds to:
+//
+// package dextest;
+// public class DexTest {
+//     public static int foo(String s) { return s.length(); }
+// }
+TEST(DexBuilderTest, VerifyDexCallStringLength) {
+  DexBuilder dex_file;
+
+  auto cbuilder{dex_file.MakeClass("dextest.DexTest")};
+
+  MethodBuilder method{cbuilder.CreateMethod(
+      "foo", Prototype{TypeDescriptor::Int(), TypeDescriptor::FromClassname("java.lang.String")})};
+
+  Value result = method.MakeRegister();
+
+  MethodDeclData string_length =
+      dex_file.GetOrDeclareMethod(TypeDescriptor::FromClassname("java.lang.String"),
+                                  "length",
+                                  Prototype{TypeDescriptor::Int()});
+
+  method.AddInstruction(Instruction::InvokeVirtual(string_length.id, result, Value::Parameter(0)));
+  method.BuildReturn(result);
+
+  method.Encode();
+
+  EXPECT_TRUE(EncodeAndVerify(&dex_file));
+}
diff --git a/startop/view_compiler/dex_builder_test/Android.bp b/startop/view_compiler/dex_builder_test/Android.bp
new file mode 100644
index 0000000..4449ea0
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/Android.bp
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2018 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.
+//
+
+android_test {
+    name: "dex-builder-test",
+    srcs: ["src/android/startop/test/DexBuilderTest.java"],
+    sdk_version: "current",
+    data: [":generate_dex_testcases"],
+    static_libs: [
+        "android-support-test",
+        "guava",
+    ],
+    manifest: "AndroidManifest.xml",
+    test_config: "AndroidTest.xml",
+    test_suites: ["general-tests"],
+}
diff --git a/startop/view_compiler/dex_builder_test/AndroidManifest.xml b/startop/view_compiler/dex_builder_test/AndroidManifest.xml
new file mode 100644
index 0000000..6ac5fc5
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="android.startop.test" >
+
+    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="android.startop.test"
+                     android:label="DexBuilder Tests"/>
+
+</manifest>
diff --git a/startop/view_compiler/dex_builder_test/AndroidTest.xml b/startop/view_compiler/dex_builder_test/AndroidTest.xml
new file mode 100644
index 0000000..6f90cf3
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<configuration description="Runs DexBuilder Tests.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-instrumentation" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="dex-builder-test.apk" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="cleanup" value="true" />
+        <option name="push" value="trivial.dex->/data/local/tmp/dex-builder-test/trivial.dex" />
+        <option name="push" value="simple.dex->/data/local/tmp/dex-builder-test/simple.dex" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.startop.test" />
+        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
new file mode 100644
index 0000000..e20f3a9
--- /dev/null
+++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2018 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.startop.test;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import com.google.common.io.ByteStreams;
+import dalvik.system.InMemoryDexClassLoader;
+import dalvik.system.PathClassLoader;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import org.junit.Assert;
+import org.junit.Test;
+
+// Adding tests here requires changes in several other places. See README.md in
+// the view_compiler directory for more information.
+public class DexBuilderTest {
+  static ClassLoader loadDexFile(String filename) throws Exception {
+    return new PathClassLoader("/data/local/tmp/dex-builder-test/" + filename,
+        ClassLoader.getSystemClassLoader());
+  }
+
+  public void hello() {}
+
+  @Test
+  public void loadTrivialDex() throws Exception {
+    ClassLoader loader = loadDexFile("trivial.dex");
+    loader.loadClass("android.startop.test.testcases.Trivial");
+  }
+
+  @Test
+  public void return5() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("return5");
+    Assert.assertEquals(5, method.invoke(null));
+  }
+
+  @Test
+  public void returnInteger5() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnInteger5");
+    Assert.assertEquals(5, method.invoke(null));
+  }
+
+  @Test
+  public void returnParam() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnParam", int.class);
+    Assert.assertEquals(5, method.invoke(null, 5));
+    Assert.assertEquals(42, method.invoke(null, 42));
+  }
+
+  @Test
+  public void returnStringLength() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnStringLength", String.class);
+    Assert.assertEquals(13, method.invoke(null, "Hello, World!"));
+  }
+
+  @Test
+  public void returnIfZero() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnIfZero", int.class);
+    Assert.assertEquals(5, method.invoke(null, 0));
+    Assert.assertEquals(3, method.invoke(null, 17));
+  }
+
+  @Test
+  public void backwardsBranch() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("backwardsBranch");
+    Assert.assertEquals(2, method.invoke(null));
+  }
+
+  @Test
+  public void returnNull() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnNull");
+    Assert.assertEquals(null, method.invoke(null));
+  }
+
+  @Test
+  public void makeString() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("makeString");
+    Assert.assertEquals("Hello, World!", method.invoke(null));
+  }
+
+  @Test
+  public void returnStringIfZeroAB() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnStringIfZeroAB", int.class);
+    Assert.assertEquals("a", method.invoke(null, 0));
+    Assert.assertEquals("b", method.invoke(null, 1));
+  }
+
+  @Test
+  public void returnStringIfZeroBA() throws Exception {
+    ClassLoader loader = loadDexFile("simple.dex");
+    Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+    Method method = clazz.getMethod("returnStringIfZeroBA", int.class);
+    Assert.assertEquals("b", method.invoke(null, 0));
+    Assert.assertEquals("a", method.invoke(null, 1));
+  }
+}
diff --git a/startop/view_compiler/dex_testcase_generator.cc b/startop/view_compiler/dex_testcase_generator.cc
new file mode 100644
index 0000000..e2bf43bc
--- /dev/null
+++ b/startop/view_compiler/dex_testcase_generator.cc
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2018 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 "android-base/logging.h"
+#include "dex_builder.h"
+
+#include <fstream>
+#include <string>
+
+// Adding tests here requires changes in several other places. See README.md in
+// the view_compiler directory for more information.
+
+using namespace startop::dex;
+using namespace std;
+
+void GenerateTrivialDexFile(const string& outdir) {
+  DexBuilder dex_file;
+
+  ClassBuilder cbuilder{dex_file.MakeClass("android.startop.test.testcases.Trivial")};
+  cbuilder.set_source_file("dex_testcase_generator.cc#GenerateTrivialDexFile");
+
+  slicer::MemView image{dex_file.CreateImage()};
+  std::ofstream out_file(outdir + "/trivial.dex");
+  out_file.write(image.ptr<const char>(), image.size());
+}
+
+// Generates test cases that test around 1 instruction.
+void GenerateSimpleTestCases(const string& outdir) {
+  DexBuilder dex_file;
+
+  ClassBuilder cbuilder{dex_file.MakeClass("android.startop.test.testcases.SimpleTests")};
+  cbuilder.set_source_file("dex_testcase_generator.cc#GenerateSimpleTestCases");
+
+  // int return5() { return 5; }
+  auto return5{cbuilder.CreateMethod("return5", Prototype{TypeDescriptor::Int()})};
+  {
+    Value r{return5.MakeRegister()};
+    return5.BuildConst4(r, 5);
+    return5.BuildReturn(r);
+  }
+  return5.Encode();
+
+  // int return5() { return 5; }
+  auto integer_type{TypeDescriptor::FromClassname("java.lang.Integer")};
+  auto returnInteger5{cbuilder.CreateMethod("returnInteger5", Prototype{integer_type})};
+  [&](MethodBuilder& method) {
+    Value five{method.MakeRegister()};
+    method.BuildConst4(five, 5);
+    Value object{method.MakeRegister()};
+    method.BuildNew(
+        object, integer_type, Prototype{TypeDescriptor::Void(), TypeDescriptor::Int()}, five);
+    method.BuildReturn(object, /*is_object=*/true);
+  }(returnInteger5);
+  returnInteger5.Encode();
+
+  // // int returnParam(int x) { return x; }
+  auto returnParam{cbuilder.CreateMethod("returnParam",
+                                         Prototype{TypeDescriptor::Int(), TypeDescriptor::Int()})};
+  returnParam.BuildReturn(Value::Parameter(0));
+  returnParam.Encode();
+
+  // int returnStringLength(String x) { return x.length(); }
+  auto string_type{TypeDescriptor::FromClassname("java.lang.String")};
+  MethodDeclData string_length{
+      dex_file.GetOrDeclareMethod(string_type, "length", Prototype{TypeDescriptor::Int()})};
+
+  auto returnStringLength{
+      cbuilder.CreateMethod("returnStringLength", Prototype{TypeDescriptor::Int(), string_type})};
+  {
+    Value result = returnStringLength.MakeRegister();
+    returnStringLength.AddInstruction(
+        Instruction::InvokeVirtual(string_length.id, result, Value::Parameter(0)));
+    returnStringLength.BuildReturn(result);
+  }
+  returnStringLength.Encode();
+
+  // int returnIfZero(int x) { if (x == 0) { return 5; } else { return 3; } }
+  MethodBuilder returnIfZero{cbuilder.CreateMethod(
+      "returnIfZero", Prototype{TypeDescriptor::Int(), TypeDescriptor::Int()})};
+  {
+    Value resultIfZero{returnIfZero.MakeRegister()};
+    Value else_target{returnIfZero.MakeLabel()};
+    returnIfZero.AddInstruction(Instruction::OpWithArgs(
+        Instruction::Op::kBranchEqz, /*dest=*/{}, Value::Parameter(0), else_target));
+    // else branch
+    returnIfZero.BuildConst4(resultIfZero, 3);
+    returnIfZero.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturn, /*dest=*/{}, resultIfZero));
+    // then branch
+    returnIfZero.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target));
+    returnIfZero.BuildConst4(resultIfZero, 5);
+    returnIfZero.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturn, /*dest=*/{}, resultIfZero));
+  }
+  returnIfZero.Encode();
+
+  // Make sure backwards branches work too.
+  //
+  // Pseudo code for test:
+  // {
+  //   zero = 0;
+  //   result = 1;
+  //   if (zero == 0) goto B;
+  // A:
+  //   return result;
+  // B:
+  //   result = 2;
+  //   if (zero == 0) goto A;
+  //   result = 3;
+  //   return result;
+  // }
+  // If it runs correctly, this test should return 2.
+  MethodBuilder backwardsBranch{
+      cbuilder.CreateMethod("backwardsBranch", Prototype{TypeDescriptor::Int()})};
+  [](MethodBuilder& method) {
+    Value zero = method.MakeRegister();
+    Value result = method.MakeRegister();
+    Value labelA = method.MakeLabel();
+    Value labelB = method.MakeLabel();
+    method.BuildConst4(zero, 0);
+    method.BuildConst4(result, 1);
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kBranchEqz, /*dest=*/{}, zero, labelB));
+
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, labelA));
+    method.BuildReturn(result);
+
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, labelB));
+    method.BuildConst4(result, 2);
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kBranchEqz, /*dest=*/{}, zero, labelA));
+
+    method.BuildConst4(result, 3);
+    method.BuildReturn(result);
+  }(backwardsBranch);
+  backwardsBranch.Encode();
+
+  // Test that we can make a null value. Basically:
+  //
+  // public static String returnNull() { return null; }
+  MethodBuilder returnNull{cbuilder.CreateMethod("returnNull", Prototype{string_type})};
+  [](MethodBuilder& method) {
+    Value zero = method.MakeRegister();
+    method.BuildConst4(zero, 0);
+    method.BuildReturn(zero, /*is_object=*/true);
+  }(returnNull);
+  returnNull.Encode();
+
+  // Test that we can make String literals. Basically:
+  //
+  // public static String makeString() { return "Hello, World!"; }
+  MethodBuilder makeString{cbuilder.CreateMethod("makeString", Prototype{string_type})};
+  [](MethodBuilder& method) {
+    Value string = method.MakeRegister();
+    method.BuildConstString(string, "Hello, World!");
+    method.BuildReturn(string, /*is_object=*/true);
+  }(makeString);
+  makeString.Encode();
+
+  // Make sure strings are sorted correctly.
+  //
+  // int returnStringIfZeroAB(int x) { if (x == 0) { return "a"; } else { return "b"; } }
+  MethodBuilder returnStringIfZeroAB{
+      cbuilder.CreateMethod("returnStringIfZeroAB", Prototype{string_type, TypeDescriptor::Int()})};
+  [&](MethodBuilder& method) {
+    Value resultIfZero{method.MakeRegister()};
+    Value else_target{method.MakeLabel()};
+    method.AddInstruction(Instruction::OpWithArgs(
+        Instruction::Op::kBranchEqz, /*dest=*/{}, Value::Parameter(0), else_target));
+    // else branch
+    method.BuildConstString(resultIfZero, "b");
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+    // then branch
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target));
+    method.BuildConstString(resultIfZero, "a");
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+    method.Encode();
+  }(returnStringIfZeroAB);
+  // int returnStringIfZeroAB(int x) { if (x == 0) { return "b"; } else { return "a"; } }
+  MethodBuilder returnStringIfZeroBA{
+      cbuilder.CreateMethod("returnStringIfZeroBA", Prototype{string_type, TypeDescriptor::Int()})};
+  [&](MethodBuilder& method) {
+    Value resultIfZero{method.MakeRegister()};
+    Value else_target{method.MakeLabel()};
+    method.AddInstruction(Instruction::OpWithArgs(
+        Instruction::Op::kBranchEqz, /*dest=*/{}, Value::Parameter(0), else_target));
+    // else branch
+    method.BuildConstString(resultIfZero, "a");
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+    // then branch
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target));
+    method.BuildConstString(resultIfZero, "b");
+    method.AddInstruction(
+        Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+    method.Encode();
+  }(returnStringIfZeroBA);
+
+  slicer::MemView image{dex_file.CreateImage()};
+  std::ofstream out_file(outdir + "/simple.dex");
+  out_file.write(image.ptr<const char>(), image.size());
+}
+
+int main(int argc, char** argv) {
+  CHECK_EQ(argc, 2);
+
+  string outdir = argv[1];
+
+  GenerateTrivialDexFile(outdir);
+  GenerateSimpleTestCases(outdir);
+}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index b6ac91d..cef99865 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -21,6 +21,7 @@
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.ParcelFileDescriptor;
@@ -322,8 +323,11 @@
         /**
          * Call can be upgraded to a video call.
          * @hide
+         * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
+         * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call
+         * whether or not video calling is supported.
          */
-        @UnsupportedAppUsage
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
         public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
 
         /**
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index f62b170..7db6940 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SdkConstant;
 import android.app.Service;
+import android.content.ComponentName;
 import android.content.Intent;
 import android.os.Handler;
 import android.os.IBinder;
@@ -229,7 +230,8 @@
                         callDetails.getTelecomCallId(),
                         response.getRejectCall(),
                         !response.getSkipCallLog(),
-                        !response.getSkipNotification());
+                        !response.getSkipNotification(),
+                        new ComponentName(getPackageName(), getClass().getName()));
             } else {
                 mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId());
             }
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 34603a3..0589cd4 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -272,6 +272,9 @@
 
     /**
      * Call can be upgraded to a video call.
+     * @deprecated Use {@link #CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL} and
+     * {@link #CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL} to indicate for a call whether or not
+     * video calling is supported.
      */
     public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 0x00080000;
 
diff --git a/telecomm/java/android/telecom/Logging/EventManager.java b/telecomm/java/android/telecom/Logging/EventManager.java
index 2bda648..1342038 100644
--- a/telecomm/java/android/telecom/Logging/EventManager.java
+++ b/telecomm/java/android/telecom/Logging/EventManager.java
@@ -180,7 +180,7 @@
             }
         }
 
-        private final List<Event> mEvents = new LinkedList<>();
+        private final List<Event> mEvents = Collections.synchronizedList(new LinkedList<>());
         private final Loggable mRecordEntry;
 
         public EventRecord(Loggable recordEntry) {
@@ -197,7 +197,7 @@
         }
 
         public List<Event> getEvents() {
-            return mEvents;
+            return new LinkedList<>(mEvents);
         }
 
         public List<EventTiming> extractEventTimings() {
@@ -207,21 +207,24 @@
 
             LinkedList<EventTiming> result = new LinkedList<>();
             Map<String, PendingResponse> pendingResponses = new HashMap<>();
-            for (Event event : mEvents) {
-                if (requestResponsePairs.containsKey(event.eventId)) {
-                    // This event expects a response, so add that expected response to the maps
-                    // of pending events.
-                    for (EventManager.TimedEventPair p : requestResponsePairs.get(event.eventId)) {
-                        pendingResponses.put(p.mResponse, new PendingResponse(event.eventId,
-                                event.time, p.mTimeoutMillis, p.mName));
+            synchronized (mEvents) {
+                for (Event event : mEvents) {
+                    if (requestResponsePairs.containsKey(event.eventId)) {
+                        // This event expects a response, so add that expected response to the maps
+                        // of pending events.
+                        for (EventManager.TimedEventPair p : requestResponsePairs.get(
+                                event.eventId)) {
+                            pendingResponses.put(p.mResponse, new PendingResponse(event.eventId,
+                                    event.time, p.mTimeoutMillis, p.mName));
+                        }
                     }
-                }
 
-                PendingResponse pendingResponse = pendingResponses.remove(event.eventId);
-                if (pendingResponse != null) {
-                    long elapsedTime = event.time - pendingResponse.requestEventTimeMillis;
-                    if (elapsedTime < pendingResponse.timeoutMillis) {
-                        result.add(new EventTiming(pendingResponse.name, elapsedTime));
+                    PendingResponse pendingResponse = pendingResponses.remove(event.eventId);
+                    if (pendingResponse != null) {
+                        long elapsedTime = event.time - pendingResponse.requestEventTimeMillis;
+                        if (elapsedTime < pendingResponse.timeoutMillis) {
+                            result.add(new EventTiming(pendingResponse.name, elapsedTime));
+                        }
                     }
                 }
             }
@@ -233,7 +236,8 @@
             pw.print(mRecordEntry.getDescription());
 
             pw.increaseIndent();
-            for (Event event : mEvents) {
+            // Iterate over copy of events so that this doesn't hold the lock for too long.
+            for (Event event : getEvents()) {
                 pw.print(event.timestampString);
                 pw.print(" - ");
                 pw.print(event.eventId);
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 9a4ea9e7..2ffad03 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -985,10 +985,10 @@
     /**
      * Generates a string representation of a capabilities bitmask.
      *
-     * @param capabilities The capabilities bitmask.
      * @return String representation of the capabilities bitmask.
+     * @hide
      */
-    private String capabilitiesToString() {
+    public String capabilitiesToString() {
         StringBuilder sb = new StringBuilder();
         if (hasCapabilities(CAPABILITY_SELF_MANAGED)) {
             sb.append("SelfManaged ");
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index fa16bfe..9f0bdd7 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -15,6 +15,7 @@
 package android.telecom;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressAutoDoc;
@@ -36,6 +37,8 @@
 
 import com.android.internal.telecom.ITelecomService;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -413,8 +416,10 @@
      * <p>
      * The phone number of the call used by Telecom to determine which call should be handed over.
      * @hide
+     * @deprecated Use the public handover APIs.  See
+     * {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} for more information.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
     public static final String EXTRA_IS_HANDOVER = "android.telecom.extra.IS_HANDOVER";
 
     /**
@@ -528,11 +533,19 @@
     public static final char DTMF_CHARACTER_WAIT = ';';
 
     /**
+     * @hide
+     */
+    @IntDef(prefix = { "TTY_MODE_" },
+            value = {TTY_MODE_OFF, TTY_MODE_FULL, TTY_MODE_HCO, TTY_MODE_VCO})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TtyMode {}
+
+    /**
      * TTY (teletypewriter) mode is off.
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
     public static final int TTY_MODE_OFF = 0;
 
     /**
@@ -541,6 +554,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int TTY_MODE_FULL = 1;
 
     /**
@@ -550,6 +564,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int TTY_MODE_HCO = 2;
 
     /**
@@ -559,6 +574,7 @@
      *
      * @hide
      */
+    @SystemApi
     public static final int TTY_MODE_VCO = 3;
 
     /**
@@ -827,8 +843,9 @@
      * @return The phone account handle of the current sim call manager.
      *
      * @hide
+     * @deprecated Use {@link #getSimCallManager()}.
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
     public PhoneAccountHandle getSimCallManager(int userId) {
         try {
             if (isServiceConnected()) {
@@ -929,10 +946,12 @@
      * Returns a list of {@link PhoneAccountHandle}s including those which have not been enabled
      * by the user.
      *
+     * @param includeDisabledAccounts When {@code true}, disabled phone accounts will be included,
+     *                                when {@code false}, only
      * @return A list of {@code PhoneAccountHandle} objects.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 119305590)
     public List<PhoneAccountHandle> getCallCapablePhoneAccounts(boolean includeDisabledAccounts) {
         try {
             if (isServiceConnected()) {
@@ -1155,7 +1174,7 @@
     /**
      * Used to set the default dialer package.
      *
-     * @param packageName to set the default dialer to..
+     * @param packageName to set the default dialer to.
      *
      * @result {@code true} if the default dialer was successfully changed, {@code false} if
      *         the specified package does not correspond to an installed dialer, or is already
@@ -1166,7 +1185,10 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.MODIFY_PHONE_STATE,
+            android.Manifest.permission.WRITE_SECURE_SETTINGS})
     public boolean setDefaultDialer(String packageName) {
         try {
             if (isServiceConnected()) {
@@ -1179,12 +1201,10 @@
     }
 
     /**
-     * Used to determine the dialer package that is preloaded on the system partition.
+     * Determines the package name of the system-provided default phone app.
      *
      * @return package name for the system dialer package or null if no system dialer is preloaded.
-     * @hide
      */
-    @UnsupportedAppUsage
     public String getSystemDialerPackage() {
         try {
             if (isServiceConnected()) {
@@ -1545,8 +1565,9 @@
      * - {@link TelecomManager#TTY_MODE_VCO}
      * @hide
      */
-    @UnsupportedAppUsage
-    public int getCurrentTtyMode() {
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @TtyMode int getCurrentTtyMode() {
         try {
             if (isServiceConnected()) {
                 return getTelecomService().getCurrentTtyMode(mContext.getOpPackageName());
diff --git a/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
index 2e0af27..d255ed1 100644
--- a/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl
@@ -16,6 +16,8 @@
 
 package com.android.internal.telecom;
 
+import android.content.ComponentName;
+
 /**
  * Internal remote callback interface for call screening services.
  *
@@ -30,5 +32,6 @@
             String callId,
             boolean shouldReject,
             boolean shouldAddToCallLog,
-            boolean shouldShowNotification);
+            boolean shouldShowNotification,
+            in ComponentName componentName);
 }
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index d7024cf..b3e1ffa 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -2756,6 +2756,13 @@
                 "content://telephony/carriers/enforce_managed");
 
         /**
+         * The {@code content://} style URL to be called from Telephony to query current APNs.
+         * @hide
+         */
+        public static final Uri SIM_APN_LIST = Uri.parse(
+                "content://telephony/carriers/sim_apn_list");
+
+        /**
          * The column name for ENFORCE_MANAGED_URI, indicates whether DPC-owned APNs are enforced.
          * @hide
          */
@@ -3606,6 +3613,27 @@
         }
 
         /**
+         * Generates a content {@link Uri} used to receive updates on precise carrier identity
+         * change on the given subscriptionId
+         * {@link TelephonyManager#ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED}.
+         * <p>
+         * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+         * precise carrier identity {@link TelephonyManager#getSimPreciseCarrierId()}
+         * while your app is running. You can also use a {@link JobService} to ensure your app
+         * is notified of changes to the {@link Uri} even when it is not running.
+         * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+         * updates to the {@link Uri}.
+         *
+         * @param subscriptionId the subscriptionId to receive updates on
+         * @return the Uri used to observe precise carrier identity changes
+         * @hide
+         */
+        public static Uri getPreciseCarrierIdUriForSubscriptionId(int subscriptionId) {
+            return Uri.withAppendedPath(Uri.withAppendedPath(CONTENT_URI, "precise"),
+                    String.valueOf(subscriptionId));
+        }
+
+        /**
          * A user facing carrier name.
          * @see TelephonyManager#getSimCarrierIdName()
          * <P>Type: TEXT </P>
@@ -3620,6 +3648,35 @@
         public static final String CARRIER_ID = "carrier_id";
 
         /**
+         * A user facing carrier name for precise carrier id.
+         * @see TelephonyManager#getSimPreciseCarrierIdName()
+         * This is not a database column, only used to notify content observers for
+         * {@link #getPreciseCarrierIdUriForSubscriptionId(int)}
+         * @hide
+         */
+        public static final String PRECISE_CARRIER_ID_NAME = "precise_carrier_id_name";
+
+        /**
+         * A fine-grained carrier id.
+         * @see TelephonyManager#getSimPreciseCarrierId()
+         * This is not a database column, only used to notify content observers for
+         * {@link #getPreciseCarrierIdUriForSubscriptionId(int)}
+         * @hide
+         */
+        public static final String PRECISE_CARRIER_ID = "precise_carrier_id";
+
+        /**
+         * A unique parent carrier id. The parent-child
+         * relationship can be used to further differentiate a single carrier by different networks,
+         * by prepaid v.s. postpaid or even by 4G v.s. 3G plan. It's an optional field.
+         * A carrier id with a valid parent_carrier_id is considered fine-grained carrier id, will
+         * not be returned as {@link #CARRIER_ID} but {@link #PRECISE_CARRIER_ID}.
+         * <P>Type: INTEGER </P>
+         * @hide
+         */
+        public static final String PARENT_CARRIER_ID = "parent_carrier_id";
+
+        /**
          * A unique mno carrier id. mno carrier shares the same {@link All#MCCMNC} as carrier id
          * and can be solely identified by {@link All#MCCMNC} only. If there is no such mno
          * carrier, then mno carrier id equals to {@link #CARRIER_ID carrier id}.
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index cac9f2b..9c64cf6 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -32,7 +32,20 @@
         public static final int IWLAN = 5;
 
         /** @hide */
-        private AccessNetworkType() {};
+        private AccessNetworkType() {}
+
+        /** @hide */
+        public static String toString(int type) {
+            switch (type) {
+                case UNKNOWN: return "UNKNOWN";
+                case GERAN: return "GERAN";
+                case UTRAN: return "UTRAN";
+                case EUTRAN: return "EUTRAN";
+                case CDMA2000: return "CDMA2000";
+                case IWLAN: return "IWLAN";
+                default: return Integer.toString(type);
+            }
+        }
     }
 
     /**
@@ -47,7 +60,16 @@
         public static final int WLAN = 2;
 
         /** @hide */
-        private TransportType() {};
+        private TransportType() {}
+
+        /** @hide */
+        public static String toString(int type) {
+            switch (type) {
+                case WWAN: return "WWAN";
+                case WLAN: return "WLAN";
+                default: return Integer.toString(type);
+            }
+        }
     }
 
     /**
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 983e766..c7ecdfa 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1079,24 +1079,44 @@
             "wfc_operator_error_codes_string_array";
 
     /**
-     * Indexes of SPN format strings in wfcSpnFormats and wfcDataSpnFormats.
+     * Indexes of SPN format strings in wfcSpnFormats.
      *
      * <p>Available options are:
      * <ul>
-     * <li> 0: %s</li>
-     * <li> 1: %s Wi-Fi Calling</li>
-     * <li> 2: WLAN Call</li>
-     * <li> 3: %s WLAN Call</li>
-     * <li> 4: %s Wi-Fi</li>
-     * <li> 5: WiFi Calling | %s</li>
-     * <li> 6: %s VoWifi</li>
+     * <li>  0: %s</li>
+     * <li>  1: %s Wi-Fi Calling</li>
+     * <li>  2: WLAN Call</li>
+     * <li>  3: %s WLAN Call</li>
+     * <li>  4: %s Wi-Fi</li>
+     * <li>  5: WiFi Calling | %s</li>
+     * <li>  6: %s VoWifi</li>
+     * <li>  7: Wi-Fi Calling</li>
+     * <li>  8: Wi-Fi</li>
+     * <li>  9: WiFi Calling</li>
+     * <li> 10: VoWifi</li>
      * @hide
      */
     public static final String KEY_WFC_SPN_FORMAT_IDX_INT = "wfc_spn_format_idx_int";
-    /** @hide */
+
+    /**
+     * Indexes of data SPN format strings in wfcSpnFormats.
+     *
+     * @see KEY_WFC_SPN_FORMAT_IDX_INT for available options.
+     * @hide
+     */
     public static final String KEY_WFC_DATA_SPN_FORMAT_IDX_INT = "wfc_data_spn_format_idx_int";
 
     /**
+     * Indexes of SPN format strings in wfcSpnFormats used during flight mode.
+     *
+     * Set to -1 to use the value from KEY_WFC_SPN_FORMAT_IDX_INT also in this case.
+     * @see KEY_WFC_SPN_FORMAT_IDX_INT for other available options.
+     * @hide
+     */
+    public static final String KEY_WFC_FLIGHT_MODE_SPN_FORMAT_IDX_INT =
+            "wfc_flight_mode_spn_format_idx_int";
+
+    /**
      * Use root locale when reading wfcSpnFormats.
      *
      * If true, then the root locale will always be used when reading wfcSpnFormats. This means the
@@ -1231,6 +1251,38 @@
     public static final String KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL =
             "show_precise_failed_cause_bool";
 
+    /**
+     * Boolean to decide whether lte is enabled.
+     * @hide
+     */
+    public static final String KEY_LTE_ENABLED_BOOL = "lte_enabled_bool";
+
+    /**
+     * Boolean to decide whether TD-SCDMA is supported.
+     * @hide
+     */
+    public static final String KEY_SUPPORT_TDSCDMA_BOOL = "support_tdscdma_bool";
+
+    /**
+     * A list of mcc/mnc that support TD-SCDMA for device when connect to the roaming network.
+     * @hide
+     */
+    public static final String KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY =
+            "support_tdscdma_roaming_networks_string_array";
+
+    /**
+     * Boolean to decide whether world mode is enabled.
+     * @hide
+     */
+    public static final String KEY_WORLD_MODE_ENABLED_BOOL = "world_mode_enabled_bool";
+
+    /**
+     * Flatten {@link android.content.ComponentName} of the carrier's settings activity.
+     * @hide
+     */
+    public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING =
+            "carrier_settings_activity_component_name_string";
+
     // These variables are used by the MMS service and exposed through another API,
     // SmsManager. The variable names and string values are copied from there.
     public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
@@ -1268,18 +1320,13 @@
     public static final String KEY_MMS_CLOSE_CONNECTION_BOOL = "mmsCloseConnection";
 
     /**
-     * If carriers require differentiate un-provisioned status: cold sim or out of credit sim
-     * a package name and activity name can be provided to launch a supported carrier application
-     * that check the sim provisioning status
-     * The first element is the package name and the second element is the activity name
-     * of the provisioning app
-     * example:
-     * <item>com.google.android.carrierPackageName</item>
-     * <item>com.google.android.carrierPackageName.CarrierActivityName</item>
-     * The ComponentName of the carrier activity that can setup the device and activate with the
-     * network as part of the Setup Wizard flow.
+     * The flatten {@link android.content.ComponentName componentName} of the activity that can
+     * setup the device and activate with the network per carrier requirements.
+     *
+     * e.g, com.google.android.carrierPackageName/.CarrierActivityName
      * @hide
      */
+    @SystemApi
     public static final String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
 
     /**
@@ -2245,6 +2292,45 @@
     public static final String KEY_SUPPORT_EMERGENCY_DIALER_SHORTCUT_BOOL =
             "support_emergency_dialer_shortcut_bool";
 
+    /**
+     * Call forwarding uses USSD command without SS command.
+     * When {@code true}, the call forwarding query/set by ussd command and UI only display Call
+     * Forwarding when unanswered.
+     * When {@code false}, don't use USSD to query/set call forwarding.
+     * @hide
+     */
+    public static final String KEY_USE_CALL_FORWARDING_USSD_BOOL = "use_call_forwarding_ussd_bool";
+
+    /**
+     * This flag specifies whether to support for the caller id set command by ussd.
+     * When {@code true}, device shall sync caller id ussd result to ss command.
+     * When {@code false}, caller id don't support ussd command.
+     * @hide
+     */
+    public static final String KEY_USE_CALLER_ID_USSD_BOOL = "use_caller_id_ussd_bool";
+
+    /**
+     * Specifies the service class for call waiting service.
+     * Default value is
+     * {@link com.android.internal.telephony.CommandsInterface#SERVICE_CLASS_VOICE}.
+     * <p>
+     * See 27.007 +CCFC or +CLCK.
+     * The value set as below:
+     * {@link com.android.internal.telephony.CommandsInterface#SERVICE_CLASS_NONE}
+     * {@link com.android.internal.telephony.CommandsInterface#SERVICE_CLASS_VOICE}
+     * {@link com.android.internal.telephony.CommandsInterface#SERVICE_CLASS_DATA}
+     * {@link com.android.internal.telephony.CommandsInterface#SERVICE_CLASS_FAX}
+     * {@link com.android.internal.telephony.CommandsInterface#SERVICE_CLASS_SMS}
+     * {@link com.android.internal.telephony.CommandsInterface#SERVICE_CLASS_DATA_SYNC}
+     * {@link com.android.internal.telephony.CommandsInterface#SERVICE_CLASS_DATA_ASYNC}
+     * {@link com.android.internal.telephony.CommandsInterface#SERVICE_CLASS_PACKET}
+     * {@link com.android.internal.telephony.CommandsInterface#SERVICE_CLASS_PAD}
+     * {@link com.android.internal.telephony.CommandsInterface#SERVICE_CLASS_MAX}
+     * @hide
+     */
+    public static final String KEY_CALL_WAITING_SERVICE_CLASS_INT =
+            "call_waiting_service_class_int";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -2424,6 +2510,7 @@
         sDefaults.putStringArray(KEY_WFC_OPERATOR_ERROR_CODES_STRING_ARRAY, null);
         sDefaults.putInt(KEY_WFC_SPN_FORMAT_IDX_INT, 0);
         sDefaults.putInt(KEY_WFC_DATA_SPN_FORMAT_IDX_INT, 0);
+        sDefaults.putInt(KEY_WFC_FLIGHT_MODE_SPN_FORMAT_IDX_INT, -1);
         sDefaults.putBoolean(KEY_WFC_SPN_USE_ROOT_LOCALE, false);
         sDefaults.putString(KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING, "");
         sDefaults.putBoolean(KEY_CONFIG_WIFI_DISABLE_IN_ECBM, false);
@@ -2570,6 +2657,11 @@
         sDefaults.putBoolean(KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL, false);
         sDefaults.putBoolean(KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL, false);
         sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true);
+        sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true);
+        sDefaults.putBoolean(KEY_SUPPORT_TDSCDMA_BOOL, false);
+        sDefaults.putStringArray(KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
+        sDefaults.putBoolean(KEY_WORLD_MODE_ENABLED_BOOL, false);
+        sDefaults.putString(KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING, "");
         sDefaults.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
         sDefaults.putBoolean(KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL, false);
         sDefaults.putIntArray(KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY,
@@ -2595,6 +2687,9 @@
         sDefaults.putBoolean(KEY_CALL_WAITING_OVER_UT_WARNING_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL, true);
         sDefaults.putBoolean(KEY_SUPPORT_EMERGENCY_DIALER_SHORTCUT_BOOL, true);
+        sDefaults.putBoolean(KEY_USE_CALL_FORWARDING_USSD_BOOL, false);
+        sDefaults.putBoolean(KEY_USE_CALLER_ID_USSD_BOOL, false);
+        sDefaults.putInt(KEY_CALL_WAITING_SERVICE_CLASS_INT, 1 /* SERVICE_CLASS_VOICE */);
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellConfigLte.java b/telephony/java/android/telephony/CellConfigLte.java
new file mode 100644
index 0000000..35769f0
--- /dev/null
+++ b/telephony/java/android/telephony/CellConfigLte.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2018 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * The container of LTE cell related configs.
+ * @hide
+ */
+public class CellConfigLte implements Parcelable {
+    private final boolean mIsEndcAvailable;
+
+    /** @hide */
+    public CellConfigLte() {
+        mIsEndcAvailable = false;
+    }
+
+    /** @hide */
+    public CellConfigLte(boolean isEndcAvailable) {
+        mIsEndcAvailable = isEndcAvailable;
+    }
+
+    /** @hide */
+    public CellConfigLte(CellConfigLte config) {
+        mIsEndcAvailable = config.mIsEndcAvailable;
+    }
+
+    /**
+     * Indicates that if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the LTE cell.
+     *
+     * Reference: 3GPP TS 36.331 v15.2.2 6.3.1 System information blocks.
+     *
+     * @return {@code true} if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the LTE cell.
+     *
+     */
+    boolean isEndcAvailable() {
+        return mIsEndcAvailable;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIsEndcAvailable);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof CellConfigLte)) return false;
+
+        CellConfigLte o = (CellConfigLte) other;
+        return mIsEndcAvailable == o.mIsEndcAvailable;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeBoolean(mIsEndcAvailable);
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder().append(this.getClass().getName())
+                .append(" :{")
+                .append(" isEndcAvailable = " + mIsEndcAvailable)
+                .append(" }")
+                .toString();
+    }
+
+    private CellConfigLte(Parcel in) {
+        mIsEndcAvailable = in.readBoolean();
+    }
+
+    public static final Creator<CellConfigLte> CREATOR = new Creator<CellConfigLte>() {
+        @Override
+        public CellConfigLte createFromParcel(Parcel in) {
+            return new CellConfigLte(in);
+        }
+
+        @Override
+        public CellConfigLte[] newArray(int size) {
+            return new CellConfigLte[0];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 76a0026..6958d22 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -190,6 +190,7 @@
                         case CellInfo.TYPE_LTE: return CellIdentityLte.createFromParcelBody(in);
                         case CellInfo.TYPE_TDSCDMA:
                             return CellIdentityTdscdma.createFromParcelBody(in);
+                        case CellInfo.TYPE_NR: return CellIdentityNr.createFromParcelBody(in);
                         default: throw new IllegalArgumentException("Bad Cell identity Parcel");
                     }
                 }
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
new file mode 100644
index 0000000..6b1b84c
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2018 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.telephony;
+
+import android.os.Parcel;
+import android.telephony.gsm.GsmCellLocation;
+
+import java.util.Objects;
+
+/**
+ * Information to represent a unique 5G NR cell.
+ */
+public final class CellIdentityNr extends CellIdentity {
+    private static final String TAG = "CellIdentityNr";
+
+    private final int mNrArfcn;
+    private final int mPci;
+    private final int mTac;
+
+    /**
+     *
+     * @param pci Physical Cell Id in range [0, 1007].
+     * @param tac 16-bit Tracking Area Code.
+     * @param nrArfcn NR Absolute Radio Frequency Channel Number, in range [0, 3279165].
+     * @param mccStr 3-digit Mobile Country Code in string format.
+     * @param mncStr 2 or 3-digit Mobile Network Code in string format.
+     * @param alphal long alpha Operator Name String or Enhanced Operator Name String.
+     * @param alphas short alpha Operator Name String or Enhanced Operator Name String.
+     *
+     * @hide
+     */
+    public CellIdentityNr(int pci, int tac, int nrArfcn,  String mccStr, String mncStr,
+            String alphal, String alphas) {
+        super(TAG, CellInfo.TYPE_NR, mccStr, mncStr, alphal, alphas);
+        mPci = pci;
+        mTac = tac;
+        mNrArfcn = nrArfcn;
+    }
+
+    /**
+     * @return a CellLocation object for this CellIdentity.
+     * @hide
+     */
+    @Override
+    public CellLocation asCellLocation() {
+        return new GsmCellLocation();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(super.hashCode(), mPci, mTac, mNrArfcn);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof CellIdentityNr)) {
+            return false;
+        }
+
+        CellIdentityNr o = (CellIdentityNr) other;
+        return super.equals(o) && mPci == o.mPci && mTac == o.mTac && mNrArfcn == o.mNrArfcn;
+    }
+
+    /**
+     * Get the Absolute Radio Frequency Channel Number.
+     * @return Integer value in range [0, 3279165] or {@link CellInfo#UNAVAILABLE} if unknown.
+     */
+    @Override
+    public int getChannelNumber() {
+        return mNrArfcn;
+    }
+
+    /**
+     * Get the physical cell id.
+     * @return Integer value in range [0, 1007] or {@link CellInfo#UNAVAILABLE} if unknown.
+     */
+    public int getPci() {
+        return mPci;
+    }
+
+    /**
+     * Get the tracking area code.
+     * @return a 16 bit integer or {@link CellInfo#UNAVAILABLE} if unknown.
+     */
+    public int getTac() {
+        return mTac;
+    }
+
+    /**
+     * @return Mobile Country Code in string format, or {@code null} if unknown.
+     */
+    public String getMccString() {
+        return mMccStr;
+    }
+
+    /**
+     * @return Mobile Network Code in string fomrat, or {@code null} if unknown.
+     */
+    public String getMncString() {
+        return mMncStr;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(TAG + ":{")
+                .append(" mPci = ").append(mPci)
+                .append(" mTac = ").append(mTac)
+                .append(" mNrArfcn = ").append(mNrArfcn)
+                .append(" mMcc = ").append(mMccStr)
+                .append(" mMnc = ").append(mMncStr)
+                .append(" mAlphaLong = ").append(mAlphaLong)
+                .append(" mAlphaShort = ").append(mAlphaShort)
+                .append(" }")
+                .toString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int type) {
+        super.writeToParcel(dest, CellInfo.TYPE_NR);
+        dest.writeInt(mPci);
+        dest.writeInt(mTac);
+        dest.writeInt(mNrArfcn);
+    }
+
+    /** Construct from Parcel, type has already been processed */
+    private CellIdentityNr(Parcel in) {
+        super(TAG, CellInfo.TYPE_NR, in);
+        mPci = in.readInt();
+        mTac = in.readInt();
+        mNrArfcn = in.readInt();
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellIdentityNr> CREATOR =
+            new Creator<CellIdentityNr>() {
+                @Override
+                public CellIdentityNr createFromParcel(Parcel in) {
+                    // Skip the type info.
+                    in.readInt();
+                    return createFromParcelBody(in);
+                }
+
+                @Override
+                public CellIdentityNr[] newArray(int size) {
+                    return new CellIdentityNr[size];
+                }
+            };
+
+    /** @hide */
+    protected static CellIdentityNr createFromParcelBody(Parcel in) {
+        return new CellIdentityNr(in);
+    }
+}
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 1c63e82..d0b2687 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -42,38 +42,51 @@
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = "TYPE_", value = {TYPE_GSM, TYPE_CDMA, TYPE_LTE, TYPE_WCDMA, TYPE_TDSCDMA})
+    @IntDef(prefix = "TYPE_",
+            value = {TYPE_GSM, TYPE_CDMA, TYPE_LTE, TYPE_WCDMA, TYPE_TDSCDMA, TYPE_NR})
     public @interface Type {}
+
     /**
      * Unknown cell identity type
      * @hide
      */
-    public static final int TYPE_UNKNOWN        = 0;
+    public static final int TYPE_UNKNOWN = 0;
+
     /**
      * GSM cell identity type
      * @hide
      */
-    public static final int TYPE_GSM            = 1;
+    public static final int TYPE_GSM = 1;
+
     /**
      * CDMA cell identity type
      * @hide
      */
-    public static final int TYPE_CDMA           = 2;
+    public static final int TYPE_CDMA = 2;
+
     /**
      * LTE cell identity type
      * @hide
      */
-    public static final int TYPE_LTE            = 3;
+    public static final int TYPE_LTE = 3;
+
     /**
      * WCDMA cell identity type
      * @hide
      */
-    public static final int TYPE_WCDMA          = 4;
+    public static final int TYPE_WCDMA = 4;
+
     /**
      * TD-SCDMA cell identity type
      * @hide
      */
-    public static final int TYPE_TDSCDMA        = 5;
+    public static final int TYPE_TDSCDMA = 5;
+
+    /**
+     * 5G cell identity type
+     * @hide
+     */
+    public static final int TYPE_NR = 6;
 
     // Type to distinguish where time stamp gets recorded.
 
@@ -277,6 +290,7 @@
                     case TYPE_LTE: return CellInfoLte.createFromParcelBody(in);
                     case TYPE_WCDMA: return CellInfoWcdma.createFromParcelBody(in);
                     case TYPE_TDSCDMA: return CellInfoTdscdma.createFromParcelBody(in);
+                    case TYPE_NR: return CellInfoNr.createFromParcelBody(in);
                     default: throw new RuntimeException("Bad CellInfo Parcel");
                 }
         }
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 389f643..7d5388b 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -19,7 +19,8 @@
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.telephony.Rlog;
+
+import java.util.Objects;
 
 /**
  * A {@link CellInfo} representing an LTE cell that provides identity and measurement info.
@@ -31,6 +32,7 @@
 
     private CellIdentityLte mCellIdentityLte;
     private CellSignalStrengthLte mCellSignalStrengthLte;
+    private CellConfigLte mCellConfig;
 
     /** @hide */
     @UnsupportedAppUsage
@@ -38,6 +40,7 @@
         super();
         mCellIdentityLte = new CellIdentityLte();
         mCellSignalStrengthLte = new CellSignalStrengthLte();
+        mCellConfig = new CellConfigLte();
     }
 
     /** @hide */
@@ -45,6 +48,7 @@
         super(ci);
         this.mCellIdentityLte = ci.mCellIdentityLte.copy();
         this.mCellSignalStrengthLte = ci.mCellSignalStrengthLte.copy();
+        this.mCellConfig = new CellConfigLte(ci.mCellConfig);
     }
 
     @Override
@@ -71,26 +75,37 @@
         mCellSignalStrengthLte = css;
     }
 
+    /** @hide */
+    public void setCellConfig(CellConfigLte cellConfig) {
+        if (DBG) log("setCellConfig: " + cellConfig);
+        mCellConfig = cellConfig;
+    }
+
+    /** @hide */
+    public CellConfigLte getCellConfig() {
+        if (DBG) log("getCellConfig: " + mCellConfig);
+        return mCellConfig;
+    }
+
     /**
      * @return hash code
      */
     @Override
     public int hashCode() {
-        return super.hashCode() + mCellIdentityLte.hashCode() + mCellSignalStrengthLte.hashCode();
+        return Objects.hash(
+                super.hashCode(),
+                mCellIdentityLte.hashCode(),
+                mCellSignalStrengthLte.hashCode(),
+                mCellConfig.hashCode());
     }
 
     @Override
     public boolean equals(Object other) {
-        if (!super.equals(other)) {
-            return false;
-        }
-        try {
-            CellInfoLte o = (CellInfoLte) other;
-            return mCellIdentityLte.equals(o.mCellIdentityLte)
-                    && mCellSignalStrengthLte.equals(o.mCellSignalStrengthLte);
-        } catch (ClassCastException e) {
-            return false;
-        }
+        if (!(other instanceof CellInfoLte)) return false;
+        CellInfoLte o = (CellInfoLte) other;
+        return super.equals(o) && mCellIdentityLte.equals(o.mCellIdentityLte)
+                && mCellSignalStrengthLte.equals(o.mCellSignalStrengthLte)
+                && mCellConfig.equals(o.mCellConfig);
     }
 
     @Override
@@ -101,6 +116,7 @@
         sb.append(super.toString());
         sb.append(" ").append(mCellIdentityLte);
         sb.append(" ").append(mCellSignalStrengthLte);
+        sb.append(" ").append(mCellConfig);
         sb.append("}");
 
         return sb.toString();
@@ -119,6 +135,7 @@
         super.writeToParcel(dest, flags, TYPE_LTE);
         mCellIdentityLte.writeToParcel(dest, flags);
         mCellSignalStrengthLte.writeToParcel(dest, flags);
+        mCellConfig.writeToParcel(dest, flags);
     }
 
     /**
@@ -129,6 +146,7 @@
         super(in);
         mCellIdentityLte = CellIdentityLte.CREATOR.createFromParcel(in);
         mCellSignalStrengthLte = CellSignalStrengthLte.CREATOR.createFromParcel(in);
+        mCellConfig = CellConfigLte.CREATOR.createFromParcel(in);
         if (DBG) log("CellInfoLte(Parcel): " + toString());
     }
 
diff --git a/telephony/java/android/telephony/CellInfoNr.java b/telephony/java/android/telephony/CellInfoNr.java
new file mode 100644
index 0000000..11857a6
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoNr.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 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.telephony;
+
+import android.os.Parcel;
+
+import java.util.Objects;
+
+/**
+ * A {@link CellInfo} representing an 5G NR cell that provides identity and measurement info.
+ */
+public final class CellInfoNr extends CellInfo {
+    private static final String TAG = "CellInfoNr";
+
+    private final CellIdentityNr mCellIdentity;
+    private final CellSignalStrengthNr mCellSignalStrength;
+
+    private CellInfoNr(Parcel in) {
+        super(in);
+        mCellIdentity = CellIdentityNr.CREATOR.createFromParcel(in);
+        mCellSignalStrength = CellSignalStrengthNr.CREATOR.createFromParcel(in);
+    }
+
+    @Override
+    public CellIdentity getCellIdentity() {
+        return mCellIdentity;
+    }
+
+    @Override
+    public CellSignalStrength getCellSignalStrength() {
+        return mCellSignalStrength;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(super.hashCode(), mCellIdentity, mCellSignalStrength);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof CellInfoNr)) {
+            return false;
+        }
+
+        CellInfoNr o = (CellInfoNr) other;
+        return super.equals(o) && mCellIdentity.equals(o.mCellIdentity)
+                && mCellSignalStrength.equals(o.mCellSignalStrength);
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder()
+                .append(TAG + ":{")
+                .append(" " + super.toString())
+                .append(" " + mCellIdentity)
+                .append(" " + mCellSignalStrength)
+                .append(" }")
+                .toString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags, TYPE_NR);
+        mCellIdentity.writeToParcel(dest, flags);
+        mCellSignalStrength.writeToParcel(dest, flags);
+    }
+
+    public static final Creator<CellInfoNr> CREATOR = new Creator<CellInfoNr>() {
+        @Override
+        public CellInfoNr createFromParcel(Parcel in) {
+            // Skip the type info.
+            in.readInt();
+            return new CellInfoNr(in);
+        }
+
+        @Override
+        public CellInfoNr[] newArray(int size) {
+            return new CellInfoNr[size];
+        }
+    };
+
+    /** @hide */
+    protected static CellInfoNr createFromParcelBody(Parcel in) {
+        return new CellInfoNr(in);
+    }
+}
diff --git a/telephony/java/android/telephony/CellSignalStrength.java b/telephony/java/android/telephony/CellSignalStrength.java
index 6090d5c..fd21d42 100644
--- a/telephony/java/android/telephony/CellSignalStrength.java
+++ b/telephony/java/android/telephony/CellSignalStrength.java
@@ -21,15 +21,20 @@
  */
 public abstract class CellSignalStrength {
 
-    public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
+    public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN =
+            TelephonyProtoEnums.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; // 0
 
-    public static final int SIGNAL_STRENGTH_POOR = 1;
+    public static final int SIGNAL_STRENGTH_POOR =
+            TelephonyProtoEnums.SIGNAL_STRENGTH_POOR; // 1
 
-    public static final int SIGNAL_STRENGTH_MODERATE = 2;
+    public static final int SIGNAL_STRENGTH_MODERATE =
+            TelephonyProtoEnums.SIGNAL_STRENGTH_MODERATE; // 2
 
-    public static final int SIGNAL_STRENGTH_GOOD = 3;
+    public static final int SIGNAL_STRENGTH_GOOD =
+            TelephonyProtoEnums.SIGNAL_STRENGTH_GOOD; // 3
 
-    public static final int SIGNAL_STRENGTH_GREAT = 4;
+    public static final int SIGNAL_STRENGTH_GREAT =
+            TelephonyProtoEnums.SIGNAL_STRENGTH_GREAT; // 4
 
     /** @hide */
     public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index d6856b3..d075394 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -19,7 +19,6 @@
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.telephony.Rlog;
 
 import java.util.Objects;
 
@@ -31,6 +30,25 @@
     private static final String LOG_TAG = "CellSignalStrengthLte";
     private static final boolean DBG = false;
 
+    /**
+     * Indicates the unknown or undetectable RSSI value in ASU.
+     *
+     * Reference: TS 27.007 8.5 - Signal quality +CSQ
+     */
+    private static final int SIGNAL_STRENGTH_LTE_RSSI_ASU_UNKNOWN = 99;
+    /**
+     * Indicates the maximum valid RSSI value in ASU.
+     *
+     * Reference: TS 27.007 8.5 - Signal quality +CSQ
+     */
+    private static final int SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MAX_VALUE = 31;
+    /**
+     * Indicates the minimum valid RSSI value in ASU.
+     *
+     * Reference: TS 27.007 8.5 - Signal quality +CSQ
+     */
+    private static final int SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MIN_VALUE = 0;
+
     @UnsupportedAppUsage
     private int mSignalStrength;
     @UnsupportedAppUsage
@@ -142,6 +160,19 @@
     }
 
     /**
+     * Get Received Signal Strength Indication (RSSI) in dBm
+     *
+     * The value range is [-113, -51] inclusively or {@link CellInfo#UNAVAILABLE} if unavailable.
+     *
+     * Reference: TS 27.007 8.5 Signal quality +CSQ
+     *
+     * @return the RSSI if available or {@link CellInfo#UNAVAILABLE} if unavailable.
+     */
+    public int getRssi() {
+        return convertRssiAsuToDBm(mSignalStrength);
+    }
+
+    /**
      * Get reference signal signal-to-noise ratio
      *
      * @return the RSSNR if available or
@@ -309,4 +340,17 @@
     private static void log(String s) {
         Rlog.w(LOG_TAG, s);
     }
+
+    private static int convertRssiAsuToDBm(int rssiAsu) {
+        if (rssiAsu != SIGNAL_STRENGTH_LTE_RSSI_ASU_UNKNOWN
+                && (rssiAsu < SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MIN_VALUE
+                || rssiAsu > SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MAX_VALUE)) {
+            Rlog.e(LOG_TAG, "convertRssiAsuToDBm: invalid RSSI in ASU=" + rssiAsu);
+            return CellInfo.UNAVAILABLE;
+        }
+        if (rssiAsu == SIGNAL_STRENGTH_LTE_RSSI_ASU_UNKNOWN) {
+            return CellInfo.UNAVAILABLE;
+        }
+        return -113 + (2 * rssiAsu);
+    }
 }
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
new file mode 100644
index 0000000..8079242
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2018 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * 5G NR signal strength related information.
+ */
+public final class CellSignalStrengthNr extends CellSignalStrength implements Parcelable {
+    /**
+     * The value is used to indicate that the asu level is unknown.
+     * Reference: 3GPP TS 27.007 section 8.69.
+     * @hide
+     */
+    public static final int UNKNOWN_ASU_LEVEL = 99;
+
+    private static final String TAG = "CellSignalStrengthNr";
+
+    /**
+     * These threshold values are copied from LTE.
+     * TODO: make it configurable via CarrierConfig.
+     */
+    private static final int SIGNAL_GREAT_THRESHOLD = -95;
+    private static final int SIGNAL_GOOD_THRESHOLD = -105;
+    private static final int SIGNAL_MODERATE_THRESHOLD = -115;
+
+    private int mCsiRsrp;
+    private int mCsiRsrq;
+    private int mCsiSinr;
+    private int mSsRsrp;
+    private int mSsRsrq;
+    private int mSsSinr;
+
+    /**
+     * @param csiRsrp CSI reference signal received power.
+     * @param csiRsrq CSI reference signal received quality.
+     * @param csiSinr CSI signal-to-noise and interference ratio.
+     * @param ssRsrp SS reference signal received power.
+     * @param ssRsrq SS reference signal received quality.
+     * @param ssSinr SS signal-to-noise and interference ratio.
+     * @hide
+     */
+    public CellSignalStrengthNr(
+            int csiRsrp, int csiRsrq, int csiSinr, int ssRsrp, int ssRsrq, int ssSinr) {
+        mCsiRsrp = csiRsrp;
+        mCsiRsrq = csiRsrq;
+        mCsiSinr = csiSinr;
+        mSsRsrp = ssRsrp;
+        mSsRsrq = ssRsrq;
+        mSsSinr = ssSinr;
+    }
+
+    /**
+     * Reference: 3GPP TS 38.215.
+     * Range: -140 dBm to -44 dBm.
+     * @return SS reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported
+     * value.
+     */
+    public int getSsRsrp() {
+        return mSsRsrp;
+    }
+
+    /**
+     * Reference: 3GPP TS 38.215.
+     * Range: -20 dB to -3 dB.
+     * @return SS reference signal received quality, {@link CellInfo#UNAVAILABLE} means unreported
+     * value.
+     */
+    public int getSsRsrq() {
+        return mSsRsrq;
+    }
+
+    /**
+     * Reference: 3GPP TS 38.215 Sec 5.1.*, 3GPP TS 38.133 10.1.16.1
+     * Range: -23 dB to 40 dB
+     * @return SS signal-to-noise and interference ratio, {@link CellInfo#UNAVAILABLE} means
+     * unreported value.
+     */
+    public int getSsSinr() {
+        return mSsSinr;
+    }
+
+    /**
+     * Reference: 3GPP TS 38.215.
+     * Range: -140 dBm to -44 dBm.
+     * @return CSI reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported
+     * value.
+     */
+    public int getCsiRsrp() {
+        return mCsiRsrp;
+    }
+
+    /**
+     * Reference: 3GPP TS 38.215.
+     * Range: -20 dB to -3 dB.
+     * @return CSI reference signal received quality, {@link CellInfo#UNAVAILABLE} means unreported
+     * value.
+     */
+    public int getCsiRsrq() {
+        return mCsiRsrq;
+    }
+
+    /**
+     * Reference: 3GPP TS 38.215 Sec 5.1.*, 3GPP TS 38.133 10.1.16.1
+     * Range: -23 dB to 23 dB
+     * @return CSI signal-to-noise and interference ratio, {@link CellInfo#UNAVAILABLE} means
+     * unreported value.
+     */
+    public int getCsiSinr() {
+        return mCsiSinr;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** @hide */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mCsiRsrp);
+        dest.writeInt(mCsiRsrq);
+        dest.writeInt(mCsiSinr);
+        dest.writeInt(mSsRsrp);
+        dest.writeInt(mSsRsrq);
+        dest.writeInt(mSsSinr);
+    }
+
+    private CellSignalStrengthNr(Parcel in) {
+        mCsiRsrp = in.readInt();
+        mCsiRsrq = in.readInt();
+        mCsiSinr = in.readInt();
+        mSsRsrp = in.readInt();
+        mSsRsrq = in.readInt();
+        mSsSinr = in.readInt();
+    }
+
+    /** @hide */
+    @Override
+    public void setDefaultValues() {
+        mCsiRsrp = CellInfo.UNAVAILABLE;
+        mCsiRsrq = CellInfo.UNAVAILABLE;
+        mCsiSinr = CellInfo.UNAVAILABLE;
+        mSsRsrp = CellInfo.UNAVAILABLE;
+        mSsRsrq = CellInfo.UNAVAILABLE;
+        mSsSinr = CellInfo.UNAVAILABLE;
+    }
+
+    @Override
+    public int getLevel() {
+        if (mCsiRsrp == CellInfo.UNAVAILABLE) {
+            return SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        } else if (mCsiRsrp >= SIGNAL_GREAT_THRESHOLD) {
+            return SIGNAL_STRENGTH_GREAT;
+        } else if (mCsiRsrp >= SIGNAL_GOOD_THRESHOLD) {
+            return SIGNAL_STRENGTH_GOOD;
+        } else if (mCsiRsrp >= SIGNAL_MODERATE_THRESHOLD) {
+            return SIGNAL_STRENGTH_MODERATE;
+        } else {
+            return SIGNAL_STRENGTH_POOR;
+        }
+    }
+
+    /**
+     * Calculates the NR signal as an asu value between 0..97, 99 is unknown.
+     * Asu is calculated based on 3GPP RSRP, refer to 3GPP TS 27.007 section 8.69.
+     * @return an integer represent the asu level of the signal strength.
+     */
+    @Override
+    public int getAsuLevel() {
+        int asuLevel;
+        int nrDbm = getDbm();
+        if (nrDbm == CellInfo.UNAVAILABLE) {
+            asuLevel = UNKNOWN_ASU_LEVEL;
+        } else if (nrDbm <= -140) {
+            asuLevel = 0;
+        } else if (nrDbm >= -43) {
+            asuLevel = 97;
+        } else {
+            asuLevel = nrDbm + 140;
+        }
+        return asuLevel;
+    }
+
+    @Override
+    public int getDbm() {
+        return mCsiRsrp;
+    }
+
+    /** @hide */
+    @Override
+    public CellSignalStrength copy() {
+        return new CellSignalStrengthNr(
+                mCsiRsrp, mCsiRsrq, mCsiSinr, mSsRsrp, mSsRsrq, mSsSinr);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mCsiRsrp, mCsiRsrq, mCsiSinr, mSsRsrp, mSsRsrq, mSsSinr);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof CellSignalStrengthNr) {
+            CellSignalStrengthNr o = (CellSignalStrengthNr) obj;
+            return mCsiRsrp == o.mCsiRsrp && mCsiRsrq == o.mCsiRsrq && mCsiSinr == o.mCsiSinr
+                    && mSsRsrp == o.mSsRsrp && mSsRsrq == o.mSsRsrq && mSsSinr == o.mSsSinr;
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder()
+                .append(TAG + ":{")
+                .append(" csiRsrp = " + mCsiRsrp)
+                .append(" csiRsrq = " + mCsiRsrq)
+                .append(" csiSinr = " + mCsiSinr)
+                .append(" ssRsrp = " + mSsRsrp)
+                .append(" ssRsrq = " + mSsRsrq)
+                .append(" ssSinr = " + mSsSinr)
+                .append(" }")
+                .toString();
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Parcelable.Creator<CellSignalStrengthNr> CREATOR =
+            new Parcelable.Creator<CellSignalStrengthNr>() {
+        @Override
+        public CellSignalStrengthNr createFromParcel(Parcel in) {
+            return new CellSignalStrengthNr(in);
+        }
+
+        @Override
+        public CellSignalStrengthNr[] newArray(int size) {
+            return new CellSignalStrengthNr[size];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationStates.java b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
index 97e3037..b6e6cba 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationStates.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
@@ -17,17 +17,40 @@
      */
     public final int maxDataCalls;
 
-    DataSpecificRegistrationStates(int maxDataCalls) {
+    /**
+     * Indicates if the use of dual connectivity with NR is restricted.
+     * Reference: 3GPP TS 24.301 v15.03 section 9.3.3.12A.
+     */
+    public final boolean isDcNrRestricted;
+
+    /**
+     * Indicates if NR is supported by the selected PLMN.
+     *
+     * {@code true} if the bit N is in the PLMN-InfoList-r15 is true and the selected PLMN is
+     * present in plmn-IdentityList at position N.
+     * Reference: 3GPP TS 36.331 v15.2.2 section 6.3.1 PLMN-InfoList-r15.
+     *            3GPP TS 36.331 v15.2.2 section 6.2.2 SystemInformationBlockType1 message.
+     */
+    public final boolean isNrAvailable;
+
+    DataSpecificRegistrationStates(
+            int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable) {
         this.maxDataCalls = maxDataCalls;
+        this.isDcNrRestricted = isDcNrRestricted;
+        this.isNrAvailable = isNrAvailable;
     }
 
     private DataSpecificRegistrationStates(Parcel source) {
         maxDataCalls = source.readInt();
+        isDcNrRestricted = source.readBoolean();
+        isNrAvailable = source.readBoolean();
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(maxDataCalls);
+        dest.writeBoolean(isDcNrRestricted);
+        dest.writeBoolean(isNrAvailable);
     }
 
     @Override
@@ -37,24 +60,30 @@
 
     @Override
     public String toString() {
-        return "DataSpecificRegistrationStates {" + " mMaxDataCalls=" + maxDataCalls + "}";
+        return new StringBuilder().append(this.getClass().getName())
+                .append(" :{")
+                .append(" maxDataCalls = " + maxDataCalls)
+                .append(" isDcNrRestricted = " + isDcNrRestricted)
+                .append(" isNrAvailable = " + isNrAvailable)
+                .append(" }")
+                .toString();
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(maxDataCalls);
+        return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable);
     }
 
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
 
-        if (o == null || !(o instanceof DataSpecificRegistrationStates)) {
-            return false;
-        }
+        if (!(o instanceof DataSpecificRegistrationStates)) return false;
 
         DataSpecificRegistrationStates other = (DataSpecificRegistrationStates) o;
-        return this.maxDataCalls == other.maxDataCalls;
+        return this.maxDataCalls == other.maxDataCalls
+                && this.isDcNrRestricted == other.isDcNrRestricted
+                && this.isNrAvailable == other.isNrAvailable;
     }
 
     public static final Parcelable.Creator<DataSpecificRegistrationStates> CREATOR =
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index d7169b2..c6887ab 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -342,6 +342,12 @@
      */
     public static final int TOO_MANY_ONGOING_CALLS = 75;
 
+    /**
+     * Indicates that a new outgoing call cannot be placed because OTASP provisioning is currently
+     * in process.
+     */
+    public static final int OTASP_PROVISIONING_IN_PROCESS = 76;
+
     //*********************************************************************************************
     // When adding a disconnect type:
     // 1) Update toString() with the newly added disconnect type.
@@ -505,6 +511,8 @@
             return "CALLING_DISABLED";
         case TOO_MANY_ONGOING_CALLS:
             return "TOO_MANY_ONGOING_CALLS";
+        case OTASP_PROVISIONING_IN_PROCESS:
+            return "OTASP_PROVISIONING_IN_PROCESS";
         default:
             return "INVALID: " + cause;
         }
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/telephony/java/android/telephony/ICellInfoCallback.aidl
similarity index 66%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to telephony/java/android/telephony/ICellInfoCallback.aidl
index ede8695..7fb62682 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/telephony/java/android/telephony/ICellInfoCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 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,8 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package android.telephony;
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+import android.telephony.CellInfo;
+
+import java.util.List;
+
+/**
+ * Callback to provide asynchronous CellInfo.
+ * @hide
+ */
+oneway interface ICellInfoCallback
+{
+    void onCellInfo(in List<CellInfo> state);
+}
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index c3d8898..aee744f 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -70,6 +70,43 @@
     /** Registered on roaming network */
     public static final int REG_STATE_ROAMING               = 5;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "NR_STATUS_",
+            value = {NR_STATUS_NONE, NR_STATUS_RESTRICTED, NR_STATUS_NOT_RESTRICTED,
+                    NR_STATUS_CONNECTED})
+    public @interface NRStatus {}
+
+    /**
+     * The device isn't camped on an LTE cell or the LTE cell doesn't support E-UTRA-NR
+     * Dual Connectivity(EN-DC).
+     * @hide
+     */
+    public static final int NR_STATUS_NONE = -1;
+
+    /**
+     * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) but
+     * either the use of dual connectivity with NR(DCNR) is restricted or NR is not supported by
+     * the selected PLMN.
+     * @hide
+     */
+    public static final int NR_STATUS_RESTRICTED = 1;
+
+    /**
+     * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) and both
+     * the use of dual connectivity with NR(DCNR) is not restricted and NR is supported by the
+     * selected PLMN.
+     * @hide
+     */
+    public static final int NR_STATUS_NOT_RESTRICTED = 2;
+
+    /**
+     * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) and
+     * also connected to at least one 5G cell as a secondary serving cell.
+     * @hide
+     */
+    public static final int NR_STATUS_CONNECTED = 3;
+
     /**
      * Supported service type
      * @hide
@@ -104,6 +141,9 @@
 
     private int mAccessNetworkTechnology;
 
+    @NRStatus
+    private int mNrStatus;
+
     private final int mRejectCause;
 
     private final boolean mEmergencyOnly;
@@ -154,6 +194,7 @@
         mAvailableServices = availableServices;
         mCellIdentity = cellIdentity;
         mEmergencyOnly = emergencyOnly;
+        mNrStatus = NR_STATUS_NONE;
     }
 
     /**
@@ -161,11 +202,9 @@
      * @hide
      */
     public NetworkRegistrationState(int domain, int transportType, int regState,
-                                    int accessNetworkTechnology, int rejectCause,
-                                    boolean emergencyOnly, int[] availableServices,
-                                    @Nullable CellIdentity cellIdentity, boolean cssSupported,
-                                    int roamingIndicator, int systemIsInPrl,
-                                    int defaultRoamingIndicator) {
+            int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
+            int[] availableServices, @Nullable CellIdentity cellIdentity, boolean cssSupported,
+            int roamingIndicator, int systemIsInPrl, int defaultRoamingIndicator) {
         this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
                 availableServices, cellIdentity);
 
@@ -178,13 +217,14 @@
      * @hide
      */
     public NetworkRegistrationState(int domain, int transportType, int regState,
-                                    int accessNetworkTechnology, int rejectCause,
-                                    boolean emergencyOnly, int[] availableServices,
-                                    @Nullable CellIdentity cellIdentity, int maxDataCalls) {
+            int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
+            int[] availableServices, @Nullable CellIdentity cellIdentity, int maxDataCalls,
+            boolean isDcNrRestricted, boolean isNrAvailable) {
         this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
                 availableServices, cellIdentity);
 
-        mDataSpecificStates = new DataSpecificRegistrationStates(maxDataCalls);
+        mDataSpecificStates = new DataSpecificRegistrationStates(
+                maxDataCalls, isDcNrRestricted, isNrAvailable);
     }
 
     protected NetworkRegistrationState(Parcel source) {
@@ -201,6 +241,7 @@
                 VoiceSpecificRegistrationStates.class.getClassLoader());
         mDataSpecificStates = source.readParcelable(
                 DataSpecificRegistrationStates.class.getClassLoader());
+        mNrStatus = source.readInt();
     }
 
     /**
@@ -214,6 +255,19 @@
     public @Domain int getDomain() { return mDomain; }
 
     /**
+     * @return the 5G NR connection status.
+     * @hide
+     */
+    public @NRStatus int getNrStatus() {
+        return mNrStatus;
+    }
+
+    /** @hide */
+    public void setNrStatus(@NRStatus int nrStatus) {
+        mNrStatus = nrStatus;
+    }
+
+    /**
      * @return The registration state.
      */
     public @RegState int getRegState() {
@@ -237,10 +291,9 @@
     }
 
     /**
-     * @return {@link ServiceState.RoamingType roaming type}. This could return
-     * overridden roaming type based on resource overlay or carrier config.
-     * @hide
+     * @return the current network roaming type.
      */
+
     public @ServiceState.RoamingType int getRoamingType() {
         return mRoamingType;
     }
@@ -317,6 +370,19 @@
         return "Unknown reg state " + regState;
     }
 
+    private static String nrStatusToString(@NRStatus int nrStatus) {
+        switch (nrStatus) {
+            case NR_STATUS_RESTRICTED:
+                return "RESTRICTED";
+            case NR_STATUS_NOT_RESTRICTED:
+                return "NOT_RESTRICTED";
+            case NR_STATUS_CONNECTED:
+                return "CONNECTED";
+            default:
+                return "NONE";
+        }
+    }
+
     @Override
     public String toString() {
         return new StringBuilder("NetworkRegistrationState{")
@@ -332,6 +398,7 @@
                 .append(" cellIdentity=").append(mCellIdentity)
                 .append(" voiceSpecificStates=").append(mVoiceSpecificStates)
                 .append(" dataSpecificStates=").append(mDataSpecificStates)
+                .append(" nrStatus=").append(nrStatusToString(mNrStatus))
                 .append("}").toString();
     }
 
@@ -339,14 +406,14 @@
     public int hashCode() {
         return Objects.hash(mDomain, mTransportType, mRegState, mRoamingType,
                 mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
-                mCellIdentity, mVoiceSpecificStates, mDataSpecificStates);
+                mCellIdentity, mVoiceSpecificStates, mDataSpecificStates, mNrStatus);
     }
 
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
 
-        if (o == null || !(o instanceof NetworkRegistrationState)) {
+        if (!(o instanceof NetworkRegistrationState)) {
             return false;
         }
 
@@ -358,11 +425,11 @@
                 && mAccessNetworkTechnology == other.mAccessNetworkTechnology
                 && mRejectCause == other.mRejectCause
                 && mEmergencyOnly == other.mEmergencyOnly
-                && (mAvailableServices == other.mAvailableServices
-                    || Arrays.equals(mAvailableServices, other.mAvailableServices))
-                && equals(mCellIdentity, other.mCellIdentity)
-                && equals(mVoiceSpecificStates, other.mVoiceSpecificStates)
-                && equals(mDataSpecificStates, other.mDataSpecificStates);
+                && Arrays.equals(mAvailableServices, other.mAvailableServices)
+                && Objects.equals(mCellIdentity, other.mCellIdentity)
+                && Objects.equals(mVoiceSpecificStates, other.mVoiceSpecificStates)
+                && Objects.equals(mDataSpecificStates, other.mDataSpecificStates)
+                && mNrStatus == other.mNrStatus;
     }
 
     @Override
@@ -378,6 +445,7 @@
         dest.writeParcelable(mCellIdentity, 0);
         dest.writeParcelable(mVoiceSpecificStates, 0);
         dest.writeParcelable(mDataSpecificStates, 0);
+        dest.writeInt(mNrStatus);
     }
 
     public static final Parcelable.Creator<NetworkRegistrationState> CREATOR =
@@ -392,14 +460,4 @@
             return new NetworkRegistrationState[size];
         }
     };
-
-    private static boolean equals(Object o1, Object o2) {
-        if (o1 == o2) {
-            return true;
-        } else if (o1 == null) {
-            return false;
-        } else {
-            return o1.equals(o2);
-        }
-    }
 }
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 97b1bdc..3c5ad84 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -16,19 +16,23 @@
 
 package android.telephony;
 
+import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.Looper;
-import android.os.Message;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.IPhoneStateListener;
 
 import java.lang.ref.WeakReference;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * A listener class for monitoring changes in specific telephony states
@@ -201,12 +205,13 @@
     public static final int LISTEN_DATA_CONNECTION_REAL_TIME_INFO           = 0x00002000;
 
     /**
-     * Listen for changes to LTE network state
-     *
-     * @see #onLteNetworkStateChanged
+     * Listen for changes to the SRVCC state of the active call.
+     * @see #onServiceStateChanged(ServiceState)
      * @hide
      */
-    public static final int LISTEN_VOLTE_STATE                              = 0x00004000;
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public static final int LISTEN_SRVCC_STATE_CHANGED                     = 0x00004000;
 
     /**
      * Listen for OEM hook raw event
@@ -228,34 +233,35 @@
     public static final int LISTEN_CARRIER_NETWORK_CHANGE                   = 0x00010000;
 
     /**
-     *  Listen for changes to the sim voice activation state
-     *  @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
-     *  @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
-     *  @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
-     *  @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
-     *  @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
-     *  {@more}
-     *  Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates voice service has been
-     *  fully activated
+     * Listen for changes to the sim voice activation state
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
+     * {@more}
+     * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates voice service has been
+     * fully activated
      *
-     *  @see #onVoiceActivationStateChanged
-     *  @hide
+     * @see #onVoiceActivationStateChanged
+     * @hide
      */
+    @SystemApi
     public static final int LISTEN_VOICE_ACTIVATION_STATE                   = 0x00020000;
 
     /**
-     *  Listen for changes to the sim data activation state
-     *  @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
-     *  @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
-     *  @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
-     *  @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
-     *  @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
-     *  {@more}
-     *  Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been
-     *  fully activated
+     * Listen for changes to the sim data activation state
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
+     * {@more}
+     * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been
+     * fully activated
      *
-     *  @see #onDataActivationStateChanged
-     *  @hide
+     * @see #onDataActivationStateChanged
+     * @hide
      */
     public static final int LISTEN_DATA_ACTIVATION_STATE                   = 0x00040000;
 
@@ -317,7 +323,12 @@
     @UnsupportedAppUsage
     protected Integer mSubId;
 
-    private final Handler mHandler;
+    /**
+     * @hide
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    @UnsupportedAppUsage
+    public final IPhoneStateListener callback;
 
     /**
      * Create a PhoneStateListener for the Phone with the default subscription.
@@ -355,95 +366,27 @@
      */
     @UnsupportedAppUsage
     public PhoneStateListener(Integer subId, Looper looper) {
-        if (DBG) log("ctor: subId=" + subId + " looper=" + looper);
+        this(subId, new HandlerExecutor(new Handler(looper)));
+    }
+
+    /**
+     * Create a PhoneStateListener for the Phone using the specified Executor
+     *
+     * <p>Create a PhoneStateListener with a specified Executor for handling necessary callbacks.
+     * The Executor must not be null.
+     *
+     * @param executor a non-null Executor that will execute callbacks for the PhoneStateListener.
+     */
+    public PhoneStateListener(@NonNull Executor executor) {
+        this(null, executor);
+    }
+
+    private PhoneStateListener(Integer subId, Executor e) {
+        if (e == null) {
+            throw new IllegalArgumentException("PhoneStateListener Executor must be non-null");
+        }
         mSubId = subId;
-        mHandler = new Handler(looper) {
-            public void handleMessage(Message msg) {
-                if (DBG) {
-                    log("mSubId=" + mSubId + " what=0x" + Integer.toHexString(msg.what)
-                            + " msg=" + msg);
-                }
-                switch (msg.what) {
-                    case LISTEN_SERVICE_STATE:
-                        PhoneStateListener.this.onServiceStateChanged((ServiceState)msg.obj);
-                        break;
-                    case LISTEN_SIGNAL_STRENGTH:
-                        PhoneStateListener.this.onSignalStrengthChanged(msg.arg1);
-                        break;
-                    case LISTEN_MESSAGE_WAITING_INDICATOR:
-                        PhoneStateListener.this.onMessageWaitingIndicatorChanged(msg.arg1 != 0);
-                        break;
-                    case LISTEN_CALL_FORWARDING_INDICATOR:
-                        PhoneStateListener.this.onCallForwardingIndicatorChanged(msg.arg1 != 0);
-                        break;
-                    case LISTEN_CELL_LOCATION:
-                        PhoneStateListener.this.onCellLocationChanged((CellLocation)msg.obj);
-                        break;
-                    case LISTEN_CALL_STATE:
-                        PhoneStateListener.this.onCallStateChanged(msg.arg1, (String)msg.obj);
-                        break;
-                    case LISTEN_DATA_CONNECTION_STATE:
-                        PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1, msg.arg2);
-                        PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1);
-                        break;
-                    case LISTEN_DATA_ACTIVITY:
-                        PhoneStateListener.this.onDataActivity(msg.arg1);
-                        break;
-                    case LISTEN_SIGNAL_STRENGTHS:
-                        PhoneStateListener.this.onSignalStrengthsChanged((SignalStrength)msg.obj);
-                        break;
-                    case LISTEN_OTASP_CHANGED:
-                        PhoneStateListener.this.onOtaspChanged(msg.arg1);
-                        break;
-                    case LISTEN_CELL_INFO:
-                        PhoneStateListener.this.onCellInfoChanged((List<CellInfo>)msg.obj);
-                        break;
-                    case LISTEN_PRECISE_CALL_STATE:
-                        PhoneStateListener.this.onPreciseCallStateChanged((PreciseCallState)msg.obj);
-                        break;
-                    case LISTEN_PRECISE_DATA_CONNECTION_STATE:
-                        PhoneStateListener.this.onPreciseDataConnectionStateChanged(
-                                (PreciseDataConnectionState)msg.obj);
-                        break;
-                    case LISTEN_DATA_CONNECTION_REAL_TIME_INFO:
-                        PhoneStateListener.this.onDataConnectionRealTimeInfoChanged(
-                                (DataConnectionRealTimeInfo)msg.obj);
-                        break;
-                    case LISTEN_VOLTE_STATE:
-                        PhoneStateListener.this.onVoLteServiceStateChanged((VoLteServiceState)msg.obj);
-                        break;
-                    case LISTEN_VOICE_ACTIVATION_STATE:
-                        PhoneStateListener.this.onVoiceActivationStateChanged((int)msg.obj);
-                        break;
-                    case LISTEN_DATA_ACTIVATION_STATE:
-                        PhoneStateListener.this.onDataActivationStateChanged((int)msg.obj);
-                        break;
-                    case LISTEN_USER_MOBILE_DATA_STATE:
-                        PhoneStateListener.this.onUserMobileDataStateChanged((boolean)msg.obj);
-                        break;
-                    case LISTEN_OEM_HOOK_RAW_EVENT:
-                        PhoneStateListener.this.onOemHookRawEvent((byte[])msg.obj);
-                        break;
-                    case LISTEN_CARRIER_NETWORK_CHANGE:
-                        PhoneStateListener.this.onCarrierNetworkChange((boolean)msg.obj);
-                        break;
-                    case LISTEN_PHYSICAL_CHANNEL_CONFIGURATION:
-                        PhoneStateListener.this.onPhysicalChannelConfigurationChanged(
-                                (List<PhysicalChannelConfig>)msg.obj);
-                        break;
-                    case LISTEN_PHONE_CAPABILITY_CHANGE:
-                        PhoneStateListener.this.onPhoneCapabilityChanged(
-                                (PhoneCapability) msg.obj);
-                        break;
-                    case LISTEN_PREFERRED_DATA_SUBID_CHANGE:
-                        PhoneStateListener.this.onPreferredDataSubIdChanged((int) msg.obj);
-                        break;
-                    case LISTEN_RADIO_POWER_STATE_CHANGED:
-                        PhoneStateListener.this.onRadioPowerStateChanged((int) msg.obj);
-                        break;
-                }
-            }
-        };
+        callback = new IPhoneStateListenerStub(this, e);
     }
 
     /**
@@ -613,13 +556,13 @@
     }
 
     /**
-     * Callback invoked when the service state of LTE network
-     * related to the VoLTE service has changed.
-     * @param stateInfo is the current LTE network information
+     * Callback invoked when there has been a change in the Single Radio Voice Call Continuity
+     * (SRVCC) state for the currently active call.
      * @hide
      */
-    @UnsupportedAppUsage
-    public void onVoLteServiceStateChanged(VoLteServiceState stateInfo) {
+    @SystemApi
+    public void onSrvccStateChanged(@TelephonyManager.SrvccState int srvccState) {
+
     }
 
     /**
@@ -627,8 +570,8 @@
      * @param state is the current SIM voice activation state
      * @hide
      */
-    public void onVoiceActivationStateChanged(int state) {
-
+    @SystemApi
+    public void onVoiceActivationStateChanged(@TelephonyManager.SimActivationState int state) {
     }
 
     /**
@@ -636,8 +579,7 @@
      * @param state is the current SIM data activation state
      * @hide
      */
-    public void onDataActivationStateChanged(int state) {
-
+    public void onDataActivationStateChanged(@TelephonyManager.SimActivationState int state) {
     }
 
     /**
@@ -732,125 +674,215 @@
      */
     private static class IPhoneStateListenerStub extends IPhoneStateListener.Stub {
         private WeakReference<PhoneStateListener> mPhoneStateListenerWeakRef;
+        private Executor mExecutor;
 
-        public IPhoneStateListenerStub(PhoneStateListener phoneStateListener) {
+        IPhoneStateListenerStub(PhoneStateListener phoneStateListener, Executor executor) {
             mPhoneStateListenerWeakRef = new WeakReference<PhoneStateListener>(phoneStateListener);
-        }
-
-        private void send(int what, int arg1, int arg2, Object obj) {
-            PhoneStateListener listener = mPhoneStateListenerWeakRef.get();
-            if (listener != null) {
-                Message.obtain(listener.mHandler, what, arg1, arg2, obj).sendToTarget();
-            }
+            mExecutor = executor;
         }
 
         public void onServiceStateChanged(ServiceState serviceState) {
-            send(LISTEN_SERVICE_STATE, 0, 0, serviceState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onServiceStateChanged(serviceState)));
         }
 
         public void onSignalStrengthChanged(int asu) {
-            send(LISTEN_SIGNAL_STRENGTH, asu, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onSignalStrengthChanged(asu)));
         }
 
         public void onMessageWaitingIndicatorChanged(boolean mwi) {
-            send(LISTEN_MESSAGE_WAITING_INDICATOR, mwi ? 1 : 0, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onMessageWaitingIndicatorChanged(mwi)));
         }
 
         public void onCallForwardingIndicatorChanged(boolean cfi) {
-            send(LISTEN_CALL_FORWARDING_INDICATOR, cfi ? 1 : 0, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCallForwardingIndicatorChanged(cfi)));
         }
 
         public void onCellLocationChanged(Bundle bundle) {
             CellLocation location = CellLocation.newFromBundle(bundle);
-            send(LISTEN_CELL_LOCATION, 0, 0, location);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCellLocationChanged(location)));
         }
 
         public void onCallStateChanged(int state, String incomingNumber) {
-            send(LISTEN_CALL_STATE, state, 0, incomingNumber);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCallStateChanged(state, incomingNumber)));
         }
 
         public void onDataConnectionStateChanged(int state, int networkType) {
-            send(LISTEN_DATA_CONNECTION_STATE, state, networkType, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onDataConnectionStateChanged(state, networkType)));
         }
 
         public void onDataActivity(int direction) {
-            send(LISTEN_DATA_ACTIVITY, direction, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onDataActivity(direction)));
         }
 
         public void onSignalStrengthsChanged(SignalStrength signalStrength) {
-            send(LISTEN_SIGNAL_STRENGTHS, 0, 0, signalStrength);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onSignalStrengthsChanged(signalStrength)));
         }
 
         public void onOtaspChanged(int otaspMode) {
-            send(LISTEN_OTASP_CHANGED, otaspMode, 0, null);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onOtaspChanged(otaspMode)));
         }
 
         public void onCellInfoChanged(List<CellInfo> cellInfo) {
-            send(LISTEN_CELL_INFO, 0, 0, cellInfo);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCellInfoChanged(cellInfo)));
         }
 
         public void onPreciseCallStateChanged(PreciseCallState callState) {
-            send(LISTEN_PRECISE_CALL_STATE, 0, 0, callState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onPreciseCallStateChanged(callState)));
         }
 
         public void onPreciseDataConnectionStateChanged(
                 PreciseDataConnectionState dataConnectionState) {
-            send(LISTEN_PRECISE_DATA_CONNECTION_STATE, 0, 0, dataConnectionState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onPreciseDataConnectionStateChanged(dataConnectionState)));
         }
 
-        public void onDataConnectionRealTimeInfoChanged(
-                DataConnectionRealTimeInfo dcRtInfo) {
-            send(LISTEN_DATA_CONNECTION_REAL_TIME_INFO, 0, 0, dcRtInfo);
+        public void onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo dcRtInfo) {
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onDataConnectionRealTimeInfoChanged(dcRtInfo)));
         }
 
-        public void onVoLteServiceStateChanged(VoLteServiceState lteState) {
-            send(LISTEN_VOLTE_STATE, 0, 0, lteState);
+        public void onSrvccStateChanged(int state) {
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onSrvccStateChanged(state)));
         }
 
         public void onVoiceActivationStateChanged(int activationState) {
-            send(LISTEN_VOICE_ACTIVATION_STATE, 0, 0, activationState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onVoiceActivationStateChanged(activationState)));
         }
 
         public void onDataActivationStateChanged(int activationState) {
-            send(LISTEN_DATA_ACTIVATION_STATE, 0, 0, activationState);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onDataActivationStateChanged(activationState)));
         }
 
         public void onUserMobileDataStateChanged(boolean enabled) {
-            send(LISTEN_USER_MOBILE_DATA_STATE, 0, 0, enabled);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onUserMobileDataStateChanged(enabled)));
         }
 
         public void onOemHookRawEvent(byte[] rawData) {
-            send(LISTEN_OEM_HOOK_RAW_EVENT, 0, 0, rawData);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onOemHookRawEvent(rawData)));
         }
 
         public void onCarrierNetworkChange(boolean active) {
-            send(LISTEN_CARRIER_NETWORK_CHANGE, 0, 0, active);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onCarrierNetworkChange(active)));
         }
 
         public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
-            send(LISTEN_PHYSICAL_CHANNEL_CONFIGURATION, 0, 0, configs);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(
+                            () -> psl.onPhysicalChannelConfigurationChanged(configs)));
         }
 
         public void onPhoneCapabilityChanged(PhoneCapability capability) {
-            send(LISTEN_PHONE_CAPABILITY_CHANGE, 0, 0, capability);
-        }
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
 
-        public void onPreferredDataSubIdChanged(int subId) {
-            send(LISTEN_PREFERRED_DATA_SUBID_CHANGE, 0, 0, subId);
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onPhoneCapabilityChanged(capability)));
         }
 
         public void onRadioPowerStateChanged(@TelephonyManager.RadioPowerState int state) {
-            send(LISTEN_RADIO_POWER_STATE_CHANGED, 0, 0, state);
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onRadioPowerStateChanged(state)));
         }
 
+        public void onPreferredDataSubIdChanged(int subId) {
+            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+            if (psl == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> psl.onPreferredDataSubIdChanged(subId)));
+        }
     }
 
-    /**
-     * @hide
-     */
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    @UnsupportedAppUsage
-    public final IPhoneStateListener callback = new IPhoneStateListenerStub(this);
 
     private void log(String s) {
         Rlog.d(LOG_TAG, s);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index c407681..ab80e25 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -83,7 +83,45 @@
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({DUPLEX_MODE_UNKNOWN, DUPLEX_MODE_FDD, DUPLEX_MODE_TDD})
+    @IntDef(prefix = "FREQUENCY_RANGE_",
+            value = {FREQUENCY_RANGE_UNKNOWN, FREQUENCY_RANGE_LOW, FREQUENCY_RANGE_MID,
+                    FREQUENCY_RANGE_HIGH, FREQUENCY_RANGE_MMWAVE})
+    public @interface FrequencyRange {}
+
+    /**
+     * Indicates frequency range is unknown.
+     * @hide
+     */
+    public static final int FREQUENCY_RANGE_UNKNOWN = -1;
+
+    /**
+     * Indicates the frequency range is below 1GHz.
+     * @hide
+     */
+    public static final int FREQUENCY_RANGE_LOW = 1;
+
+    /**
+     * Indicates the frequency range is between 1GHz to 3GHz.
+     * @hide
+     */
+    public static final int FREQUENCY_RANGE_MID = 2;
+
+    /**
+     * Indicates the frequency range is between 3GHz and 6GHz.
+     * @hide
+     */
+    public static final int FREQUENCY_RANGE_HIGH = 3;
+
+    /**
+     * Indicates the frequency range is above 6GHz (millimeter wave frequency).
+     * @hide
+     */
+    public static final int FREQUENCY_RANGE_MMWAVE = 4;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "DUPLEX_MODE_",
+            value = {DUPLEX_MODE_UNKNOWN, DUPLEX_MODE_FDD, DUPLEX_MODE_TDD})
     public @interface DuplexMode {}
 
     /**
@@ -211,29 +249,30 @@
             ROAMING_TYPE_INTERNATIONAL
     })
     public @interface RoamingType {}
+
     /**
-     * Roaming type
-     * HOME : in home network
+     * Not roaming, registered in home network.
      * @hide
      */
+    @SystemApi
     public static final int ROAMING_TYPE_NOT_ROAMING = 0;
     /**
-     * Roaming type
-     * UNKNOWN : in a roaming network, but we can not tell if it's domestic or international
+     * registered in a roaming network, but can not tell if it's domestic or international.
      * @hide
      */
+    @SystemApi
     public static final int ROAMING_TYPE_UNKNOWN = 1;
     /**
-     * Roaming type
-     * DOMESTIC : in domestic roaming network
+     * registered in a domestic roaming network
      * @hide
      */
+    @SystemApi
     public static final int ROAMING_TYPE_DOMESTIC = 2;
     /**
-     * Roaming type
-     * INTERNATIONAL : in international roaming network
+     * registered in an international roaming network
      * @hide
      */
+    @SystemApi
     public static final int ROAMING_TYPE_INTERNATIONAL = 3;
 
     /**
@@ -282,6 +321,8 @@
     @UnsupportedAppUsage
     private boolean mIsUsingCarrierAggregation;
 
+    @FrequencyRange
+    private int mNrFrequencyRange;
     private int mChannelNumber;
     private int[] mCellBandwidths = new int[0];
 
@@ -374,6 +415,7 @@
         mLteEarfcnRsrpBoost = s.mLteEarfcnRsrpBoost;
         mNetworkRegistrationStates = s.mNetworkRegistrationStates == null ? null :
                 new ArrayList<>(s.mNetworkRegistrationStates);
+        mNrFrequencyRange = s.mNrFrequencyRange;
     }
 
     /**
@@ -405,6 +447,7 @@
         in.readList(mNetworkRegistrationStates, NetworkRegistrationState.class.getClassLoader());
         mChannelNumber = in.readInt();
         mCellBandwidths = in.createIntArray();
+        mNrFrequencyRange = in.readInt();
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -432,6 +475,7 @@
         out.writeList(mNetworkRegistrationStates);
         out.writeInt(mChannelNumber);
         out.writeIntArray(mCellBandwidths);
+        out.writeInt(mNrFrequencyRange);
     }
 
     public int describeContents() {
@@ -791,7 +835,8 @@
                 mIsEmergencyOnly,
                 mIsUsingCarrierAggregation,
                 mLteEarfcnRsrpBoost,
-                mNetworkRegistrationStates);
+                mNetworkRegistrationStates,
+                mNrFrequencyRange);
     }
 
     @Override
@@ -822,7 +867,8 @@
                 && mIsUsingCarrierAggregation == s.mIsUsingCarrierAggregation)
                 && (mNetworkRegistrationStates == null ? s.mNetworkRegistrationStates == null :
                         s.mNetworkRegistrationStates != null &&
-                        mNetworkRegistrationStates.containsAll(s.mNetworkRegistrationStates));
+                        mNetworkRegistrationStates.containsAll(s.mNetworkRegistrationStates))
+                && mNrFrequencyRange == s.mNrFrequencyRange;
     }
 
     /**
@@ -957,6 +1003,7 @@
             .append(", mIsUsingCarrierAggregation=").append(mIsUsingCarrierAggregation)
             .append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
             .append(", mNetworkRegistrationStates=").append(mNetworkRegistrationStates)
+            .append(", mNrFrequencyRange=").append(mNrFrequencyRange)
             .append("}").toString();
     }
 
@@ -986,6 +1033,7 @@
         mIsUsingCarrierAggregation = false;
         mLteEarfcnRsrpBoost = 0;
         mNetworkRegistrationStates = new ArrayList<>();
+        mNrFrequencyRange = FREQUENCY_RANGE_UNKNOWN;
     }
 
     public void setStateOutOfService() {
@@ -1224,6 +1272,7 @@
         m.putInt("LteEarfcnRsrpBoost", mLteEarfcnRsrpBoost);
         m.putInt("ChannelNumber", mChannelNumber);
         m.putIntArray("CellBandwidths", mCellBandwidths);
+        m.putInt("mNrFrequencyRange", mNrFrequencyRange);
     }
 
     /** @hide */
@@ -1287,6 +1336,22 @@
         mIsUsingCarrierAggregation = ca;
     }
 
+    /**
+     * @return the frequency range of 5G NR.
+     * @hide
+     */
+    public @FrequencyRange int getNrFrequencyRange() {
+        return mNrFrequencyRange;
+    }
+
+    /**
+     * @param nrFrequencyRange the frequency range of 5G NR.
+     * @hide
+     */
+    public void setNrFrequencyRange(@FrequencyRange int nrFrequencyRange) {
+        mNrFrequencyRange = nrFrequencyRange;
+    }
+
     /** @hide */
     public int getLteEarfcnRsrpBoost() {
         return mLteEarfcnRsrpBoost;
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index bc832c3..240b8a9 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -17,12 +17,12 @@
 package android.telephony;
 
 import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.CarrierConfigManager;
 import android.util.Log;
-import android.content.res.Resources;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -37,25 +37,25 @@
     private static final boolean DBG = false;
 
     /** @hide */
-    @UnsupportedAppUsage
-    public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN
-            = TelephonyProtoEnums.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; // = 0
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN =
+            CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; // = 0
     /** @hide */
-    @UnsupportedAppUsage
-    public static final int SIGNAL_STRENGTH_POOR
-            = TelephonyProtoEnums.SIGNAL_STRENGTH_POOR; // = 1
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    public static final int SIGNAL_STRENGTH_POOR =
+            CellSignalStrength.SIGNAL_STRENGTH_POOR; // = 1
     /** @hide */
-    @UnsupportedAppUsage
-    public static final int SIGNAL_STRENGTH_MODERATE
-            = TelephonyProtoEnums.SIGNAL_STRENGTH_MODERATE; // = 2
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    public static final int SIGNAL_STRENGTH_MODERATE =
+            CellSignalStrength.SIGNAL_STRENGTH_MODERATE; // = 2
     /** @hide */
-    @UnsupportedAppUsage
-    public static final int SIGNAL_STRENGTH_GOOD
-            = TelephonyProtoEnums.SIGNAL_STRENGTH_GOOD; // = 3
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    public static final int SIGNAL_STRENGTH_GOOD =
+            CellSignalStrength.SIGNAL_STRENGTH_GOOD; // = 3
     /** @hide */
-    @UnsupportedAppUsage
-    public static final int SIGNAL_STRENGTH_GREAT
-            = TelephonyProtoEnums.SIGNAL_STRENGTH_GREAT; // = 4
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    public static final int SIGNAL_STRENGTH_GREAT =
+            CellSignalStrength.SIGNAL_STRENGTH_GREAT; // = 4
     /** @hide */
     @UnsupportedAppUsage
     public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 22c1e58..b41e14e 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -143,9 +143,11 @@
     private boolean mIsOpportunistic;
 
     /**
-     * SubId of the parent subscription, if there is one.
+     * A UUID assigned to the subscription group. It returns
+     * null if not assigned.
      */
-    private int mParentSubId;
+    @Nullable
+    private String mGroupUUID;
 
     /**
      * @hide
@@ -156,7 +158,7 @@
             @Nullable UiccAccessRule[] accessRules, String cardId) {
         this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
                 roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardId,
-                false, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+                false, null);
     }
 
     /**
@@ -166,7 +168,7 @@
             CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
             Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
             @Nullable UiccAccessRule[] accessRules, String cardId, boolean isOpportunistic,
-            int parentSubId) {
+            @Nullable String groupUUID) {
         this.mId = id;
         this.mIccId = iccId;
         this.mSimSlotIndex = simSlotIndex;
@@ -184,7 +186,7 @@
         this.mAccessRules = accessRules;
         this.mCardId = cardId;
         this.mIsOpportunistic = isOpportunistic;
-        this.mParentSubId = parentSubId;
+        this.mGroupUUID = groupUUID;
     }
 
     /**
@@ -388,16 +390,16 @@
     }
 
     /**
-     * Used in scenarios where a child subscription is bundled with a primary parent subscription.
-     * The child subscription will typically be opportunistic (see {@link #isOpportunistic()})
-     * and will be used to provide data services where available, with the parent being the primary
-     * fallback subscription.
+     * Used in scenarios where different subscriptions are bundled as a group.
+     * It's typically a primary and an opportunistic subscription. (see {@link #isOpportunistic()})
+     * Such that those subscriptions will have some affiliated behaviors such as opportunistic
+     * subscription may be invisible to the user.
      *
-     * @return subId of parent subscription if it’s bundled with a primary subscription.
-     * If there isn't one, {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}
+     * @return group UUID a String of group UUID if it belongs to a group. Otherwise
+     * it will return null.
      */
-    public int getParentSubId() {
-        return mParentSubId;
+    public String getGroupUuid() {
+        return mGroupUUID;
     }
 
     /**
@@ -493,11 +495,11 @@
             UiccAccessRule[] accessRules = source.createTypedArray(UiccAccessRule.CREATOR);
             String cardId = source.readString();
             boolean isOpportunistic = source.readBoolean();
-            int parentSubId = source.readInt();
+            String groupUUID = source.readString();
 
             return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
                     nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
-                    isEmbedded, accessRules, cardId, isOpportunistic, parentSubId);
+                    isEmbedded, accessRules, cardId, isOpportunistic, groupUUID);
         }
 
         @Override
@@ -525,7 +527,7 @@
         dest.writeTypedArray(mAccessRules, flags);
         dest.writeString(mCardId);
         dest.writeBoolean(mIsOpportunistic);
-        dest.writeInt(mParentSubId);
+        dest.writeString(mGroupUUID);
     }
 
     @Override
@@ -559,13 +561,13 @@
                 + " mnc " + mMnc + "mCountryIso=" + mCountryIso + " isEmbedded " + mIsEmbedded
                 + " accessRules " + Arrays.toString(mAccessRules)
                 + " cardId=" + cardIdToPrint + " isOpportunistic " + mIsOpportunistic
-                + " parentSubId=" + mParentSubId + "}";
+                + " mGroupUUID=" + mGroupUUID + "}";
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
-                mIsOpportunistic, mParentSubId, mIccId, mNumber, mMcc, mMnc, mCountryIso,
+                mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc, mCountryIso,
                 mCardId, mDisplayName, mCarrierName, mAccessRules);
     }
 
@@ -588,7 +590,7 @@
                 && mDataRoaming == toCompare.mDataRoaming
                 && mIsEmbedded == toCompare.mIsEmbedded
                 && mIsOpportunistic == toCompare.mIsOpportunistic
-                && mParentSubId == toCompare.mParentSubId
+                && Objects.equals(mGroupUUID, toCompare.mGroupUUID)
                 && Objects.equals(mIccId, toCompare.mIccId)
                 && Objects.equals(mNumber, toCompare.mNumber)
                 && Objects.equals(mMcc, toCompare.mMcc)
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 0ba18ee..a6fa6bf 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -51,6 +51,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.euicc.EuiccManager;
+import android.telephony.ims.ImsMmTelManager;
 import android.util.DisplayMetrics;
 import android.util.Log;
 
@@ -118,7 +119,6 @@
     @UnsupportedAppUsage
     public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
 
-
     /**
      * Generates a content {@link Uri} used to receive updates on simInfo change
      * on the given subscriptionId
@@ -134,7 +134,7 @@
      * A content {@link Uri} used to receive updates on wfc enabled user setting.
      * <p>
      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
-     * subscription wfc enabled {@link SubscriptionManager#WFC_IMS_ENABLED}
+     * subscription wfc enabled {@link ImsMmTelManager#isVoWiFiSettingEnabled()}
      * while your app is running. You can also use a {@link JobService} to ensure your app
      * is notified of changes to the {@link Uri} even when it is not running.
      * Note, however, that using a {@link JobService} does not guarantee timely delivery of
@@ -147,10 +147,28 @@
     public static final Uri WFC_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc");
 
     /**
-     * A content {@link Uri} used to receive updates on enhanced 4g user setting.
+     * A content {@link Uri} used to receive updates on advanced calling user setting.
      * <p>
      * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
-     * subscription enhanced 4G enabled {@link SubscriptionManager#ENHANCED_4G_MODE_ENABLED}
+     * subscription advanced calling enabled
+     * {@link ImsMmTelManager#isAdvancedCallingSettingEnabled()} while your app is running.
+     * You can also use a {@link JobService} to ensure your app is notified of changes to the
+     * {@link Uri} even when it is not running.
+     * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+     * updates to the {@link Uri}.
+     * To be notified of changes to a specific subId, append subId to the URI
+     * {@link Uri#withAppendedPath(Uri, String)}.
+     * @hide
+     */
+    @SystemApi
+    public static final Uri ADVANCED_CALLING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
+            CONTENT_URI, "advanced_calling");
+
+    /**
+     * A content {@link Uri} used to receive updates on wfc mode setting.
+     * <p>
+     * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+     * subscription wfc mode {@link ImsMmTelManager#getVoWiFiModeSetting()}
      * while your app is running. You can also use a {@link JobService} to ensure your app
      * is notified of changes to the {@link Uri} even when it is not running.
      * Note, however, that using a {@link JobService} does not guarantee timely delivery of
@@ -160,9 +178,59 @@
      * @hide
      */
     @SystemApi
-    public static final Uri ENHANCED_4G_ENABLED_CONTENT_URI = Uri.withAppendedPath(
-            CONTENT_URI, "enhanced_4g");
+    public static final Uri WFC_MODE_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc_mode");
 
+    /**
+     * A content {@link Uri} used to receive updates on wfc roaming mode setting.
+     * <p>
+     * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+     * subscription wfc roaming mode {@link ImsMmTelManager#getVoWiFiRoamingModeSetting()}
+     * while your app is running. You can also use a {@link JobService} to ensure your app
+     * is notified of changes to the {@link Uri} even when it is not running.
+     * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+     * updates to the {@link Uri}.
+     * To be notified of changes to a specific subId, append subId to the URI
+     * {@link Uri#withAppendedPath(Uri, String)}.
+     * @hide
+     */
+    @SystemApi
+    public static final Uri WFC_ROAMING_MODE_CONTENT_URI = Uri.withAppendedPath(
+            CONTENT_URI, "wfc_roaming_mode");
+
+    /**
+     * A content {@link Uri} used to receive updates on vt(video telephony over IMS) enabled
+     * setting.
+     * <p>
+     * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+     * subscription vt enabled {@link ImsMmTelManager#isVtSettingEnabled()}
+     * while your app is running. You can also use a {@link JobService} to ensure your app
+     * is notified of changes to the {@link Uri} even when it is not running.
+     * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+     * updates to the {@link Uri}.
+     * To be notified of changes to a specific subId, append subId to the URI
+     * {@link Uri#withAppendedPath(Uri, String)}.
+     * @hide
+     */
+    @SystemApi
+    public static final Uri VT_ENABLED_CONTENT_URI = Uri.withAppendedPath(
+            CONTENT_URI, "vt_enabled");
+
+    /**
+     * A content {@link Uri} used to receive updates on wfc roaming enabled setting.
+     * <p>
+     * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
+     * subscription wfc roaming enabled {@link ImsMmTelManager#isVoWiFiRoamingSettingEnabled()}
+     * while your app is running. You can also use a {@link JobService} to ensure your app
+     * is notified of changes to the {@link Uri} even when it is not running.
+     * Note, however, that using a {@link JobService} does not guarantee timely delivery of
+     * updates to the {@link Uri}.
+     * To be notified of changes to a specific subId, append subId to the URI
+     * {@link Uri#withAppendedPath(Uri, String)}.
+     * @hide
+     */
+    @SystemApi
+    public static final Uri WFC_ROAMING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
+            CONTENT_URI, "wfc_roaming_enabled");
 
     /**
      * TelephonyProvider unique key column name is the subscription id.
@@ -508,6 +576,15 @@
     public static final String PARENT_SUB_ID = "parent_sub_id";
 
     /**
+     * TelephonyProvider column name for group ID. Subscriptions with same group ID
+     * are considered bundled together, and should behave as a single subscription at
+     * certain scenarios.
+     *
+     * @hide
+     */
+    public static final String GROUP_UUID = "group_uuid";
+
+    /**
      * Broadcast Action: The user has changed one of the default subs related to
      * data, phone calls, or sms</p>
      *
@@ -2221,7 +2298,7 @@
      * subscription dynamically in multi-SIM devices.
      *
      * @param subId which subscription is preferred to for cellular data. If it's
-     *              {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}, it means
+     *              {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}, it means
      *              it's unset and {@link SubscriptionManager#getDefaultDataSubscriptionId()}
      *              is used to determine which modem is preferred.
      * @hide
@@ -2296,19 +2373,40 @@
     }
 
     /**
-     * Set parent subId by simInfo index
+     * Inform SubscriptionManager that subscriptions in the list are bundled
+     * as a group. Typically it's a primary subscription and an opportunistic
+     * subscription. It should only affect multi-SIM scenarios where primary
+     * and opportunistic subscriptions can be activated together.
+     * Being in the same group means they might be activated or deactivated
+     * together, some of them may be invisible to the users, etc.
      *
-     * @param parentSubId subId of its parent subscription.
-     * @param subId the unique SubscriptionInfo index in database
-     * @return the number of records updated
-     * @hide
+     * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+     * permission or can manage all subscriptions in the list, according to their
+     * acess rules.
+     *
+     * @param subIdList list of subId that will be in the same group
+     * @return groupUUID a UUID assigned to the subscription group. It returns
+     * null if fails.
      *
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
-    public int setParentSubId(int parentSubId, int subId) {
-        if (VDBG) logd("[setParentSubId]+ parentSubId:" + parentSubId + " subId:" + subId);
-        return setSubscriptionPropertyHelper(subId, "parentSubId",
-                (iSub)-> iSub.setParentSubId(parentSubId, subId));
+    public String setSubscriptionGroup(int[] subIdList) {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        if (VDBG) {
+            logd("[setSubscriptionGroup]+ subIdList:" + Arrays.toString(subIdList));
+        }
+
+        String groupUUID = null;
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                groupUUID = iSub.setSubscriptionGroup(subIdList, pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return groupUUID;
     }
 
     private interface CallISubMethodHelper {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8a77f14..d72b5ec 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -21,6 +21,7 @@
 import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.Manifest;
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -43,6 +44,7 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.BatteryStats;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -52,6 +54,7 @@
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.os.WorkSource;
 import android.provider.Settings.SettingNotFoundException;
 import android.service.carrier.CarrierIdentifier;
 import android.telecom.PhoneAccount;
@@ -181,6 +184,57 @@
     /** @hide */
     static public final int KEY_TYPE_WLAN = 2;
 
+    /**
+     * No Single Radio Voice Call Continuity (SRVCC) handover is active.
+     * See TS 23.216 for more information.
+     * @hide
+     */
+    @SystemApi
+    public static final int SRVCC_STATE_HANDOVER_NONE  = -1;
+
+    /**
+     * Single Radio Voice Call Continuity (SRVCC) handover has been started on the network.
+     * See TS 23.216 for more information.
+     * @hide
+     */
+    @SystemApi
+    public static final int SRVCC_STATE_HANDOVER_STARTED  = 0;
+
+    /**
+     * Ongoing Single Radio Voice Call Continuity (SRVCC) handover has successfully completed.
+     * See TS 23.216 for more information.
+     * @hide
+     */
+    @SystemApi
+    public static final int SRVCC_STATE_HANDOVER_COMPLETED = 1;
+
+    /**
+     * Ongoing Single Radio Voice Call Continuity (SRVCC) handover has failed.
+     * See TS 23.216 for more information.
+     * @hide
+     */
+    @SystemApi
+    public static final int SRVCC_STATE_HANDOVER_FAILED   = 2;
+
+    /**
+     * Ongoing Single Radio Voice Call Continuity (SRVCC) handover has been canceled.
+     * See TS 23.216 for more information.
+     * @hide
+     */
+    @SystemApi
+    public static final int SRVCC_STATE_HANDOVER_CANCELED  = 3;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"SRVCC_STATE_"},
+            value = {
+                    SRVCC_STATE_HANDOVER_NONE,
+                    SRVCC_STATE_HANDOVER_STARTED,
+                    SRVCC_STATE_HANDOVER_COMPLETED,
+                    SRVCC_STATE_HANDOVER_FAILED,
+                    SRVCC_STATE_HANDOVER_CANCELED})
+    public @interface SrvccState {}
+
     private final Context mContext;
     private final int mSubId;
     @UnsupportedAppUsage
@@ -1161,6 +1215,33 @@
             "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED";
 
     /**
+     * Broadcast Action: The subscription precise carrier identity has changed.
+     * Similar like {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED}, this intent will be sent
+     * on the event of {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED}. However, its possible
+     * that precise carrier identity changes while
+     * {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} remains the same e.g, the same
+     * subscription switches to different IMSI could potentially change its precise carrier id.
+     *
+     * The intent will have the following extra values:
+     * <ul>
+     *   <li>{@link #EXTRA_PRECISE_CARRIER_ID} The up-to-date precise carrier id of the
+     *   current subscription.
+     *   </li>
+     *   <li>{@link #EXTRA_PRECISE_CARRIER_NAME} The up-to-date carrier name of the current
+     *   subscription.
+     *   </li>
+     *   <li>{@link #EXTRA_SUBSCRIPTION_ID} The subscription id associated with the changed carrier
+     *   identity.
+     *   </li>
+     * </ul>
+     * <p class="note">This is a protected intent that can only be sent by the system.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED =
+            "android.telephony.action.SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED";
+
+    /**
      * An int extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} which indicates
      * the updated carrier id {@link TelephonyManager#getSimCarrierId()} of
      * the current subscription.
@@ -1189,6 +1270,28 @@
     public static final String EXTRA_CARRIER_NAME = "android.telephony.extra.CARRIER_NAME";
 
     /**
+     * An int extra used with {@link #ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED} which
+     * indicates the updated precise carrier id {@link TelephonyManager#getSimPreciseCarrierId()} of
+     * the current subscription. Note, its possible precise carrier id changes while
+     * {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} remains the same e.g, when
+     * subscription switch to different IMSI.
+     * <p>Will be {@link TelephonyManager#UNKNOWN_CARRIER_ID} if the subscription is unavailable or
+     * the carrier cannot be identified.
+     * @hide
+     */
+    public static final String EXTRA_PRECISE_CARRIER_ID =
+            "android.telephony.extra.PRECISE_CARRIER_ID";
+
+    /**
+     * An string extra used with {@link #ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED} which
+     * indicates the updated precise carrier name of the current subscription.
+     * {@see TelephonyManager#getSimPreciseCarrierIdName()}
+     * <p>it's a user-facing name of the precise carrier id {@link #EXTRA_PRECISE_CARRIER_ID},
+     * @hide
+     */
+    public static final String EXTRA_PRECISE_CARRIER_NAME = "android.telephony.extra.CARRIER_NAME";
+
+    /**
      * An int extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} to indicate the
      * subscription which has changed.
      */
@@ -1285,9 +1388,10 @@
      * Returns the unique device ID, for example, the IMEI for GSM and the MEID
      * or ESN for CDMA phones. Return null if device ID is not available.
      *
-     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
-     * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app
-     * that owns a managed profile on the device; for more details see <a
+     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+     * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+     * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+     * managed profile on the device; for more details see <a
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      *
@@ -1295,7 +1399,7 @@
      * MEID for CDMA.
      */
     @Deprecated
-    @SuppressAutoDoc // No support for device / profile owner.
+    @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getDeviceId() {
         try {
@@ -1314,9 +1418,10 @@
      * Returns the unique device ID of a subscription, for example, the IMEI for
      * GSM and the MEID for CDMA phones. Return null if device ID is not available.
      *
-     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
-     * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app
-     * that owns a managed profile on the device; for more details see <a
+     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+     * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+     * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+     * managed profile on the device; for more details see <a
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      *
@@ -1326,7 +1431,7 @@
      * MEID for CDMA.
      */
     @Deprecated
-    @SuppressAutoDoc // No support for device / profile owner.
+    @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getDeviceId(int slotIndex) {
         // FIXME this assumes phoneId == slotIndex
@@ -1346,13 +1451,14 @@
      * Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
      * available.
      *
-     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
-     * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app
-     * that owns a managed profile on the device; for more details see <a
+     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+     * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+     * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+     * managed profile on the device; for more details see <a
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      */
-    @SuppressAutoDoc // No support for device / profile owner.
+    @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getImei() {
         return getImei(getSlotIndex());
@@ -1362,15 +1468,16 @@
      * Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
      * available.
      *
-     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
-     * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app
-     * that owns a managed profile on the device; for more details see <a
+     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+     * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+     * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+     * managed profile on the device; for more details see <a
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      *
      * @param slotIndex of which IMEI is returned
      */
-    @SuppressAutoDoc // No support for device / profile owner.
+    @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getImei(int slotIndex) {
         ITelephony telephony = getITelephony();
@@ -1415,13 +1522,14 @@
     /**
      * Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
      *
-     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
-     * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app
-     * that owns a managed profile on the device; for more details see <a
+     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+     * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+     * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+     * managed profile on the device; for more details see <a
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      */
-    @SuppressAutoDoc // No support for device / profile owner.
+    @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getMeid() {
         return getMeid(getSlotIndex());
@@ -1430,15 +1538,16 @@
     /**
      * Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
      *
-     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
-     * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app
-     * that owns a managed profile on the device; for more details see <a
+     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+     * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+     * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a
+     * managed profile on the device; for more details see <a
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      *
      * @param slotIndex of which MEID is returned
      */
-    @SuppressAutoDoc // No support for device / profile owner.
+    @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getMeid(int slotIndex) {
         ITelephony telephony = getITelephony();
@@ -2936,7 +3045,7 @@
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      */
-    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getSimSerialNumber() {
          return getSimSerialNumber(getSubId());
@@ -3098,7 +3207,7 @@
      * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
      * access is deprecated and will be removed in a future release.
      */
-    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public String getSubscriberId() {
         return getSubscriberId(getSubId());
@@ -4644,37 +4753,42 @@
     }
 
     /**
-     * Returns all observed cell information from all radios on the
-     * device including the primary and neighboring cells. Calling this method does
-     * not trigger a call to {@link android.telephony.PhoneStateListener#onCellInfoChanged
-     * onCellInfoChanged()}, or change the rate at which
-     * {@link android.telephony.PhoneStateListener#onCellInfoChanged
-     * onCellInfoChanged()} is called.
+     * Requests all available cell information from all radios on the device including the
+     * camped/registered, serving, and neighboring cells.
      *
-     *<p>
-     * The list can include one or more {@link android.telephony.CellInfoGsm CellInfoGsm},
+     * <p>The response can include one or more {@link android.telephony.CellInfoGsm CellInfoGsm},
      * {@link android.telephony.CellInfoCdma CellInfoCdma},
+     * {@link android.telephony.CellInfoTdscdma CellInfoTdscdma},
      * {@link android.telephony.CellInfoLte CellInfoLte}, and
      * {@link android.telephony.CellInfoWcdma CellInfoWcdma} objects, in any combination.
-     * On devices with multiple radios it is typical to see instances of
-     * one or more of any these in the list. In addition, zero, one, or more
-     * of the returned objects may be considered registered; that is, their
+     * It is typical to see instances of one or more of any these in the list. In addition, zero
+     * or more of the returned objects may be considered registered; that is, their
      * {@link android.telephony.CellInfo#isRegistered CellInfo.isRegistered()}
-     * methods may return true.
+     * methods may return true, indicating that the cell is being used or would be used for
+     * signaling communication if necessary.
      *
-     * <p>This method returns valid data for registered cells on devices with
-     * {@link android.content.pm.PackageManager#FEATURE_TELEPHONY}. In cases where only
-     * partial information is available for a particular CellInfo entry, unavailable fields
-     * will be reported as Integer.MAX_VALUE. All reported cells will include at least a
-     * valid set of technology-specific identification info and a power level measurement.
+     * <p>Beginning with {@link android.os.Build.VERSION_CODES#Q Android Q},
+     * if this API results in a change of the cached CellInfo, that change will be reported via
+     * {@link android.telephony.PhoneStateListener#onCellInfoChanged onCellInfoChanged()}.
      *
-     *<p>
-     * This method is preferred over using {@link
+     * <p>Apps targeting {@link android.os.Build.VERSION_CODES#Q Android Q} or higher will no
+     * longer trigger a refresh of the cached CellInfo by invoking this API. Instead, those apps
+     * will receive the latest cached results. Apps targeting
+     * {@link android.os.Build.VERSION_CODES#Q Android Q} or higher that wish to request updated
+     * CellInfo should call
+     * {android.telephony.TelephonyManager#requestCellInfoUpdate requestCellInfoUpdate()} and
+     * listen for responses via {@link android.telephony.PhoneStateListener#onCellInfoChanged
+     * onCellInfoChanged()}.
+     *
+     * <p>This method returns valid data for devices with
+     * {@link android.content.pm.PackageManager#FEATURE_TELEPHONY FEATURE_TELEPHONY}. In cases
+     * where only partial information is available for a particular CellInfo entry, unavailable
+     * fields will be reported as {@link android.telephony.CellInfo#UNAVAILABLE}. All reported
+     * cells will include at least a valid set of technology-specific identification info and a
+     * power level measurement.
+     *
+     * <p>This method is preferred over using {@link
      * android.telephony.TelephonyManager#getCellLocation getCellLocation()}.
-     * However, for older devices, <code>getAllCellInfo()</code> may return
-     * null. In these cases, you should call {@link
-     * android.telephony.TelephonyManager#getCellLocation getCellLocation()}
-     * instead.
      *
      * @return List of {@link android.telephony.CellInfo}; null if cell
      * information is unavailable.
@@ -4685,11 +4799,92 @@
             ITelephony telephony = getITelephony();
             if (telephony == null)
                 return null;
-            return telephony.getAllCellInfo(getOpPackageName());
+            return telephony.getAllCellInfo(
+                    getOpPackageName());
         } catch (RemoteException ex) {
-            return null;
         } catch (NullPointerException ex) {
-            return null;
+        }
+        return null;
+    }
+
+    /** Callback for providing asynchronous {@link CellInfo} on request */
+    public abstract static class CellInfoCallback {
+        /**
+         * Response to
+         * {@link android.telephony.TelephonyManager#requestCellInfoUpdate requestCellInfoUpdate()}.
+         *
+         * <p>Invoked when there is a response to
+         * {@link android.telephony.TelephonyManager#requestCellInfoUpdate requestCellInfoUpdate()}
+         * to provide a list of {@link CellInfo}. If no {@link CellInfo} is available then an empty
+         * list will be provided. If an error occurs, null will be provided.
+         *
+         * @param cellInfo a list of {@link CellInfo}, an empty list, or null.
+         *
+         * {@see android.telephony.TelephonyManager#getAllCellInfo getAllCellInfo()}
+         */
+        public abstract void onCellInfo(List<CellInfo> cellInfo);
+    };
+
+    /**
+     * Requests all available cell information from the current subscription for observed
+     * camped/registered, serving, and neighboring cells.
+     *
+     * <p>Any available results from this request will be provided by calls to
+     * {@link android.telephony.PhoneStateListener#onCellInfoChanged onCellInfoChanged()}
+     * for each active subscription.
+     *
+     * @param executor the executor on which callback will be invoked.
+     * @param callback a callback to receive CellInfo.
+     */
+    @RequiresPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
+    public void requestCellInfoUpdate(
+            @NonNull Executor executor, @NonNull CellInfoCallback callback) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony == null) return;
+            telephony.requestCellInfoUpdate(
+                    getSubId(),
+                    new ICellInfoCallback.Stub() {
+                        public void onCellInfo(List<CellInfo> cellInfo) {
+                            Binder.withCleanCallingIdentity(() ->
+                                    executor.execute(() -> callback.onCellInfo(cellInfo)));
+                        }
+                    }, getOpPackageName());
+
+        } catch (RemoteException ex) {
+        }
+    }
+
+    /**
+     * Requests all available cell information from the current subscription for observed
+     * camped/registered, serving, and neighboring cells.
+     *
+     * <p>Any available results from this request will be provided by calls to
+     * {@link android.telephony.PhoneStateListener#onCellInfoChanged onCellInfoChanged()}
+     * for each active subscription.
+     *
+     * @param workSource the requestor to whom the power consumption for this should be attributed.
+     * @param executor the executor on which callback will be invoked.
+     * @param callback a callback to receive CellInfo.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(allOf = {android.Manifest.permission.ACCESS_COARSE_LOCATION,
+            android.Manifest.permission.MODIFY_PHONE_STATE})
+    public void requestCellInfoUpdate(@NonNull WorkSource workSource,
+            @NonNull @CallbackExecutor Executor executor, @NonNull CellInfoCallback callback) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony == null) return;
+            telephony.requestCellInfoUpdateWithWorkSource(
+                    getSubId(),
+                    new ICellInfoCallback.Stub() {
+                        public void onCellInfo(List<CellInfo> cellInfo) {
+                            Binder.withCleanCallingIdentity(() ->
+                                    executor.execute(() -> callback.onCellInfo(cellInfo)));
+                        }
+                    }, getOpPackageName(), workSource);
+        } catch (RemoteException ex) {
         }
     }
 
@@ -6243,7 +6438,6 @@
 
     /**
      * Set the preferred network type.
-     * Used for device configuration by some CDMA operators.
      *
      * <p>Requires Permission:
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
@@ -8263,6 +8457,62 @@
     }
 
     /**
+     * Returns fine-grained carrier id of the current subscription.
+     *
+     * <p>The precise carrier id can be used to further differentiate a carrier by different
+     * networks, by prepaid v.s.postpaid or even by 4G v.s.3G plan. Each carrier has a unique
+     * carrier id {@link #getSimCarrierId()} but can have multiple precise carrier id. e.g,
+     * {@link #getSimCarrierId()} will always return Tracfone (id 2022) for a Tracfone SIM, while
+     * {@link #getSimPreciseCarrierId()} can return Tracfone AT&T or Tracfone T-Mobile based on the
+     * current subscription IMSI.
+     *
+     * <p>For carriers without any fine-grained carrier ids, return {@link #getSimCarrierId()}
+     * <p>Precise carrier ids are defined in the same way as carrier id
+     * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
+     * except each with a "parent" id linking to its top-level carrier id.
+     *
+     * @return Returns fine-grained carrier id of the current subscription.
+     * Return {@link #UNKNOWN_CARRIER_ID} if the subscription is unavailable or the carrier cannot
+     * be identified.
+     *
+     * @hide
+     */
+    public int getSimPreciseCarrierId() {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.getSubscriptionPreciseCarrierId(getSubId());
+            }
+        } catch (RemoteException ex) {
+            // This could happen if binder process crashes.
+        }
+        return UNKNOWN_CARRIER_ID;
+    }
+
+    /**
+     * Similar like {@link #getSimCarrierIdName()}, returns user-facing name of the
+     * precise carrier id {@link #getSimPreciseCarrierId()}
+     *
+     * <p>The returned name is unlocalized.
+     *
+     * @return user-facing name of the subscription precise carrier id. Return {@code null} if the
+     * subscription is unavailable or the carrier cannot be identified.
+     *
+     * @hide
+     */
+    public CharSequence getSimPreciseCarrierIdName() {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.getSubscriptionPreciseCarrierName(getSubId());
+            }
+        } catch (RemoteException ex) {
+            // This could happen if binder process crashes.
+        }
+        return null;
+    }
+
+    /**
      * Return a list of certs in hex string from loaded carrier privileges access rules.
      *
      * @return a list of certificate in hex string. return {@code null} if there is no certs
@@ -8286,6 +8536,28 @@
     }
 
     /**
+     * Returns MNO carrier id of the current subscription’s MCCMNC.
+     * <p>MNO carrier id can be solely identified by subscription mccmnc. This is mainly used
+     * for MNO fallback when exact carrier id {@link #getSimCarrierId()}
+     * configurations are not found.
+     *
+     * @return MNO carrier id of the current subscription. Return the value same as carrier id
+     * {@link #getSimCarrierId()}, if MNO carrier id cannot be identified.
+     * @hide
+     */
+    public int getSimMNOCarrierId() {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.getSubscriptionMNOCarrierId(getSubId());
+            }
+        } catch (RemoteException ex) {
+            // This could happen if binder process crashes.
+        }
+        return UNKNOWN_CARRIER_ID;
+    }
+
+    /**
      * Return the application ID for the uicc application type like {@link #APPTYPE_CSIM}.
      * All uicc applications are uniquely identified by application ID. See ETSI 102.221 and 101.220
      * <p>Requires Permission:
@@ -9040,7 +9312,7 @@
     public static final int NETWORK_TYPE_BITMASK_LTE_CA = (1 << NETWORK_TYPE_LTE_CA);
 
     /**
-     * @return Modem supported radio access family bitmask {@link NetworkTypeBitMask}
+     * @return Modem supported radio access family bitmask
      *
      * <p>Requires permission: {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or
      * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
@@ -9177,4 +9449,55 @@
         }
         return false;
     }
+
+    /**
+     * Set preferred opportunistic data subscription id.
+     *
+     * <p>Requires that the calling app has carrier privileges on both primary and
+     * secondary subscriptions (see
+     * {@link #hasCarrierPrivileges}), or has permission
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
+     * @param subId which opportunistic subscription
+     * {@link SubscriptionManager#getOpportunisticSubscriptions} is preferred for cellular data.
+     * Pass {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} to unset the preference
+     * @return true if request is accepted, else false.
+     *
+     */
+    public boolean setPreferredOpportunisticDataSubscription(int subId) {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        try {
+            IAns iAlternativeNetworkService = getIAns();
+            if (iAlternativeNetworkService != null) {
+                return iAlternativeNetworkService.setPreferredData(subId, pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "setPreferredData RemoteException", ex);
+        }
+        return false;
+    }
+
+    /**
+     * Get preferred opportunistic data subscription Id
+     *
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}),
+     * or has permission {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}.
+     * @return subId preferred opportunistic subscription id or
+     * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} if there are no preferred
+     * subscription id
+     *
+     */
+    public int getPreferredOpportunisticDataSubscription() {
+        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+        int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        try {
+            IAns iAlternativeNetworkService = getIAns();
+            if (iAlternativeNetworkService != null) {
+                subId = iAlternativeNetworkService.getPreferredData(pkgForDebug);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getPreferredData RemoteException", ex);
+        }
+        return subId;
+    }
 }
diff --git a/telephony/java/android/telephony/VoLteServiceState.java b/telephony/java/android/telephony/VoLteServiceState.java
index 25bb8b4..cf961d0 100644
--- a/telephony/java/android/telephony/VoLteServiceState.java
+++ b/telephony/java/android/telephony/VoLteServiceState.java
@@ -24,9 +24,11 @@
 
 /**
  * Contains LTE network state related information.
- *
+ * @deprecated Only contains SRVCC state, which isn't specific to LTE handovers. For SRVCC
+ * indications, use {@link PhoneStateListener#onSrvccStateChanged(int)}.
  * @hide
  */
+@Deprecated
 public final class VoLteServiceState implements Parcelable {
 
     private static final String LOG_TAG = "VoLteServiceState";
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index aabefe3..4fd7066 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -60,6 +60,7 @@
     private static final String V3_FORMAT_REGEX = "^\\[ApnSettingV3\\]\\s*";
     private static final String V4_FORMAT_REGEX = "^\\[ApnSettingV4\\]\\s*";
     private static final String V5_FORMAT_REGEX = "^\\[ApnSettingV5\\]\\s*";
+    private static final String V6_FORMAT_REGEX = "^\\[ApnSettingV6\\]\\s*";
 
     /**
      * Default value for mtu if it's not set. Moved from PhoneConstants.
@@ -268,6 +269,7 @@
     private final int mApnSetId;
 
     private boolean mPermanentFailed = false;
+    private final int mCarrierId;
 
     /**
      * Returns the MTU size of the mobile interface to which the APN connected.
@@ -596,6 +598,16 @@
         return mMvnoType;
     }
 
+    /**
+     * Returns the carrier id for this APN.
+     *
+     * @see Builder#setCarrierId(int)
+     * @return the carrier id
+     */
+    public int getCarrierId() {
+        return mCarrierId;
+    }
+
     private ApnSetting(Builder builder) {
         this.mEntryName = builder.mEntryName;
         this.mApnName = builder.mApnName;
@@ -623,47 +635,53 @@
         this.mMvnoType = builder.mMvnoType;
         this.mMvnoMatchData = builder.mMvnoMatchData;
         this.mApnSetId = builder.mApnSetId;
+        this.mCarrierId = builder.mCarrierId;
     }
 
-    /** @hide */
+    /**
+     * @hide
+     */
     public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
             String apnName, String proxyAddress, int proxyPort, Uri mmsc,
             String mmsProxyAddress, int mmsProxyPort, String user, String password,
             int authType, int mApnTypeBitmask, int protocol, int roamingProtocol,
-            boolean carrierEnabled, int networkTypeBitmask, int profileId, boolean modemCognitive,
-            int maxConns, int waitTime, int maxConnsTime, int mtu, int mvnoType,
-            String mvnoMatchData, int apnSetId) {
+            boolean carrierEnabled, int networkTypeBitmask, int profileId,
+            boolean modemCognitive, int maxConns, int waitTime, int maxConnsTime, int mtu,
+            int mvnoType, String mvnoMatchData, int apnSetId, int carrierId) {
         return new Builder()
-                .setId(id)
-                .setOperatorNumeric(operatorNumeric)
-                .setEntryName(entryName)
-                .setApnName(apnName)
-                .setProxyAddress(proxyAddress)
-                .setProxyPort(proxyPort)
-                .setMmsc(mmsc)
-                .setMmsProxyAddress(mmsProxyAddress)
-                .setMmsProxyPort(mmsProxyPort)
-                .setUser(user)
-                .setPassword(password)
-                .setAuthType(authType)
-                .setApnTypeBitmask(mApnTypeBitmask)
-                .setProtocol(protocol)
-                .setRoamingProtocol(roamingProtocol)
-                .setCarrierEnabled(carrierEnabled)
-                .setNetworkTypeBitmask(networkTypeBitmask)
-                .setProfileId(profileId)
-                .setModemCognitive(modemCognitive)
-                .setMaxConns(maxConns)
-                .setWaitTime(waitTime)
-                .setMaxConnsTime(maxConnsTime)
-                .setMtu(mtu)
-                .setMvnoType(mvnoType)
-                .setMvnoMatchData(mvnoMatchData)
-                .setApnSetId(apnSetId)
-                .buildWithoutCheck();
+            .setId(id)
+            .setOperatorNumeric(operatorNumeric)
+            .setEntryName(entryName)
+            .setApnName(apnName)
+            .setProxyAddress(proxyAddress)
+            .setProxyPort(proxyPort)
+            .setMmsc(mmsc)
+            .setMmsProxyAddress(mmsProxyAddress)
+            .setMmsProxyPort(mmsProxyPort)
+            .setUser(user)
+            .setPassword(password)
+            .setAuthType(authType)
+            .setApnTypeBitmask(mApnTypeBitmask)
+            .setProtocol(protocol)
+            .setRoamingProtocol(roamingProtocol)
+            .setCarrierEnabled(carrierEnabled)
+            .setNetworkTypeBitmask(networkTypeBitmask)
+            .setProfileId(profileId)
+            .setModemCognitive(modemCognitive)
+            .setMaxConns(maxConns)
+            .setWaitTime(waitTime)
+            .setMaxConnsTime(maxConnsTime)
+            .setMtu(mtu)
+            .setMvnoType(mvnoType)
+            .setMvnoMatchData(mvnoMatchData)
+            .setApnSetId(apnSetId)
+            .setCarrierId(carrierId)
+            .buildWithoutCheck();
     }
 
-    /** @hide */
+    /**
+     * @hide
+     */
     public static ApnSetting makeApnSetting(int id, String operatorNumeric, String entryName,
             String apnName, String proxyAddress, int proxyPort, Uri mmsc,
             String mmsProxyAddress, int mmsProxyPort, String user, String password,
@@ -675,10 +693,12 @@
             mmsc, mmsProxyAddress, mmsProxyPort, user, password, authType, mApnTypeBitmask,
             protocol, roamingProtocol, carrierEnabled, networkTypeBitmask, profileId,
             modemCognitive, maxConns, waitTime, maxConnsTime, mtu, mvnoType, mvnoMatchData,
-            Carriers.NO_SET_SET);
+            Carriers.NO_SET_SET, TelephonyManager.UNKNOWN_CARRIER_ID);
     }
 
-    /** @hide */
+    /**
+     * @hide
+     */
     public static ApnSetting makeApnSetting(Cursor cursor) {
         final int apnTypesBitmask = getApnTypesBitmaskFromString(
                 cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.TYPE)));
@@ -688,60 +708,64 @@
             final int bearerBitmask = cursor.getInt(cursor.getColumnIndexOrThrow(
                     Telephony.Carriers.BEARER_BITMASK));
             networkTypeBitmask =
-                    ServiceState.convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
+                ServiceState.convertBearerBitmaskToNetworkTypeBitmask(bearerBitmask);
         }
 
         return makeApnSetting(
-                cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
-                cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
-                cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
-                cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
-                cursor.getString(
-                        cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)),
-                portFromString(cursor.getString(
-                        cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
-                UriFromString(cursor.getString(
-                        cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
-                cursor.getString(
-                        cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)),
-                portFromString(cursor.getString(
-                        cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
-                cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
-                cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
-                cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
-                apnTypesBitmask,
-                getProtocolIntFromString(
-                    cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL))),
-                getProtocolIntFromString(
-                    cursor.getString(cursor.getColumnIndexOrThrow(
-                        Telephony.Carriers.ROAMING_PROTOCOL))),
-                cursor.getInt(cursor.getColumnIndexOrThrow(
-                        Telephony.Carriers.CARRIER_ENABLED)) == 1,
-                networkTypeBitmask,
-                cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
-                cursor.getInt(cursor.getColumnIndexOrThrow(
-                        Telephony.Carriers.MODEM_COGNITIVE)) == 1,
-                cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNS)),
-                cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME)),
-                cursor.getInt(cursor.getColumnIndexOrThrow(
-                        Telephony.Carriers.MAX_CONNS_TIME)),
-                cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
-                getMvnoTypeIntFromString(
-                    cursor.getString(cursor.getColumnIndexOrThrow(
-                        Telephony.Carriers.MVNO_TYPE))),
+            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers._ID)),
+            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NUMERIC)),
+            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.NAME)),
+            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN)),
+            cursor.getString(
+                cursor.getColumnIndexOrThrow(Telephony.Carriers.PROXY)),
+            portFromString(cursor.getString(
+                cursor.getColumnIndexOrThrow(Telephony.Carriers.PORT))),
+            UriFromString(cursor.getString(
+                cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSC))),
+            cursor.getString(
+                cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPROXY)),
+            portFromString(cursor.getString(
+                cursor.getColumnIndexOrThrow(Telephony.Carriers.MMSPORT))),
+            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.USER)),
+            cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PASSWORD)),
+            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.AUTH_TYPE)),
+            apnTypesBitmask,
+            getProtocolIntFromString(
+                cursor.getString(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROTOCOL))),
+            getProtocolIntFromString(
                 cursor.getString(cursor.getColumnIndexOrThrow(
-                        Telephony.Carriers.MVNO_MATCH_DATA)),
-                cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)));
+                    Telephony.Carriers.ROAMING_PROTOCOL))),
+            cursor.getInt(cursor.getColumnIndexOrThrow(
+                Telephony.Carriers.CARRIER_ENABLED)) == 1,
+            networkTypeBitmask,
+            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
+            cursor.getInt(cursor.getColumnIndexOrThrow(
+                Telephony.Carriers.MODEM_COGNITIVE)) == 1,
+            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNS)),
+            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.WAIT_TIME)),
+            cursor.getInt(cursor.getColumnIndexOrThrow(
+                Telephony.Carriers.MAX_CONNS_TIME)),
+            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MTU)),
+            getMvnoTypeIntFromString(
+                cursor.getString(cursor.getColumnIndexOrThrow(
+                    Telephony.Carriers.MVNO_TYPE))),
+            cursor.getString(cursor.getColumnIndexOrThrow(
+                Telephony.Carriers.MVNO_MATCH_DATA)),
+            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.APN_SET_ID)),
+            cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.CARRIER_ID)));
     }
 
-    /** @hide */
+    /**
+     * @hide
+     */
     public static ApnSetting makeApnSetting(ApnSetting apn) {
         return makeApnSetting(apn.mId, apn.mOperatorNumeric, apn.mEntryName, apn.mApnName,
-                apn.mProxyAddress, apn.mProxyPort, apn.mMmsc, apn.mMmsProxyAddress,
-                apn.mMmsProxyPort, apn.mUser, apn.mPassword, apn.mAuthType, apn.mApnTypeBitmask,
-                apn.mProtocol, apn.mRoamingProtocol, apn.mCarrierEnabled, apn.mNetworkTypeBitmask,
-                apn.mProfileId, apn.mPersistent, apn.mMaxConns, apn.mWaitTime,
-                apn.mMaxConnsTime, apn.mMtu, apn.mMvnoType, apn.mMvnoMatchData, apn.mApnSetId);
+            apn.mProxyAddress, apn.mProxyPort, apn.mMmsc, apn.mMmsProxyAddress,
+            apn.mMmsProxyPort, apn.mUser, apn.mPassword, apn.mAuthType, apn.mApnTypeBitmask,
+            apn.mProtocol, apn.mRoamingProtocol, apn.mCarrierEnabled, apn.mNetworkTypeBitmask,
+            apn.mProfileId, apn.mPersistent, apn.mMaxConns, apn.mWaitTime,
+            apn.mMaxConnsTime, apn.mMtu, apn.mMvnoType, apn.mMvnoMatchData, apn.mApnSetId,
+            apn.mCarrierId);
     }
 
     /**
@@ -783,6 +807,13 @@
      *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
      *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>
      *
+     * v6 format:
+     *   [ApnSettingV6] <carrier>, <apn>, <proxy>, <port>, <user>, <password>, <server>,
+     *   <mmsc>, <mmsproxy>, <mmsport>, <mcc>, <mnc>, <authtype>,
+     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearerBitmask>,
+     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>, <mtu>,
+     *   <mvnoType>, <mvnoMatchData>, <networkTypeBitmask>, <apnSetId>, <carrierId>
+     *
      * Note that the strings generated by {@link #toString()} do not contain the username
      * and password and thus cannot be read by this method.
      *
@@ -795,7 +826,10 @@
 
         int version;
         // matches() operates on the whole string, so append .* to the regex.
-        if (data.matches(V5_FORMAT_REGEX + ".*")) {
+        if (data.matches(V6_FORMAT_REGEX + ".*")) {
+            version = 6;
+            data = data.replaceFirst(V6_FORMAT_REGEX, "");
+        } else if (data.matches(V5_FORMAT_REGEX + ".*")) {
             version = 5;
             data = data.replaceFirst(V5_FORMAT_REGEX, "");
         } else if (data.matches(V4_FORMAT_REGEX + ".*")) {
@@ -837,6 +871,7 @@
         String mvnoType = "";
         String mvnoMatchData = "";
         int apnSetId = Carriers.NO_SET_SET;
+        int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
         if (version == 1) {
             typeArray = new String[a.length - 13];
             System.arraycopy(a, 13, typeArray, 0, a.length - 13);
@@ -880,6 +915,9 @@
             if (a.length > 27) {
                 apnSetId = Integer.parseInt(a[27]);
             }
+            if (a.length > 28) {
+                carrierId = Integer.parseInt(a[28]);
+            }
         }
 
         // If both bearerBitmask and networkTypeBitmask were specified, bearerBitmask would be
@@ -894,7 +932,8 @@
             getApnTypesBitmaskFromString(TextUtils.join(",", typeArray)),
             getProtocolIntFromString(protocol), getProtocolIntFromString(roamingProtocol),
             carrierEnabled, networkTypeBitmask, profileId, modemCognitive, maxConns, waitTime,
-            maxConnsTime, mtu, getMvnoTypeIntFromString(mvnoType), mvnoMatchData, apnSetId);
+            maxConnsTime, mtu, getMvnoTypeIntFromString(mvnoType), mvnoMatchData, apnSetId,
+            carrierId);
     }
 
     /**
@@ -1013,7 +1052,10 @@
 
     // TODO - if we have this function we should also have hashCode.
     // Also should handle changes in type order and perhaps case-insensitivity.
-    /** @hide */
+
+    /**
+     * @hide
+     */
     public boolean equals(Object o) {
         if (o instanceof ApnSetting == false) {
             return false;
@@ -1022,31 +1064,32 @@
         ApnSetting other = (ApnSetting) o;
 
         return mEntryName.equals(other.mEntryName)
-                && Objects.equals(mId, other.mId)
-                && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
-                && Objects.equals(mApnName, other.mApnName)
-                && Objects.equals(mProxyAddress, other.mProxyAddress)
-                && Objects.equals(mMmsc, other.mMmsc)
-                && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
-                && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
-                && Objects.equals(mProxyPort, other.mProxyPort)
-                && Objects.equals(mUser, other.mUser)
-                && Objects.equals(mPassword, other.mPassword)
-                && Objects.equals(mAuthType, other.mAuthType)
-                && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
-                && Objects.equals(mProtocol, other.mProtocol)
-                && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
-                && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
-                && Objects.equals(mProfileId, other.mProfileId)
-                && Objects.equals(mPersistent, other.mPersistent)
-                && Objects.equals(mMaxConns, other.mMaxConns)
-                && Objects.equals(mWaitTime, other.mWaitTime)
-                && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
-                && Objects.equals(mMtu, other.mMtu)
-                && Objects.equals(mMvnoType, other.mMvnoType)
-                && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
-                && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
-                && Objects.equals(mApnSetId, other.mApnSetId);
+            && Objects.equals(mId, other.mId)
+            && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+            && Objects.equals(mApnName, other.mApnName)
+            && Objects.equals(mProxyAddress, other.mProxyAddress)
+            && Objects.equals(mMmsc, other.mMmsc)
+            && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+            && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+            && Objects.equals(mProxyPort, other.mProxyPort)
+            && Objects.equals(mUser, other.mUser)
+            && Objects.equals(mPassword, other.mPassword)
+            && Objects.equals(mAuthType, other.mAuthType)
+            && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
+            && Objects.equals(mProtocol, other.mProtocol)
+            && Objects.equals(mRoamingProtocol, other.mRoamingProtocol)
+            && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+            && Objects.equals(mProfileId, other.mProfileId)
+            && Objects.equals(mPersistent, other.mPersistent)
+            && Objects.equals(mMaxConns, other.mMaxConns)
+            && Objects.equals(mWaitTime, other.mWaitTime)
+            && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+            && Objects.equals(mMtu, other.mMtu)
+            && Objects.equals(mMvnoType, other.mMvnoType)
+            && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
+            && Objects.equals(mNetworkTypeBitmask, other.mNetworkTypeBitmask)
+            && Objects.equals(mApnSetId, other.mApnSetId)
+            && Objects.equals(mCarrierId, other.mCarrierId);
     }
 
     /**
@@ -1069,29 +1112,30 @@
         ApnSetting other = (ApnSetting) o;
 
         return mEntryName.equals(other.mEntryName)
-                && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
-                && Objects.equals(mApnName, other.mApnName)
-                && Objects.equals(mProxyAddress, other.mProxyAddress)
-                && Objects.equals(mMmsc, other.mMmsc)
-                && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
-                && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
-                && Objects.equals(mProxyPort, other.mProxyPort)
-                && Objects.equals(mUser, other.mUser)
-                && Objects.equals(mPassword, other.mPassword)
-                && Objects.equals(mAuthType, other.mAuthType)
-                && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
-                && (isDataRoaming || Objects.equals(mProtocol, other.mProtocol))
-                && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
-                && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
-                && Objects.equals(mProfileId, other.mProfileId)
-                && Objects.equals(mPersistent, other.mPersistent)
-                && Objects.equals(mMaxConns, other.mMaxConns)
-                && Objects.equals(mWaitTime, other.mWaitTime)
-                && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
-                && Objects.equals(mMtu, other.mMtu)
-                && Objects.equals(mMvnoType, other.mMvnoType)
-                && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
-                && Objects.equals(mApnSetId, other.mApnSetId);
+            && Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
+            && Objects.equals(mApnName, other.mApnName)
+            && Objects.equals(mProxyAddress, other.mProxyAddress)
+            && Objects.equals(mMmsc, other.mMmsc)
+            && Objects.equals(mMmsProxyAddress, other.mMmsProxyAddress)
+            && Objects.equals(mMmsProxyPort, other.mMmsProxyPort)
+            && Objects.equals(mProxyPort, other.mProxyPort)
+            && Objects.equals(mUser, other.mUser)
+            && Objects.equals(mPassword, other.mPassword)
+            && Objects.equals(mAuthType, other.mAuthType)
+            && Objects.equals(mApnTypeBitmask, other.mApnTypeBitmask)
+            && (isDataRoaming || Objects.equals(mProtocol, other.mProtocol))
+            && (!isDataRoaming || Objects.equals(mRoamingProtocol, other.mRoamingProtocol))
+            && Objects.equals(mCarrierEnabled, other.mCarrierEnabled)
+            && Objects.equals(mProfileId, other.mProfileId)
+            && Objects.equals(mPersistent, other.mPersistent)
+            && Objects.equals(mMaxConns, other.mMaxConns)
+            && Objects.equals(mWaitTime, other.mWaitTime)
+            && Objects.equals(mMaxConnsTime, other.mMaxConnsTime)
+            && Objects.equals(mMtu, other.mMtu)
+            && Objects.equals(mMvnoType, other.mMvnoType)
+            && Objects.equals(mMvnoMatchData, other.mMvnoMatchData)
+            && Objects.equals(mApnSetId, other.mApnSetId)
+            && Objects.equals(mCarrierId, other.mCarrierId);
     }
 
     /**
@@ -1103,22 +1147,23 @@
      */
     public boolean similar(ApnSetting other) {
         return (!this.canHandleType(TYPE_DUN)
-                && !other.canHandleType(TYPE_DUN)
-                && Objects.equals(this.mApnName, other.mApnName)
-                && !typeSameAny(this, other)
-                && xorEquals(this.mProxyAddress, other.mProxyAddress)
-                && xorEqualsInt(this.mProxyPort, other.mProxyPort)
-                && xorEquals(this.mProtocol, other.mProtocol)
-                && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
-                && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
-                && Objects.equals(this.mProfileId, other.mProfileId)
-                && Objects.equals(this.mMvnoType, other.mMvnoType)
-                && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
-                && xorEquals(this.mMmsc, other.mMmsc)
-                && xorEquals(this.mMmsProxyAddress, other.mMmsProxyAddress)
-                && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
-                && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
-                && Objects.equals(mApnSetId, other.mApnSetId);
+            && !other.canHandleType(TYPE_DUN)
+            && Objects.equals(this.mApnName, other.mApnName)
+            && !typeSameAny(this, other)
+            && xorEquals(this.mProxyAddress, other.mProxyAddress)
+            && xorEqualsInt(this.mProxyPort, other.mProxyPort)
+            && xorEquals(this.mProtocol, other.mProtocol)
+            && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
+            && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
+            && Objects.equals(this.mProfileId, other.mProfileId)
+            && Objects.equals(this.mMvnoType, other.mMvnoType)
+            && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
+            && xorEquals(this.mMmsc, other.mMmsc)
+            && xorEquals(this.mMmsProxyAddress, other.mMmsProxyAddress)
+            && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
+            && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
+            && Objects.equals(mApnSetId, other.mApnSetId)
+            && Objects.equals(mCarrierId, other.mCarrierId);
     }
 
     // Equal or one is null.
@@ -1164,6 +1209,7 @@
         apnValue.put(Telephony.Carriers.CARRIER_ENABLED, mCarrierEnabled);
         apnValue.put(Telephony.Carriers.MVNO_TYPE, getMvnoTypeStringFromInt(mMvnoType));
         apnValue.put(Telephony.Carriers.NETWORK_TYPE_BITMASK, mNetworkTypeBitmask);
+        apnValue.put(Telephony.Carriers.CARRIER_ID, mCarrierId);
 
         return apnValue;
     }
@@ -1184,6 +1230,16 @@
     }
 
     /**
+     * @param apnType APN type
+     * @return APN type in string format
+     * @hide
+     */
+    public static String getApnTypeString(int apnType) {
+        String apnTypeString = APN_TYPE_INT_MAP.get(apnType);
+        return apnTypeString == null ? "Unknown" : apnTypeString;
+    }
+
+    /**
      * @param types comma delimited list of APN types.
      * @return bitmask of APN types.
      * @hide
@@ -1311,6 +1367,8 @@
         dest.writeBoolean(mCarrierEnabled);
         dest.writeInt(mMvnoType);
         dest.writeInt(mNetworkTypeBitmask);
+        dest.writeInt(mApnSetId);
+        dest.writeInt(mCarrierId);
     }
 
     private static ApnSetting readFromParcel(Parcel in) {
@@ -1320,7 +1378,7 @@
         final String apnName = in.readString();
         final String proxy = in.readString();
         final int port = in.readInt();
-        final Uri mmsc = (Uri)in.readValue(Uri.class.getClassLoader());
+        final Uri mmsc = (Uri) in.readValue(Uri.class.getClassLoader());
         final String mmsProxy = in.readString();
         final int mmsPort = in.readInt();
         final String user = in.readString();
@@ -1332,11 +1390,13 @@
         final boolean carrierEnabled = in.readBoolean();
         final int mvnoType = in.readInt();
         final int networkTypeBitmask = in.readInt();
+        final int apnSetId = in.readInt();
+        final int carrierId = in.readInt();
 
         return makeApnSetting(id, operatorNumeric, entryName, apnName,
             proxy, port, mmsc, mmsProxy, mmsPort, user, password, authType, apnTypesBitmask,
             protocol, roamingProtocol, carrierEnabled, networkTypeBitmask, 0, false,
-            0, 0, 0, 0, mvnoType, null);
+            0, 0, 0, 0, mvnoType, null, apnSetId, carrierId);
     }
 
     public static final Parcelable.Creator<ApnSetting> CREATOR =
@@ -1412,6 +1472,7 @@
         private int mMvnoType = UNSPECIFIED_INT;
         private String mMvnoMatchData;
         private int mApnSetId;
+        private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
 
         /**
          * Default constructor for Builder.
@@ -1741,6 +1802,19 @@
         }
 
         /**
+         * Sets the carrier id for this APN.
+         *
+         * See {@link TelephonyManager#getSimCarrierId()} which provides more background for what a
+         * carrier ID is.
+         *
+         * @param carrierId the carrier id to set for this APN
+         */
+        public Builder setCarrierId(int carrierId) {
+            this.mCarrierId = carrierId;
+            return this;
+        }
+
+        /**
          * Builds {@link ApnSetting} from this builder.
          *
          * @return {@code null} if {@link #setApnName(String)} or {@link #setEntryName(String)}
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index 1141177..3b1ef3f 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -15,6 +15,7 @@
  */
 package android.telephony.euicc;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -50,7 +51,6 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import android.annotation.CallbackExecutor;
 import java.util.concurrent.Executor;
 
 /**
@@ -119,6 +119,9 @@
     /** Result code when the eUICC card with the given card Id is not found. */
     public static final int RESULT_EUICC_NOT_FOUND = -2;
 
+    /** Result code indicating the caller is not the active LPA. */
+    public static final int RESULT_CALLER_NOT_ALLOWED = -3;
+
     /**
      * Callback to receive the result of an eUICC card API.
      *
@@ -152,7 +155,7 @@
      * Requests all the profiles on eUicc.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code and all the profiles.
      */
     public void requestAllProfiles(String cardId, @CallbackExecutor Executor executor,
@@ -176,7 +179,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code and profile.
      */
     public void requestProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
@@ -201,7 +204,7 @@
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
      * @param refresh Whether sending the REFRESH command to modem.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code.
      */
     public void disableProfile(String cardId, String iccid, boolean refresh,
@@ -227,7 +230,7 @@
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile to switch to.
      * @param refresh Whether sending the REFRESH command to modem.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code and the EuiccProfileInfo enabled.
      */
     public void switchToProfile(String cardId, String iccid, boolean refresh,
@@ -252,7 +255,7 @@
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
      * @param nickname The nickname of the profile.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code.
      */
     public void setNickname(String cardId, String iccid, String nickname,
@@ -276,7 +279,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param iccid The iccid of the profile.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code.
      */
     public void deleteProfile(String cardId, String iccid, @CallbackExecutor Executor executor,
@@ -301,7 +304,7 @@
      * @param cardId The Id of the eUICC.
      * @param options Bits of the options of resetting which parts of the eUICC memory. See
      *     EuiccCard for details.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code.
      */
     public void resetMemory(String cardId, @ResetOption int options,
@@ -324,7 +327,7 @@
      * Requests the default SM-DP+ address from eUICC.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code and the default SM-DP+ address.
      */
     public void requestDefaultSmdpAddress(String cardId, @CallbackExecutor Executor executor,
@@ -347,7 +350,7 @@
      * Requests the SM-DS address from eUICC.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code and the SM-DS address.
      */
     public void requestSmdsAddress(String cardId, @CallbackExecutor Executor executor,
@@ -371,7 +374,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param defaultSmdpAddress The default SM-DP+ address to set.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback The callback to get the result code.
      */
     public void setDefaultSmdpAddress(String cardId, String defaultSmdpAddress,
@@ -395,7 +398,7 @@
      * Requests Rules Authorisation Table.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the rule authorisation table.
      */
     public void requestRulesAuthTable(String cardId, @CallbackExecutor Executor executor,
@@ -418,7 +421,7 @@
      * Requests the eUICC challenge for new profile downloading.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the challenge.
      */
     public void requestEuiccChallenge(String cardId, @CallbackExecutor Executor executor,
@@ -441,7 +444,7 @@
      * Requests the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the info1.
      */
     public void requestEuiccInfo1(String cardId, @CallbackExecutor Executor executor,
@@ -464,7 +467,7 @@
      * Gets the eUICC info2 defined in GSMA RSP v2.0+ for new profile downloading.
      *
      * @param cardId The Id of the eUICC.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the info2.
      */
     public void requestEuiccInfo2(String cardId, @CallbackExecutor Executor executor,
@@ -497,7 +500,7 @@
      *     GSMA RSP v2.0+.
      * @param serverCertificate ASN.1 data in byte array indicating SM-DP+ Certificate returned by
      *     SM-DP+ server.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and a byte array which represents a
      *     {@code AuthenticateServerResponse} defined in GSMA RSP v2.0+.
      */
@@ -537,7 +540,7 @@
      *     SM-DP+ server.
      * @param smdpCertificate ASN.1 data in byte array indicating the SM-DP+ Certificate returned
      *     by SM-DP+ server.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and a byte array which represents a
      *     {@code PrepareDownloadResponse} defined in GSMA RSP v2.0+
      */
@@ -569,7 +572,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param boundProfilePackage the Bound Profile Package data returned by SM-DP+ server.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and a byte array which represents a
      *     {@code LoadBoundProfilePackageResponse} defined in GSMA RSP v2.0+.
      */
@@ -598,7 +601,7 @@
      * @param cardId The Id of the eUICC.
      * @param transactionId the transaction ID returned by SM-DP+ server.
      * @param reason the cancel reason.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and an byte[] which represents a
      *     {@code CancelSessionResponse} defined in GSMA RSP v2.0+.
      */
@@ -627,7 +630,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param events bits of the event types ({@link EuiccNotification.Event}) to list.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the list of notifications.
      */
     public void listNotifications(String cardId, @EuiccNotification.Event int events,
@@ -651,7 +654,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param events bits of the event types ({@link EuiccNotification.Event}) to list.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the list of notifications.
      */
     public void retrieveNotificationList(String cardId, @EuiccNotification.Event int events,
@@ -675,7 +678,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param seqNumber the sequence number of the notification.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code and the notification.
      */
     public void retrieveNotification(String cardId, int seqNumber,
@@ -699,7 +702,7 @@
      *
      * @param cardId The Id of the eUICC.
      * @param seqNumber the sequence number of the notification.
-     * @param executor The executor through which the callback should be invode.
+     * @param executor The executor through which the callback should be invoke.
      * @param callback the callback to get the result code.
      */
     public void removeNotificationFromList(String cardId, int seqNumber,
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 89ef339..f73036e 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -16,17 +16,20 @@
 
 package android.telephony.ims;
 
+import android.annotation.IntDef;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.PersistableBundle;
 import android.telecom.VideoProfile;
 import android.util.Log;
 
 import com.android.internal.telephony.PhoneConstants;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Parcelable object to handle IMS call profile.
  * It is created from GSMA IR.92/IR.94, 3GPP TS 24.229/TS 26.114/TS26.111.
@@ -206,17 +209,36 @@
     public static final int DIALSTRING_USSD = 2;
 
     /**
-     * Values for causes that restrict call types
+     * Call is not restricted on peer side and High Definition media is supported
      */
-    // Default cause not restricted at peer and HD is supported
     public static final int CALL_RESTRICT_CAUSE_NONE = 0;
-    // Service not supported by RAT at peer
+
+    /**
+     * High Definition media is not supported on the peer side due to the Radio Access Technology
+     * (RAT) it is are connected to.
+     */
     public static final int CALL_RESTRICT_CAUSE_RAT = 1;
-    // Service Disabled at peer
+
+    /**
+     * The service has been disabled on the peer side.
+     */
     public static final int CALL_RESTRICT_CAUSE_DISABLED = 2;
-    // HD is not supported
+
+    /**
+     * High definition media is not currently supported.
+     */
     public static final int CALL_RESTRICT_CAUSE_HD = 3;
 
+    /**@hide*/
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "CALL_RESTRICT_CAUSE_", value = {
+            CALL_RESTRICT_CAUSE_NONE,
+            CALL_RESTRICT_CAUSE_RAT,
+            CALL_RESTRICT_CAUSE_DISABLED,
+            CALL_RESTRICT_CAUSE_HD
+    })
+    public @interface CallRestrictCause {}
+
     /**
      * String extra properties
      *  oi : Originating identity (number), MT only
@@ -270,7 +292,7 @@
     public int mCallType;
     /** @hide */
     @UnsupportedAppUsage
-    public int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
+    public @CallRestrictCause int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
 
     /**
      * Extras associated with this {@link ImsCallProfile}.
@@ -285,7 +307,7 @@
      *     <li>{@code long[]}</li>
      *     <li>{@code double[]}</li>
      *     <li>{@code String[]}</li>
-     *     <li>{@link PersistableBundle}</li>
+     *     <li>{@link android.os.PersistableBundle}</li>
      *     <li>{@link Boolean} (and boolean)</li>
      *     <li>{@code boolean[]}</li>
      *     <li>Other {@link Parcelable} classes in the {@code android.*} namespace.</li>
@@ -426,6 +448,14 @@
         }
     }
 
+    /**
+     * Set the call restrict cause, which provides the reason why a call has been restricted from
+     * using High Definition media.
+     */
+    public void setCallRestrictCause(@CallRestrictCause int cause) {
+        mRestrictCause = cause;
+    }
+
     public void updateCallType(ImsCallProfile profile) {
         mCallType = profile.mCallType;
     }
@@ -494,7 +524,11 @@
         return mCallType;
     }
 
-    public int getRestrictCause() {
+    /**
+     * @return The call restrict cause, which provides the reason why a call has been restricted
+     * from using High Definition media.
+     */
+    public @CallRestrictCause int getRestrictCause() {
         return mRestrictCause;
     }
 
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index c9cf473..e06c372 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -292,7 +292,7 @@
      * Create an instance of ImsManager for the subscription id specified.
      *
      * @param context
-     * @param subId The ID of the subscription that this ImsManager will use.
+     * @param subId The ID of the subscription that this ImsMmTelManager will use.
      * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
      * @throws IllegalArgumentException if the subscription is invalid or
      *         the subscription ID is not an active subscription.
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
new file mode 100644
index 0000000..916e282
--- /dev/null
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2018 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.telephony.ims;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.ims.aidl.IImsConfigCallback;
+import android.telephony.ims.stub.ImsConfigImplBase;
+
+import com.android.internal.telephony.ITelephony;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Manages IMS provisioning and configuration parameters, as well as callbacks for apps to listen
+ * to changes in these configurations.
+ *
+ * Note: IMS provisioning keys are defined per carrier or OEM using OMA-DM or other provisioning
+ * applications and may vary.
+ * @hide
+ */
+@SystemApi
+public class ProvisioningManager {
+
+    /**
+     * Callback for IMS provisioning changes.
+     */
+    public static class Callback {
+
+        private static class CallbackBinder extends IImsConfigCallback.Stub {
+
+            private final Callback mLocalConfigurationCallback;
+            private Executor mExecutor;
+
+            private CallbackBinder(Callback localConfigurationCallback) {
+                mLocalConfigurationCallback = localConfigurationCallback;
+            }
+
+            @Override
+            public final void onIntConfigChanged(int item, int value) {
+                Binder.withCleanCallingIdentity(() ->
+                        mExecutor.execute(() ->
+                                mLocalConfigurationCallback.onProvisioningIntChanged(item, value)));
+            }
+
+            @Override
+            public final void onStringConfigChanged(int item, String value) {
+                Binder.withCleanCallingIdentity(() ->
+                        mExecutor.execute(() ->
+                                mLocalConfigurationCallback.onProvisioningStringChanged(item,
+                                        value)));
+            }
+
+            private void setExecutor(Executor executor) {
+                mExecutor = executor;
+            }
+        }
+
+        private final CallbackBinder mBinder = new CallbackBinder(this);
+
+        /**
+         * Called when a provisioning item has changed.
+         * @param item the IMS provisioning key constant, as defined by the OEM.
+         * @param value the new integer value of the IMS provisioning key.
+         */
+        public void onProvisioningIntChanged(int item, int value) {
+            // Base Implementation
+        }
+
+        /**
+         * Called when a provisioning item has changed.
+         * @param item the IMS provisioning key constant, as defined by the OEM.
+         * @param value the new String value of the IMS configuration constant.
+         */
+        public void onProvisioningStringChanged(int item, String value) {
+            // Base Implementation
+        }
+
+        /**@hide*/
+        public final IImsConfigCallback getBinder() {
+            return mBinder;
+        }
+
+        /**@hide*/
+        public void setExecutor(Executor executor) {
+            mBinder.setExecutor(executor);
+        }
+    }
+
+    private int mSubId;
+
+    /**
+     * Create a new {@link ProvisioningManager} for the subscription specified.
+     * @param context The context that this manager will use.
+     * @param subId The ID of the subscription that this ProvisioningManager will use.
+     * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
+     * @throws IllegalArgumentException if the subscription is invalid or
+     *         the subscription ID is not an active subscription.
+     */
+    public static ProvisioningManager createForSubscriptionId(Context context, int subId) {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)
+                || !getSubscriptionManager(context).isActiveSubscriptionId(subId)) {
+            throw new IllegalArgumentException("Invalid subscription ID");
+        }
+
+        return new ProvisioningManager(subId);
+    }
+
+    private ProvisioningManager(int subId) {
+        mSubId = subId;
+    }
+
+    /**
+     * Register a new {@link Callback} to listen to changes to changes in
+     * IMS provisioning. Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
+     * Subscription changed events and call
+     * {@link #unregisterProvisioningChangedCallback(Callback)} to clean up after a
+     * subscription is removed.
+     * @param executor The {@link Executor} to call the callback methods on
+     * @param callback The provisioning callbackto be registered.
+     * @see #unregisterProvisioningChangedCallback(Callback)
+     * @see SubscriptionManager.OnSubscriptionsChangedListener
+     */
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public void registerProvisioningChangedCallback(@CallbackExecutor Executor executor,
+            @NonNull Callback callback) {
+        callback.setExecutor(executor);
+        try {
+            getITelephony().registerImsProvisioningChangedCallback(mSubId,
+                    callback.getBinder());
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Unregister an existing {@link Callback}. Ensure to call this method when cleaning
+     * up to avoid memory leaks or when the subscription is removed.
+     * @param callback The existing {@link Callback} to be removed.
+     * @see #registerProvisioningChangedCallback(Executor, Callback)
+     */
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public void unregisterProvisioningChangedCallback(@NonNull Callback callback) {
+        try {
+            getITelephony().unregisterImsProvisioningChangedCallback(mSubId,
+                    callback.getBinder());
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Query for the integer value associated with the provided key.
+     * @param key An integer that represents the provisioning key, which is defined by the OEM.
+     * @return an integer value for the provided key.
+     * @throws IllegalArgumentException if the key provided was invalid.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public int getProvisioningIntValue(int key) {
+        try {
+            return getITelephony().getImsProvisioningInt(mSubId, key);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Query for the String value associated with the provided key.
+     * @param key An integer that represents the provisioning key, which is defined by the OEM.
+     * @return a String value for the provided key, or {@code null} if the key doesn't exist.
+     * @throws IllegalArgumentException if the key provided was invalid.
+     */
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public String getProvisioningStringValue(int key) {
+        try {
+            return getITelephony().getImsProvisioningString(mSubId, key);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Set the integer value associated with the provided key.
+     * @param key An integer that represents the provisioning key, which is defined by the OEM.
+     * @param value a integer value for the provided key.
+     * @return the result of setting the configuration value.
+     */
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public @ImsConfigImplBase.SetConfigResult int setProvisioningIntValue(int key, int value) {
+        try {
+            return getITelephony().setImsProvisioningInt(mSubId, key, value);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Set the String value associated with the provided key.
+     *
+     * @param key An integer that represents the provisioning key, which is defined by the OEM.
+     * @param value a String value for the provided key.
+     * @return the result of setting the configuration value.
+     */
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public @ImsConfigImplBase.SetConfigResult int setProvisioningStringValue(int key,
+            String value) {
+        try {
+            return getITelephony().setImsProvisioningString(mSubId, key, value);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    private static SubscriptionManager getSubscriptionManager(Context context) {
+        SubscriptionManager manager = context.getSystemService(SubscriptionManager.class);
+        if (manager == null) {
+            throw new RuntimeException("Could not find SubscriptionManager.");
+        }
+        return manager;
+    }
+
+    private static ITelephony getITelephony() {
+        ITelephony binder = ITelephony.Stub.asInterface(
+                ServiceManager.getService(Context.TELEPHONY_SERVICE));
+        if (binder == null) {
+            throw new RuntimeException("Could not find Telephony Service.");
+        }
+        return binder;
+    }
+}
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index dcd7ea7..321bfff 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -16,9 +16,9 @@
 
 package android.telephony.ims.stub;
 
+import android.annotation.IntDef;
 import android.annotation.SystemApi;
 import android.content.Context;
-import android.content.Intent;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.telephony.ims.aidl.IImsConfig;
@@ -28,6 +28,8 @@
 import com.android.ims.ImsConfig;
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.HashMap;
 
@@ -215,41 +217,6 @@
     }
 
     /**
-     * Callback that the framework uses for receiving Configuration change updates.
-     * {@hide}
-     */
-    public static class Callback extends IImsConfigCallback.Stub {
-
-        @Override
-        public final void onIntConfigChanged(int item, int value) throws RemoteException {
-            onConfigChanged(item, value);
-        }
-
-        @Override
-        public final void onStringConfigChanged(int item, String value) throws RemoteException {
-            onConfigChanged(item, value);
-        }
-
-        /**
-         * Called when the IMS configuration has changed.
-         * @param item the IMS configuration key constant, as defined in ImsConfig.
-         * @param value the new integer value of the IMS configuration constant.
-         */
-        public void onConfigChanged(int item, int value) {
-            // Base Implementation
-        }
-
-        /**
-         * Called when the IMS configuration has changed.
-         * @param item the IMS configuration key constant, as defined in ImsConfig.
-         * @param value the new String value of the IMS configuration constant.
-         */
-        public void onConfigChanged(int item, String value) {
-            // Base Implementation
-        }
-    }
-
-    /**
      * The configuration requested resulted in an unknown result. This may happen if the
      * IMS configurations are unavailable.
      */
@@ -263,6 +230,16 @@
      */
     public static final int CONFIG_RESULT_FAILED =  1;
 
+    /**
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "CONFIG_RESULT_", value = {
+            CONFIG_RESULT_SUCCESS,
+            CONFIG_RESULT_FAILED
+    })
+    public @interface SetConfigResult {}
+
     private final RemoteCallbackList<IImsConfigCallback> mCallbacks = new RemoteCallbackList<>();
     ImsConfigStub mImsConfigStub;
 
@@ -279,17 +256,16 @@
     }
 
     /**
-     * Adds a {@link Callback} to the list of callbacks notified when a value in the configuration
-     * changes.
+     * Adds a {@link android.telephony.ims.ProvisioningManager.Callback} to the list of callbacks
+     * notified when a value in the configuration changes.
      * @param c callback to add.
      */
     private void addImsConfigCallback(IImsConfigCallback c) {
         mCallbacks.register(c);
     }
     /**
-     * Removes a {@link Callback} to the list of callbacks notified when a value in the
-     * configuration changes.
-     *
+     * Removes a {@link android.telephony.ims.ProvisioningManager.Callback} to the list of callbacks
+     * notified when a value in the configuration changes.
      * @param c callback to remove.
      */
     private void removeImsConfigCallback(IImsConfigCallback c) {
@@ -370,10 +346,9 @@
      *
      * @param item an integer key.
      * @param value an integer containing the configuration value.
-     * @return the result of setting the configuration value, defined as either
-     * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
+     * @return the result of setting the configuration value.
      */
-    public int setConfig(int item, int value) {
+    public @SetConfigResult int setConfig(int item, int value) {
         // Base Implementation - To be overridden.
         return CONFIG_RESULT_FAILED;
     }
@@ -383,10 +358,9 @@
      *
      * @param item an integer key.
      * @param value a String containing the new configuration value.
-     * @return Result of setting the configuration value, defined as either
-     * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
+     * @return Result of setting the configuration value.
      */
-    public int setConfig(int item, String value) {
+    public @SetConfigResult int setConfig(int item, String value) {
         // Base Implementation - To be overridden.
         return CONFIG_RESULT_FAILED;
     }
diff --git a/telephony/java/android/telephony/RcsManager.java b/telephony/java/android/telephony/rcs/RcsManager.java
similarity index 86%
rename from telephony/java/android/telephony/RcsManager.java
rename to telephony/java/android/telephony/rcs/RcsManager.java
index 00ce03a..0ef4e15 100644
--- a/telephony/java/android/telephony/RcsManager.java
+++ b/telephony/java/android/telephony/rcs/RcsManager.java
@@ -14,18 +14,22 @@
  * limitations under the License.
  */
 
-package android.telephony;
+package android.telephony.rcs;
 
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.telephony.Rlog;
 
-import com.android.internal.telephony.IRcs;
+import com.android.internal.telephony.rcs.IRcs;
 
 /**
  * RcsManager is the application interface to RcsProvider and provides access methods to
  * RCS related database tables.
  * @hide - TODO make this public
  */
+@SystemService(Context.TELEPHONY_RCS_SERVICE)
 public class RcsManager {
     private static final String TAG = "RcsManager";
     private static final boolean VDBG = false;
diff --git a/telephony/java/android/telephony/rcs/RcsThread.aidl b/telephony/java/android/telephony/rcs/RcsThread.aidl
new file mode 100644
index 0000000..e2e0da5d
--- /dev/null
+++ b/telephony/java/android/telephony/rcs/RcsThread.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2018, 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.telephony;
+
+parcelable RcsThread;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/rcs/RcsThread.java b/telephony/java/android/telephony/rcs/RcsThread.java
new file mode 100644
index 0000000..83eb973
--- /dev/null
+++ b/telephony/java/android/telephony/rcs/RcsThread.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 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.telephony.rcs;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.telephony.rcs.IRcs;
+
+/**
+ * RcsThread represents a single RCS conversation thread. It holds messages that were sent and
+ * received and events that occured on that thread.
+ * @hide - TODO(sahinc) make this public
+ */
+public class RcsThread implements Parcelable {
+    public static final Creator<RcsThread> CREATOR = new Creator<RcsThread>() {
+        @Override
+        public RcsThread createFromParcel(Parcel in) {
+            return new RcsThread(in);
+        }
+
+        @Override
+        public RcsThread[] newArray(int size) {
+            return new RcsThread[size];
+        }
+    };
+
+    protected RcsThread(Parcel in) {
+    }
+
+    /**
+     * Returns the number of messages in this RCS thread.
+     *
+     * @hide
+     */
+    public int getMessageCount() {
+        try {
+            IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService("ircs"));
+            if (iRcs != null) {
+                // TODO(sahinc): substitute to the regular thread id once we have database
+                // TODO(sahinc): connection in place
+                return iRcs.getMessageCount(/* rcsThreadId= */ 123);
+            }
+        } catch (RemoteException re) {
+            // TODO(sahinc): Log something meaningful
+        }
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+    }
+}
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index 90e9880..71a2174 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -16,12 +16,17 @@
 
 package com.android.ims;
 
-import android.content.Context;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.telephony.Rlog;
 import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ProvisioningManager;
 import android.telephony.ims.aidl.IImsConfig;
-import android.telephony.ims.stub.ImsConfigImplBase;
+import android.telephony.ims.aidl.IImsConfigCallback;
+
+import java.util.concurrent.Executor;
 
 /**
  * Provides APIs to get/set the IMS service feature/capability/parameters.
@@ -29,8 +34,10 @@
  * 1) Items provisioned by the operator.
  * 2) Items configured by user. Mainly service feature class.
  *
+ * @deprecated Use {@link  ProvisioningManager} to change these configurations in the ImsService.
  * @hide
  */
+@Deprecated
 public class ImsConfig {
     private static final String TAG = "ImsConfig";
     private boolean DBG = true;
@@ -46,7 +53,7 @@
 
     /**
      * Broadcast action: the configuration was changed
-     * @deprecated Use {@link ImsConfig#addConfigCallback(ImsConfigImplBase.Callback)} instead.
+     * @deprecated Use {@link android.telephony.ims.ProvisioningManager.Callback} instead.
      * @hide
      */
     public static final String ACTION_IMS_CONFIG_CHANGED =
@@ -673,13 +680,25 @@
     }
 
     /**
-     * Adds a {@link ImsConfigImplBase.Callback} to the ImsService to notify when a Configuration
+     * Adds a {@link ProvisioningManager.Callback} to the ImsService to notify when a Configuration
      * item has changed.
      *
-     * Make sure to call {@link #removeConfigCallback(ImsConfigImplBase.Callback)} when finished
+     * Make sure to call {@link #removeConfigCallback(IImsConfigCallback)} when finished
      * using this callback.
      */
-    public void addConfigCallback(ImsConfigImplBase.Callback callback) throws ImsException {
+    public void addConfigCallback(ProvisioningManager.Callback callback) throws ImsException {
+        callback.setExecutor(getThreadExecutor());
+        addConfigCallback(callback.getBinder());
+    }
+
+    /**
+     * Adds a {@link IImsConfigCallback} to the ImsService to notify when a Configuration
+     * item has changed.
+     *
+     * Make sure to call {@link #removeConfigCallback(IImsConfigCallback)} when finished
+     * using this callback.
+     */
+    public void addConfigCallback(IImsConfigCallback callback) throws ImsException {
         if (DBG) Rlog.d(TAG, "addConfigCallback: " + callback);
         try {
             miConfig.addImsConfigCallback(callback);
@@ -690,10 +709,9 @@
     }
 
     /**
-     * Removes a {@link ImsConfigImplBase.Callback} from the ImsService that was previously added
-     * by {@link #addConfigCallback(ImsConfigImplBase.Callback)}.
+     * Removes an existing {@link IImsConfigCallback} from the ImsService.
      */
-    public void removeConfigCallback(ImsConfigImplBase.Callback callback) throws ImsException {
+    public void removeConfigCallback(IImsConfigCallback callback) throws ImsException {
         if (DBG) Rlog.d(TAG, "removeConfigCallback: " + callback);
         try {
             miConfig.removeImsConfigCallback(callback);
@@ -709,4 +727,11 @@
     public boolean isBinderAlive() {
         return miConfig.asBinder().isBinderAlive();
     }
+
+    private Executor getThreadExecutor() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        return new HandlerExecutor(new Handler(Looper.myLooper()));
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/IAns.aidl b/telephony/java/com/android/internal/telephony/IAns.aidl
index 6eb8d66..e9a4649 100755
--- a/telephony/java/com/android/internal/telephony/IAns.aidl
+++ b/telephony/java/com/android/internal/telephony/IAns.aidl
@@ -49,4 +49,33 @@
     * @param callingPackage caller's package name
     */
     boolean isEnabled(String callingPackage);
+
+    /**
+     * Set preferred opportunistic data subscription id.
+     *
+     * <p>Requires that the calling app has carrier privileges on both primary and
+     * secondary subscriptions (see
+     * {@link #hasCarrierPrivileges}), or has permission
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     *
+     * @param subId which opportunistic subscription
+     * {@link SubscriptionManager#getOpportunisticSubscriptions} is preferred for cellular data.
+     * Pass {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} to unset the preference
+     * @param callingPackage caller's package name
+     * @return true if request is accepted, else false.
+     *
+     */
+    boolean setPreferredData(int subId, String callingPackage);
+
+    /**
+     * Get preferred opportunistic data subscription Id
+     *
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}),
+     * or has permission {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}.
+     * @return subId preferred opportunistic subscription id or
+     * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} if there are no preferred
+     * subscription id
+     *
+     */
+    int getPreferredData(String callingPackage);
 }
diff --git a/telephony/java/com/android/internal/telephony/IApnSourceService.aidl b/telephony/java/com/android/internal/telephony/IApnSourceService.aidl
index 07bb18b..34c9067 100644
--- a/telephony/java/com/android/internal/telephony/IApnSourceService.aidl
+++ b/telephony/java/com/android/internal/telephony/IApnSourceService.aidl
@@ -20,5 +20,5 @@
 
 interface IApnSourceService {
     /** Retreive APNs. */
-    ContentValues[] getApns();
+    ContentValues[] getApns(int subId);
 }
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 9e42f12..79f0635 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -25,7 +25,6 @@
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
-import android.telephony.VoLteServiceState;
 
 oneway interface IPhoneStateListener {
     void onServiceStateChanged(in ServiceState serviceState);
@@ -45,7 +44,7 @@
     void onPreciseCallStateChanged(in PreciseCallState callState);
     void onPreciseDataConnectionStateChanged(in PreciseDataConnectionState dataConnectionState);
     void onDataConnectionRealTimeInfoChanged(in DataConnectionRealTimeInfo dcRtInfo);
-    void onVoLteServiceStateChanged(in VoLteServiceState lteState);
+    void onSrvccStateChanged(in int state);
     void onVoiceActivationStateChanged(int activationState);
     void onDataActivationStateChanged(int activationState);
     void onOemHookRawEvent(in byte[] rawData);
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 4bdec08..bc44519 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -165,13 +165,23 @@
     int setOpportunistic(boolean opportunistic, int subId);
 
     /**
-     * Set parent subId by simInfo index
+     * Inform SubscriptionManager that subscriptions in the list are bundled
+     * as a group. Typically it's a primary subscription and an opportunistic
+     * subscription. It should only affect multi-SIM scenarios where primary
+     * and opportunistic subscriptions can be activated together.
+     * Being in the same group means they might be activated or deactivated
+     * together, some of them may be invisible to the users, etc.
      *
-     * @param parentSubId: subId of its parent subscription.
-     * @param subId the unique SubscriptionInfo index in database
-     * @return the number of records updated
+     * Caller will either have {@link android.Manifest.permission.MODIFY_PHONE_STATE}
+     * permission or can manage all subscriptions in the list, according to their
+     * acess rules.
+     *
+     * @param subIdList list of subId that will be in the same group
+     * @return groupUUID a UUID assigned to the subscription group. It returns
+     * null if fails.
+     *
      */
-    int setParentSubId(int parentSubId, int subId);
+    String setSubscriptionGroup(in int[] subIdList, String callingPackage);
 
     /**
      * Set which subscription is preferred for cellular data. It's
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index b20b164..f0e8586 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -22,6 +22,7 @@
 import android.os.IBinder;
 import android.os.Messenger;
 import android.os.ResultReceiver;
+import android.os.WorkSource;
 import android.net.NetworkStats;
 import android.net.Uri;
 import android.service.carrier.CarrierIdentifier;
@@ -30,6 +31,7 @@
 import android.telephony.CellInfo;
 import android.telephony.ClientRequestStats;
 import android.telephony.IccOpenLogicalChannelResponse;
+import android.telephony.ICellInfoCallback;
 import android.telephony.ModemActivityInfo;
 import android.telephony.NeighboringCellInfo;
 import android.telephony.NetworkScanRequest;
@@ -40,6 +42,7 @@
 import android.telephony.VisualVoicemailSmsFilterSettings;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsConfigCallback;
 import android.telephony.ims.aidl.IImsMmTelFeature;
 import android.telephony.ims.aidl.IImsRcsFeature;
 import android.telephony.ims.aidl.IImsRegistration;
@@ -506,11 +509,26 @@
     int getLteOnCdmaModeForSubscriber(int subId, String callingPackage);
 
     /**
-     * Returns the all observed cell information of the device.
+     * Returns all observed cell information of the device.
      */
     List<CellInfo> getAllCellInfo(String callingPkg);
 
     /**
+     * Request a cell information update for the specified subscription,
+     * reported via the CellInfoCallback.
+     */
+    void requestCellInfoUpdate(int subId, in ICellInfoCallback cb, String callingPkg);
+
+    /**
+     * Request a cell information update for the specified subscription,
+     * reported via the CellInfoCallback.
+     *
+     * @param workSource the requestor to whom the power consumption for this should be attributed.
+     */
+    void requestCellInfoUpdateWithWorkSource(
+            int subId, in ICellInfoCallback cb, in String callingPkg, in WorkSource ws);
+
+    /**
      * Sets minimum time in milli-seconds between onCellInfoChanged
      */
     void setCellInfoListRate(int rateInMillis);
@@ -1311,6 +1329,49 @@
     String getSubscriptionCarrierName(int subId);
 
     /**
+     * Returns MNO carrier id of the current subscription’s MCCMNC.
+     * <p>MNO carrier id can be solely identified by subscription mccmnc. This is mainly used
+     * for MNO fallback when exact carrier id {@link #getSimCarrierId()}
+     * configurations are not found.
+     *
+     * @return MNO carrier id of the current subscription. Return the value same as carrier id
+     * {@link #getSimCarrierId()}, if MNO carrier id cannot be identified.
+     * @hide
+     */
+    int getSubscriptionMNOCarrierId(int subId);
+
+    /**
+     * Returns fine-grained carrier id of the current subscription.
+     *
+     * <p>The precise carrier id can be used to further differentiate a carrier by different
+     * networks, by prepaid v.s.postpaid or even by 4G v.s.3G plan. Each carrier has a unique
+     * carrier id {@link #getSimCarrierId()} but can have multiple precise carrier id. e.g,
+     * {@link #getSimCarrierId()} will always return Tracfone (id 2022) for a Tracfone SIM, while
+     * {@link #getSimPreciseCarrierId()} can return Tracfone AT&T or Tracfone T-Mobile based on the
+     * current underlying network.
+     *
+     * <p>For carriers without any fine-grained carrier ids, return {@link #getSimCarrierId()}
+     *
+     * @return Returns fine-grained carrier id of the current subscription.
+     * Return {@link #UNKNOWN_CARRIER_ID} if the subscription is unavailable or the carrier cannot
+     * be identified.
+     * @hide
+     */
+    int getSubscriptionPreciseCarrierId(int subId);
+
+    /**
+     * Similar like {@link #getSimCarrierIdName()}, returns user-facing name of the
+     * precise carrier id {@link #getSimPreciseCarrierId()}
+     *
+     * <p>The returned name is unlocalized.
+     *
+     * @return user-facing name of the subscription precise carrier id. Return {@code null} if the
+     * subscription is unavailable or the carrier cannot be identified.
+     * @hide
+     */
+    String getSubscriptionPreciseCarrierName(int subId);
+
+    /**
      * Action set from carrier signalling broadcast receivers to enable/disable metered apns
      * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
      * @param subId the subscription ID that this action applies to.
@@ -1526,24 +1587,24 @@
     /**
      * Adds an IMS registration status callback for the subscription id specified.
      */
-    oneway void addImsRegistrationCallback(int subId, IImsRegistrationCallback c,
+    void addImsRegistrationCallback(int subId, IImsRegistrationCallback c,
             String callingPackage);
      /**
       * Removes an existing IMS registration status callback for the subscription specified.
       */
-    oneway void removeImsRegistrationCallback(int subId, IImsRegistrationCallback c,
+    void removeImsRegistrationCallback(int subId, IImsRegistrationCallback c,
             String callingPackage);
 
     /**
      * Adds an IMS MmTel capabilities callback for the subscription specified.
      */
-    oneway void addMmTelCapabilityCallback(int subId, IImsCapabilityCallback c,
+    void addMmTelCapabilityCallback(int subId, IImsCapabilityCallback c,
             String callingPackage);
 
     /**
      * Removes an existing IMS MmTel capabilities callback for the subscription specified.
      */
-    oneway void removeMmTelCapabilityCallback(int subId, IImsCapabilityCallback c,
+    void removeMmTelCapabilityCallback(int subId, IImsCapabilityCallback c,
             String callingPackage);
 
     /**
@@ -1648,4 +1709,34 @@
      * Return a list of certs in hex string from loaded carrier privileges access rules.
      */
     List<String> getCertsFromCarrierPrivilegeAccessRules(int subId);
+
+    /**
+     * Register an IMS provisioning change callback with Telephony.
+     */
+    void registerImsProvisioningChangedCallback(int subId, IImsConfigCallback callback);
+
+    /**
+     * unregister an existing IMS provisioning change callback.
+     */
+    void unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback);
+
+    /**
+     * Return an integer containing the provisioning value for the specified provisioning key.
+     */
+    int getImsProvisioningInt(int subId, int key);
+
+    /**
+     * return a String containing the provisioning value for the provisioning key specified.
+     */
+    String getImsProvisioningString(int subId, int key);
+
+    /**
+     * Set the integer provisioning value for the provisioning key specified.
+     */
+    int setImsProvisioningInt(int subId, int key, int value);
+
+    /**
+     * Set the String provisioning value for the provisioning key specified.
+     */
+    int setImsProvisioningString(int subId, int key, String value);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 0baf860..923ab06 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -25,7 +25,6 @@
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
-import android.telephony.VoLteServiceState;
 import com.android.internal.telephony.IPhoneStateListener;
 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
 
@@ -70,7 +69,7 @@
     void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn,
             String failCause);
     void notifyCellInfoForSubscriber(in int subId, in List<CellInfo> cellInfo);
-    void notifyVoLteServiceStateChanged(in VoLteServiceState lteState);
+    void notifySrvccStateChanged(in int subId, in int lteState);
     void notifySimActivationStateChangedForPhoneId(in int phoneId, in int subId,
             int activationState, int activationType);
     void notifyOemHookRawEventForSubscriber(in int subId, in byte[] rawData);
diff --git a/telephony/java/com/android/internal/telephony/NetworkScanResult.java b/telephony/java/com/android/internal/telephony/NetworkScanResult.java
index 95f39d7..d07d77c 100644
--- a/telephony/java/com/android/internal/telephony/NetworkScanResult.java
+++ b/telephony/java/com/android/internal/telephony/NetworkScanResult.java
@@ -19,6 +19,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.CellInfo;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -106,6 +107,17 @@
     }
 
     @Override
+    public String toString() {
+        return new StringBuilder()
+            .append("{")
+            .append("scanStatus=" + scanStatus)
+            .append(", scanError=" + scanError)
+            .append(", networkInfos=" + networkInfos)
+            .append("}")
+            .toString();
+    }
+
+    @Override
     public int hashCode () {
         return ((scanStatus * 31)
                 + (scanError * 23)
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 5ecb43e..2a648bd 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -480,9 +480,9 @@
     public static final String EXTRA_PCO_VALUE_KEY = "pcoValue";
     public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE_KEY = "defaultNetworkAvailable";
 
-   /**
+    /**
      * Broadcast action to trigger CI OMA-DM Session.
-    */
+     */
     public static final String ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE =
             "com.android.omadm.service.CONFIGURATION_UPDATE";
 
@@ -491,4 +491,14 @@
      */
     public static final String ACTION_CARRIER_CERTIFICATE_DOWNLOAD =
             "com.android.internal.telephony.ACTION_CARRIER_CERTIFICATE_DOWNLOAD";
+
+    /**
+     * Broadcast action to indicate an error related to Line1Number has been detected.
+     *
+     * Requires the READ_PRIVILEGED_PHONE_STATE permission.
+     *
+     * @hide
+     */
+    public static final String ACTION_LINE1_NUMBER_ERROR_DETECTED =
+            "com.android.internal.telephony.ACTION_LINE1_NUMBER_ERROR_DETECTED";
 }
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index eb6be65..553e3fb 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -188,6 +188,13 @@
         if (checkReadDeviceIdentifiers(context, pid, uid, callingPackage)) {
             return true;
         }
+        // Calling packages with carrier privileges will also have access to device identifiers, but
+        // this may be removed in a future release.
+        if (SubscriptionManager.isValidSubscriptionId(subId) && getCarrierPrivilegeStatus(
+                TELEPHONY_SUPPLIER, subId, uid)
+                == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+            return true;
+        }
         // else the calling package is not authorized to access the device identifiers; call
         // a central method to report the failure based on the target SDK and if the calling package
         // has the READ_PHONE_STATE permission or carrier privileges that were previously required
@@ -279,44 +286,51 @@
             int uid, String callingPackage, String message) {
         Log.wtf(LOG_TAG,
                 "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message);
-        // if the device identifier check is relaxed then revert to the READ_PHONE_STATE permission
-        // check that was previously required to access device identifiers.
-        boolean relaxDeviceIdentifierCheck = Settings.Global.getInt(context.getContentResolver(),
-                Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_CHECK_ENABLED, 0) == 0;
-        if (relaxDeviceIdentifierCheck) {
-            return checkReadPhoneState(context, subId, pid, uid, callingPackage, message);
-        } else {
+        // If the device identifier check is enabled then enforce the new access requirements for
+        // both 1P and 3P apps.
+        boolean enableDeviceIdentifierCheck = Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_CHECK_ENABLED, 0) == 1;
+        // Check if the application is a 3P app; if so then a separate setting is required to relax
+        // the check to begin flagging problems with 3P apps early.
+        boolean relax3PDeviceIdentifierCheck = Settings.Global.getInt(context.getContentResolver(),
+                Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_3P_CHECK_RELAXED, 0) == 1;
+        boolean is3PApp = true;
+        ApplicationInfo callingPackageInfo = null;
+        try {
+            callingPackageInfo = context.getPackageManager().getApplicationInfo(callingPackage, 0);
+            if (callingPackageInfo.isSystemApp()) {
+                is3PApp = false;
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            // If the application info for the calling package could not be found then assume the
+            // calling app is a 3P app to detect any issues with the check
+        }
+        if (enableDeviceIdentifierCheck || (is3PApp && !relax3PDeviceIdentifierCheck)) {
             boolean targetQBehaviorDisabled = Settings.Global.getInt(context.getContentResolver(),
                     Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_TARGET_Q_BEHAVIOR_ENABLED, 0) == 0;
             if (callingPackage != null) {
-                try {
-                    // if the target SDK is pre-Q or the target Q behavior is disabled then check if
-                    // the calling package would have previously had access to device identifiers.
-                    ApplicationInfo callingPackageInfo =
-                            context.getPackageManager().getApplicationInfo(
-                                    callingPackage, 0);
-                    if (callingPackageInfo != null && (
-                            callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q
-                                    || targetQBehaviorDisabled)) {
-                        if (context.checkPermission(
-                                android.Manifest.permission.READ_PHONE_STATE,
-                                pid,
-                                uid) == PackageManager.PERMISSION_GRANTED) {
-                            return false;
-                        }
-                        if (SubscriptionManager.isValidSubscriptionId(subId)
-                                && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, uid)
-                                == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
-                            return false;
-                        }
+                // if the target SDK is pre-Q or the target Q behavior is disabled then check if
+                // the calling package would have previously had access to device identifiers.
+                if (callingPackageInfo != null && (
+                        callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q
+                                || targetQBehaviorDisabled)) {
+                    if (context.checkPermission(
+                            android.Manifest.permission.READ_PHONE_STATE,
+                            pid,
+                            uid) == PackageManager.PERMISSION_GRANTED) {
+                        return false;
                     }
-                } catch (PackageManager.NameNotFoundException e) {
-                    // If the application info for the calling package could not be found then
-                    // default to throwing the SecurityException.
+                    if (SubscriptionManager.isValidSubscriptionId(subId)
+                            && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, uid)
+                            == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+                        return false;
+                    }
                 }
             }
             throw new SecurityException(message + ": The user " + uid
                     + " does not meet the requirements to access device identifiers.");
+        } else {
+            return checkReadPhoneState(context, subId, pid, uid, callingPackage, message);
         }
     }
 
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
similarity index 83%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
index ede8695..4c289ac 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/telephony/java/com/android/internal/telephony/rcs/IRcs.aidl
@@ -14,8 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package com.android.internal.telephony.rcs;
 
 interface IRcs {
+    // RcsManager APIs
     void deleteThread(int threadId);
+
+    // RcsThread APIs
+    int getMessageCount(int rcsThreadId);
 }
\ No newline at end of file
diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt
index fc9b4c6..f91d74a 100644
--- a/test-mock/api/current.txt
+++ b/test-mock/api/current.txt
@@ -31,6 +31,7 @@
 
   public class MockContext extends android.content.Context {
     ctor public MockContext();
+    method public boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, java.lang.String);
     method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
     method public int checkCallingOrSelfPermission(java.lang.String);
     method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index fa5b896..66be6d9 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -576,6 +576,13 @@
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    public boolean bindIsolatedService(Intent service,
+            ServiceConnection conn, int flags,
+            String instanceName) {
+        throw new UnsupportedOperationException();
+    }
+
     /** @hide */
     @Override
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
diff --git a/test-runner/src/android/test/IsolatedContext.java b/test-runner/src/android/test/IsolatedContext.java
index 6e4c41e..73db451 100644
--- a/test-runner/src/android/test/IsolatedContext.java
+++ b/test-runner/src/android/test/IsolatedContext.java
@@ -75,6 +75,12 @@
     }
 
     @Override
+    public boolean bindIsolatedService(Intent service, ServiceConnection conn, int flags,
+            String instanceName) {
+        return false;
+    }
+
+    @Override
     public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
         return null;
     }
diff --git a/tests/RcsTests/Android.mk b/tests/RcsTests/Android.mk
new file mode 100644
index 0000000..adc7cab
--- /dev/null
+++ b/tests/RcsTests/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := RcsTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := junit android-support-test mockito-target-minus-junit4
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/RcsTests/AndroidManifest.xml b/tests/RcsTests/AndroidManifest.xml
new file mode 100644
index 0000000..a7e7d47
--- /dev/null
+++ b/tests/RcsTests/AndroidManifest.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.tests.rcs">
+    <application android:label="RCS Test">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.tests.rcs"/>
+</manifest>
diff --git a/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java b/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java
new file mode 100644
index 0000000..7f5f03e
--- /dev/null
+++ b/tests/RcsTests/src/com/android/tests/rcs/RcsManagerTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.rcs;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.telephony.rcs.RcsManager;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class RcsManagerTest {
+    //TODO(sahinc): Add meaningful tests once we have more of the implementation in place
+    @Test
+    public void testDeleteThreadDoesntCrash() {
+        RcsManager mRcsManager = new RcsManager();
+        mRcsManager.deleteThread(0);
+    }
+}
diff --git a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
index 8467bee..be74a6d 100644
--- a/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
+++ b/tests/UsageStatsPerfTests/src/com/android/frameworks/perftests/usage/tests/UsageStatsDatabasePerfTest.java
@@ -18,10 +18,6 @@
 
 import static junit.framework.Assert.assertEquals;
 
-import com.android.server.usage.UsageStatsDatabase;
-import com.android.server.usage.UsageStatsDatabase.StatCombiner;
-import com.android.server.usage.IntervalStats;
-
 import android.app.usage.EventList;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStatsManager;
@@ -29,10 +25,14 @@
 import android.os.SystemClock;
 import android.perftests.utils.ManualBenchmarkState;
 import android.perftests.utils.PerfManualStatusReporter;
-import android.support.test.filters.LargeTest;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import com.android.server.usage.IntervalStats;
+import com.android.server.usage.UsageStatsDatabase;
+import com.android.server.usage.UsageStatsDatabase.StatCombiner;
+
 import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
@@ -90,11 +90,13 @@
         for (int pkg = 0; pkg < packageCount; pkg++) {
             UsageEvents.Event event = new UsageEvents.Event();
             event.mPackage = "fake.package.name" + pkg;
+            event.mClass = event.mPackage + ".class1";
             event.mTimeStamp = 1;
             event.mEventType = UsageEvents.Event.MOVE_TO_FOREGROUND;
             for (int evt = 0; evt < eventsPerPackage; evt++) {
                 intervalStats.events.insert(event);
-                intervalStats.update(event.mPackage, event.mTimeStamp, event.mEventType);
+                intervalStats.update(event.mPackage, event.mClass, event.mTimeStamp,
+                        event.mEventType);
             }
         }
     }
diff --git a/tests/net/java/android/net/MacAddressTest.java b/tests/net/java/android/net/MacAddressTest.java
index 04266c5..17486e0 100644
--- a/tests/net/java/android/net/MacAddressTest.java
+++ b/tests/net/java/android/net/MacAddressTest.java
@@ -16,20 +16,22 @@
 
 package android.net;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
-import java.util.Arrays;
-import java.util.Random;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.net.Inet6Address;
+import java.util.Arrays;
+import java.util.Random;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class MacAddressTest {
@@ -252,6 +254,52 @@
         }
     }
 
+    @Test
+    public void testMatches() {
+        // match 4 bytes prefix
+        assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+                MacAddress.fromString("aa:bb:cc:dd:00:00"),
+                MacAddress.fromString("ff:ff:ff:ff:00:00")));
+
+        // match bytes 0,1,2 and 5
+        assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+                MacAddress.fromString("aa:bb:cc:00:00:11"),
+                MacAddress.fromString("ff:ff:ff:00:00:ff")));
+
+        // match 34 bit prefix
+        assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+                MacAddress.fromString("aa:bb:cc:dd:c0:00"),
+                MacAddress.fromString("ff:ff:ff:ff:c0:00")));
+
+        // fail to match 36 bit prefix
+        assertFalse(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+                MacAddress.fromString("aa:bb:cc:dd:40:00"),
+                MacAddress.fromString("ff:ff:ff:ff:f0:00")));
+
+        // match all 6 bytes
+        assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+                MacAddress.fromString("aa:bb:cc:dd:ee:11"),
+                MacAddress.fromString("ff:ff:ff:ff:ff:ff")));
+
+        // match none of 6 bytes
+        assertTrue(MacAddress.fromString("aa:bb:cc:dd:ee:11").matches(
+                MacAddress.fromString("00:00:00:00:00:00"),
+                MacAddress.fromString("00:00:00:00:00:00")));
+    }
+
+    /**
+     * Tests that link-local address generation from MAC is valid.
+     */
+    @Test
+    public void testLinkLocalFromMacGeneration() {
+        MacAddress mac = MacAddress.fromString("52:74:f2:b1:a8:7f");
+        byte[] inet6ll = {(byte) 0xfe, (byte) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x74,
+            (byte) 0xf2, (byte) 0xff, (byte) 0xfe, (byte) 0xb1, (byte) 0xa8, 0x7f};
+        Inet6Address llv6 = mac.getLinkLocalIpv6FromEui48Mac();
+        assertTrue(llv6.isLinkLocalAddress());
+        assertArrayEquals(inet6ll, llv6.getAddress());
+    }
+
     static byte[] toByteArray(int... in) {
         byte[] out = new byte[in.length];
         for (int i = 0; i < in.length; i++) {
diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
index dfe31bd..bf42412 100644
--- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
+++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -31,6 +31,7 @@
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
+import android.net.NetworkMisc;
 import android.os.Handler;
 import android.os.INetworkManagementService;
 import android.os.test.TestLooper;
@@ -55,6 +56,7 @@
     static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29");
 
     @Mock ConnectivityService mConnectivity;
+    @Mock NetworkMisc mMisc;
     @Mock INetworkManagementService mNms;
     @Mock InterfaceConfiguration mConfig;
     @Mock NetworkAgentInfo mNai;
@@ -78,6 +80,7 @@
         mNai.networkInfo = new NetworkInfo(null);
         mNai.networkInfo.setType(ConnectivityManager.TYPE_WIFI);
         when(mNai.connService()).thenReturn(mConnectivity);
+        when(mNai.netMisc()).thenReturn(mMisc);
         when(mNai.handler()).thenReturn(mHandler);
 
         when(mNms.getInterfaceConfig(eq(STACKED_IFACE))).thenReturn(mConfig);
@@ -103,9 +106,16 @@
             mNai.networkInfo.setType(type);
             for (NetworkInfo.DetailedState state : supportedDetailedStates) {
                 mNai.networkInfo.setDetailedState(state, "reason", "extraInfo");
-                assertTrue(
-                        String.format("requiresClat expected for type=%d state=%s", type, state),
-                        Nat464Xlat.requiresClat(mNai));
+                String msg = String.format("requiresClat expected for type=%d state=%s",
+                        type, state);
+
+                mMisc.skip464xlat = true;
+                String errorMsg = msg + String.format(" skip464xlat=%b", mMisc.skip464xlat);
+                assertFalse(errorMsg, Nat464Xlat.requiresClat(mNai));
+
+                mMisc.skip464xlat = false;
+                errorMsg = msg + String.format(" skip464xlat=%b", mMisc.skip464xlat);
+                assertTrue(errorMsg, Nat464Xlat.requiresClat(mNai));
             }
         }
     }
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index f12756a..af7123b 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -30,7 +30,9 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -63,24 +65,13 @@
     @Mock private PackageManager mPackageManager;
 
     private PermissionMonitor mPermissionMonitor;
-    private int mMockFirstSdkInt;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(MOCK_PACKAGE_NAMES);
-        // Try to use spy() here for stubbing getDeviceFirstSdkInt value but the spies are loaded
-        // by a custom class loader that's different from the loader used for loading the real
-        // thing. That means those two classes are not in the same package, so a package private
-        // method is not accessible. Hence, using override method to control FIRST_SDK_INT value
-        // instead of spy function for testing.
-        mPermissionMonitor = new PermissionMonitor(mContext, null) {
-            @Override
-            int getDeviceFirstSdkInt() {
-                return mMockFirstSdkInt;
-            }
-        };
+        mPermissionMonitor = spy(new PermissionMonitor(mContext, null));
     }
 
     private boolean hasBgPermission(String partition, int targetSdkVersion, int uid,
@@ -166,13 +157,13 @@
 
     @Test
     public void testHasUseBackgroundNetworksPermissionSystemUid() throws Exception {
-        mMockFirstSdkInt = VERSION_P;
+        doReturn(VERSION_P).when(mPermissionMonitor).getDeviceFirstSdkInt();
         assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID));
         assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CHANGE_WIFI_STATE));
         assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID,
                 CONNECTIVITY_USE_RESTRICTED_NETWORKS));
 
-        mMockFirstSdkInt = VERSION_Q;
+        doReturn(VERSION_Q).when(mPermissionMonitor).getDeviceFirstSdkInt();
         assertFalse(hasBgPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID));
         assertFalse(hasBgPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CHANGE_WIFI_STATE));
         assertTrue(hasBgPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID,
diff --git a/tests/utils/testutils/Android.bp b/tests/utils/testutils/Android.bp
index 4be6534..0a9e964 100644
--- a/tests/utils/testutils/Android.bp
+++ b/tests/utils/testutils/Android.bp
@@ -19,7 +19,7 @@
 
     srcs: ["java/**/*.java"],
 
-    static_libs: ["android-support-test"],
+    static_libs: ["junit"],
 
     libs: [
         "android.test.runner",
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 0a517ab..583f14a 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -306,8 +306,29 @@
             break;
         }
 
-        if (entry->overlayable) {
-          printer->Print(" OVERLAYABLE");
+        for (size_t i = 0; i < entry->overlayable_declarations.size(); i++) {
+          printer->Print((i == 0) ? " " : "|");
+          printer->Print("OVERLAYABLE");
+
+          if (entry->overlayable_declarations[i].policy) {
+            switch (entry->overlayable_declarations[i].policy.value()) {
+              case Overlayable::Policy::kProduct:
+                printer->Print("_PRODUCT");
+                break;
+              case Overlayable::Policy::kProductServices:
+                printer->Print("_PRODUCT_SERVICES");
+                break;
+              case Overlayable::Policy::kSystem:
+                printer->Print("_SYSTEM");
+                break;
+              case Overlayable::Policy::kVendor:
+                printer->Print("_VENDOR");
+                break;
+              case Overlayable::Policy::kPublic:
+                printer->Print("_PUBLIC");
+                break;
+            }
+          }
         }
 
         printer->Println();
@@ -410,7 +431,7 @@
 
 void Debug::DumpResStringPool(const android::ResStringPool* pool, text::Printer* printer) {
   using namespace android;
-  
+
   if (pool->getError() == NO_INIT) {
     printer->Print("String pool is unitialized.\n");
     return;
@@ -439,7 +460,7 @@
   const size_t NS = pool->size();
   for (size_t s=0; s<NS; s++) {
     String8 str = pool->string8ObjectAt(s);
-    printer->Print(StringPrintf("String #%zd : %s\n", s, str.string()));
+    printer->Print(StringPrintf("String #%zd: %s\n", s, str.string()));
   }
 }
 
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 9a3f14c..4f25e09 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -99,7 +99,7 @@
   ResourceId id;
   Visibility::Level visibility_level = Visibility::Level::kUndefined;
   bool allow_new = false;
-  bool overlayable = false;
+  std::vector<Overlayable> overlayable_declarations;
 
   std::string comment;
   std::unique_ptr<Value> value;
@@ -133,11 +133,8 @@
     }
   }
 
-  if (res->overlayable) {
-    Overlayable overlayable;
-    overlayable.source = res->source;
-    overlayable.comment = res->comment;
-    if (!table->SetOverlayable(res->name, overlayable, diag)) {
+  for (auto& overlayable : res->overlayable_declarations) {
+    if (!table->AddOverlayable(res->name, overlayable, diag)) {
       return false;
     }
   }
@@ -673,7 +670,7 @@
   if (can_be_bag) {
     const auto bag_iter = elToBagMap.find(resource_type);
     if (bag_iter != elToBagMap.end()) {
-      // Ensure we have a name (unless this is a <public-group>).
+      // Ensure we have a name (unless this is a <public-group> or <overlayable>).
       if (resource_type != "public-group" && resource_type != "overlayable") {
         if (!maybe_name) {
           diag_->Error(DiagMessage(out_resource->source)
@@ -1062,74 +1059,137 @@
 bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource* out_resource) {
   if (out_resource->config != ConfigDescription::DefaultConfig()) {
     diag_->Warn(DiagMessage(out_resource->source)
-                << "ignoring configuration '" << out_resource->config << "' for <overlayable> tag");
+                    << "ignoring configuration '" << out_resource->config
+                    << "' for <overlayable> tag");
   }
 
-  if (Maybe<StringPiece> maybe_policy = xml::FindNonEmptyAttribute(parser, "policy")) {
-    const StringPiece& policy = maybe_policy.value();
-    if (policy != "system") {
-      diag_->Error(DiagMessage(out_resource->source)
-                   << "<overlayable> has invalid policy '" << policy << "'");
-      return false;
-    }
-  }
+  std::string comment;
+  std::vector<Overlayable::Policy> policies;
 
   bool error = false;
-  const size_t depth = parser->depth();
-  while (xml::XmlPullParser::NextChildNode(parser, depth)) {
-    if (parser->event() != xml::XmlPullParser::Event::kStartElement) {
-      // Skip text/comments.
+  const size_t start_depth = parser->depth();
+  while (xml::XmlPullParser::IsGoodEvent(parser->Next())) {
+    xml::XmlPullParser::Event event = parser->event();
+    if (event == xml::XmlPullParser::Event::kEndElement && parser->depth() == start_depth) {
+      // Break the loop when exiting the overyabale element
+      break;
+    } else if (event == xml::XmlPullParser::Event::kEndElement
+               && parser->depth() == start_depth + 1) {
+      // Clear the current policies when exiting the policy element
+      policies.clear();
+      continue;
+    } else if (event == xml::XmlPullParser::Event::kComment) {
+      // Get the comment of individual item elements
+      comment = parser->comment();
+      continue;
+    } else if (event != xml::XmlPullParser::Event::kStartElement) {
+      // Skip to the next element
       continue;
     }
 
     const Source item_source = source_.WithLine(parser->line_number());
-    const std::string& element_namespace = parser->element_namespace();
     const std::string& element_name = parser->element_name();
+    const std::string& element_namespace = parser->element_namespace();
+
     if (element_namespace.empty() && element_name == "item") {
-      Maybe<StringPiece> maybe_name = xml::FindNonEmptyAttribute(parser, "name");
-      if (!maybe_name) {
-        diag_->Error(DiagMessage(item_source)
-                     << "<item> within an <overlayable> tag must have a 'name' attribute");
+      if (!ParseOverlayableItem(parser, policies, comment, out_resource)) {
         error = true;
-        continue;
       }
-
-      Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type");
-      if (!maybe_type) {
-        diag_->Error(DiagMessage(item_source)
-                     << "<item> within an <overlayable> tag must have a 'type' attribute");
+    } else if (element_namespace.empty() && element_name == "policy") {
+      if (!policies.empty()) {
+        // If the policy list is not empty, then we are currently inside a policy element
+        diag_->Error(DiagMessage(item_source) << "<policy> blocks cannot be recursively nested");
         error = true;
-        continue;
+        break;
+      } else if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) {
+        // Parse the polices separated by vertical bar characters to allow for specifying multiple
+        // policies at once
+        for (StringPiece part : util::Tokenize(maybe_type.value(), '|')) {
+          StringPiece trimmed_part = util::TrimWhitespace(part);
+          if (trimmed_part == "public") {
+            policies.push_back(Overlayable::Policy::kPublic);
+          } else if (trimmed_part == "product") {
+            policies.push_back(Overlayable::Policy::kProduct);
+          } else if (trimmed_part == "product_services") {
+            policies.push_back(Overlayable::Policy::kProductServices);
+          } else if (trimmed_part == "system") {
+            policies.push_back(Overlayable::Policy::kSystem);
+          } else if (trimmed_part == "vendor") {
+            policies.push_back(Overlayable::Policy::kVendor);
+          } else {
+            diag_->Error(DiagMessage(out_resource->source)
+                             << "<policy> has unsupported type '" << trimmed_part << "'");
+            error = true;
+            continue;
+          }
+        }
       }
-
-      const ResourceType* type = ParseResourceType(maybe_type.value());
-      if (type == nullptr) {
-        diag_->Error(DiagMessage(out_resource->source)
-                     << "invalid resource type '" << maybe_type.value()
-                     << "' in <item> within an <overlayable>");
-        error = true;
-        continue;
-      }
-
-      ParsedResource child_resource;
-      child_resource.name.type = *type;
-      child_resource.name.entry = maybe_name.value().to_string();
-      child_resource.source = item_source;
-      child_resource.overlayable = true;
-      if (options_.visibility) {
-        child_resource.visibility_level = options_.visibility.value();
-      }
-      out_resource->child_resources.push_back(std::move(child_resource));
-
-      xml::XmlPullParser::SkipCurrentElement(parser);
     } else if (!ShouldIgnoreElement(element_namespace, element_name)) {
-      diag_->Error(DiagMessage(item_source) << ":" << element_name << ">");
+      diag_->Error(DiagMessage(item_source) << "invalid element <" << element_name << "> in "
+                                            << " <overlayable>");
       error = true;
+      break;
     }
   }
+
   return !error;
 }
 
+bool ResourceParser::ParseOverlayableItem(xml::XmlPullParser* parser,
+                                          const std::vector<Overlayable::Policy>& policies,
+                                          const std::string& comment,
+                                          ParsedResource* out_resource) {
+  const Source item_source = source_.WithLine(parser->line_number());
+
+  Maybe<StringPiece> maybe_name = xml::FindNonEmptyAttribute(parser, "name");
+  if (!maybe_name) {
+    diag_->Error(DiagMessage(item_source)
+                     << "<item> within an <overlayable> tag must have a 'name' attribute");
+    return false;
+  }
+
+  Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type");
+  if (!maybe_type) {
+    diag_->Error(DiagMessage(item_source)
+                     << "<item> within an <overlayable> tag must have a 'type' attribute");
+    return false;
+  }
+
+  const ResourceType* type = ParseResourceType(maybe_type.value());
+  if (type == nullptr) {
+    diag_->Error(DiagMessage(out_resource->source)
+                     << "invalid resource type '" << maybe_type.value()
+                     << "' in <item> within an <overlayable>");
+    return false;
+  }
+
+  ParsedResource child_resource;
+  child_resource.name.type = *type;
+  child_resource.name.entry = maybe_name.value().to_string();
+  child_resource.source = item_source;
+
+  if (policies.empty()) {
+    Overlayable overlayable;
+    overlayable.source = item_source;
+    overlayable.comment = comment;
+    child_resource.overlayable_declarations.push_back(overlayable);
+  } else {
+    for (Overlayable::Policy policy : policies) {
+      Overlayable overlayable;
+      overlayable.policy = policy;
+      overlayable.source = item_source;
+      overlayable.comment = comment;
+      child_resource.overlayable_declarations.push_back(overlayable);
+    }
+  }
+
+  if (options_.visibility) {
+    child_resource.visibility_level = options_.visibility.value();
+  }
+  out_resource->child_resources.push_back(std::move(child_resource));
+  return true;
+}
+
 bool ResourceParser::ParseAddResource(xml::XmlPullParser* parser, ParsedResource* out_resource) {
   if (ParseSymbolImpl(parser, out_resource)) {
     out_resource->visibility_level = Visibility::Level::kUndefined;
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
index 06bb0c9..ebacd6f 100644
--- a/tools/aapt2/ResourceParser.h
+++ b/tools/aapt2/ResourceParser.h
@@ -96,6 +96,10 @@
   bool ParseSymbolImpl(xml::XmlPullParser* parser, ParsedResource* out_resource);
   bool ParseSymbol(xml::XmlPullParser* parser, ParsedResource* out_resource);
   bool ParseOverlayable(xml::XmlPullParser* parser, ParsedResource* out_resource);
+  bool ParseOverlayableItem(xml::XmlPullParser* parser,
+                            const std::vector<Overlayable::Policy>& policies,
+                            const std::string& comment,
+                            ParsedResource* out_resource);
   bool ParseAddResource(xml::XmlPullParser* parser, ParsedResource* out_resource);
   bool ParseAttr(xml::XmlPullParser* parser, ParsedResource* out_resource);
   bool ParseAttrImpl(xml::XmlPullParser* parser, ParsedResource* out_resource, bool weak);
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 0dff664..c6f29ac 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -891,56 +891,162 @@
   ASSERT_TRUE(TestParse(R"(<string name="foo">%1$s %n %2$s</string>)"));
 }
 
-TEST_F(ResourceParserTest, ParseOverlayableTagWithSystemPolicy) {
-  std::string input = R"(
-      <overlayable policy="illegal_policy">
-        <item type="string" name="foo" />
-      </overlayable>)";
-  EXPECT_FALSE(TestParse(input));
-
-  input = R"(
-      <overlayable policy="system">
-        <item name="foo" />
-      </overlayable>)";
-  EXPECT_FALSE(TestParse(input));
-
-  input = R"(
-      <overlayable policy="system">
-        <item type="attr" />
-      </overlayable>)";
-  EXPECT_FALSE(TestParse(input));
-
-  input = R"(
-      <overlayable policy="system">
-        <item type="bad_type" name="foo" />
-      </overlayable>)";
-  EXPECT_FALSE(TestParse(input));
-
-  input = R"(<overlayable policy="system" />)";
+TEST_F(ResourceParserTest, ParseOverlayable) {
+  std::string input = R"(<overlayable />)";
   EXPECT_TRUE(TestParse(input));
 
-  input = R"(<overlayable />)";
-  EXPECT_TRUE(TestParse(input));
-
-  input = R"(
-      <overlayable policy="system">
-        <item type="string" name="foo" />
-        <item type="dimen" name="foo" />
-      </overlayable>)";
-  ASSERT_TRUE(TestParse(input));
-
   input = R"(
       <overlayable>
-        <item type="string" name="bar" />
+        <item type="string" name="foo" />
+        <item type="drawable" name="bar" />
       </overlayable>)";
   ASSERT_TRUE(TestParse(input));
 
-  Maybe<ResourceTable::SearchResult> search_result =
-      table_.FindResource(test::ParseNameOrDie("string/bar"));
+  auto search_result = table_.FindResource(test::ParseNameOrDie("string/foo"));
   ASSERT_TRUE(search_result);
   ASSERT_THAT(search_result.value().entry, NotNull());
   EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
-  EXPECT_TRUE(search_result.value().entry->overlayable);
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations.size(), Eq(1));
+  EXPECT_FALSE(search_result.value().entry->overlayable_declarations[0].policy);
+
+  search_result = table_.FindResource(test::ParseNameOrDie("drawable/bar"));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations.size(), Eq(1));
+  EXPECT_FALSE(search_result.value().entry->overlayable_declarations[0].policy);
+}
+
+TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
+  std::string input = R"(<overlayable />)";
+  EXPECT_TRUE(TestParse(input));
+
+  input = R"(
+      <overlayable>
+        <item type="string" name="foo" />
+        <policy type="product">
+          <item type="string" name="bar" />
+        </policy>
+        <policy type="product_services">
+          <item type="string" name="baz" />
+        </policy>
+        <policy type="system">
+          <item type="string" name="fiz" />
+        </policy>
+        <policy type="vendor">
+          <item type="string" name="fuz" />
+        </policy>
+        <policy type="public">
+          <item type="string" name="faz" />
+        </policy>
+      </overlayable>)";
+  ASSERT_TRUE(TestParse(input));
+
+  auto search_result = table_.FindResource(test::ParseNameOrDie("string/foo"));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations.size(), Eq(1));
+  EXPECT_FALSE(search_result.value().entry->overlayable_declarations[0].policy);
+
+  search_result = table_.FindResource(test::ParseNameOrDie("string/bar"));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations.size(), Eq(1));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kProduct));
+
+  search_result = table_.FindResource(test::ParseNameOrDie("string/baz"));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations.size(), Eq(1));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kProductServices));
+
+  search_result = table_.FindResource(test::ParseNameOrDie("string/fiz"));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations.size(), Eq(1));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kSystem));
+
+  search_result = table_.FindResource(test::ParseNameOrDie("string/fuz"));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations.size(), Eq(1));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kVendor));
+
+  search_result = table_.FindResource(test::ParseNameOrDie("string/faz"));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations.size(), Eq(1));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kPublic));
+}
+
+TEST_F(ResourceParserTest, ParseOverlayableBadPolicyError) {
+  std::string input = R"(
+      <overlayable>
+        <policy type="illegal_policy">
+          <item type="string" name="foo" />
+        </policy>
+      </overlayable>)";
+  EXPECT_FALSE(TestParse(input));
+
+  input = R"(
+      <overlayable>
+        <policy type="product">
+          <item name="foo" />
+        </policy>
+      </overlayable>)";
+  EXPECT_FALSE(TestParse(input));
+
+  input = R"(
+      <overlayable>
+        <policy type="vendor">
+          <item type="string" />
+        </policy>
+      </overlayable>)";
+  EXPECT_FALSE(TestParse(input));
+}
+
+TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) {
+  std::string input = R"(
+      <overlayable>
+        <policy type="vendor|product_services">
+          <item type="string" name="foo" />
+        </policy>
+        <policy type="product|system">
+          <item type="string" name="bar" />
+        </policy>
+      </overlayable>)";
+  ASSERT_TRUE(TestParse(input));
+
+  auto search_result = table_.FindResource(test::ParseNameOrDie("string/foo"));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations.size(), Eq(2));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kVendor));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations[1].policy,
+              Eq(Overlayable::Policy::kProductServices));
+
+  search_result = table_.FindResource(test::ParseNameOrDie("string/bar"));
+  ASSERT_TRUE(search_result);
+  ASSERT_THAT(search_result.value().entry, NotNull());
+  EXPECT_THAT(search_result.value().entry->visibility.level, Eq(Visibility::Level::kUndefined));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations.size(), Eq(2));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kProduct));
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations[1].policy,
+              Eq(Overlayable::Policy::kSystem));
 }
 
 TEST_F(ResourceParserTest, DuplicateOverlayableIsError) {
@@ -950,6 +1056,85 @@
         <item type="string" name="foo" />
       </overlayable>)";
   EXPECT_FALSE(TestParse(input));
+
+  input = R"(
+      <overlayable>
+        <item type="string" name="foo" />
+      </overlayable>
+      <overlayable>
+        <item type="string" name="foo" />
+      </overlayable>)";
+  EXPECT_FALSE(TestParse(input));
+
+  input = R"(
+      <overlayable">
+        <policy type="product">
+          <item type="string" name="foo" />
+          <item type="string" name="foo" />
+        </policy>
+      </overlayable>)";
+  EXPECT_FALSE(TestParse(input));
+
+  input = R"(
+      <overlayable>
+        <policy type="product">
+          <item type="string" name="foo" />
+        </policy>
+      </overlayable>
+
+      <overlayable>
+        <policy type="product">
+          <item type="string" name="foo" />
+        </policy>
+      </overlayable>)";
+  EXPECT_FALSE(TestParse(input));
+}
+
+TEST_F(ResourceParserTest, PolicyAndNonPolicyOverlayableError) {
+  std::string input = R"(
+        <overlayable policy="product">
+          <item type="string" name="foo" />
+        </overlayable>
+        <overlayable policy="">
+          <item type="string" name="foo" />
+        </overlayable>)";
+  EXPECT_FALSE(TestParse(input));
+
+  input = R"(
+        <overlayable policy="">
+          <item type="string" name="foo" />
+        </overlayable>
+        <overlayable policy="product">
+          <item type="string" name="foo" />
+        </overlayable>)";
+  EXPECT_FALSE(TestParse(input));
+}
+
+TEST_F(ResourceParserTest, DuplicateOverlayableMultiplePolicyError) {
+  std::string input = R"(
+      <overlayable>
+        <policy type="vendor|product">
+          <item type="string" name="foo" />
+        </policy>
+      </overlayable>
+      <overlayable>
+        <policy type="product_services|vendor">
+          <item type="string" name="foo" />
+        </policy>
+      </overlayable>)";
+  EXPECT_FALSE(TestParse(input));
+}
+
+TEST_F(ResourceParserTest, NestPolicyInOverlayableError) {
+  std::string input = R"(
+      <overlayable>
+        <policy type="vendor|product">
+          <policy type="product_services">
+            <item type="string" name="foo" />
+          </policy>
+        </policy>
+      </overlayable>)";
+  EXPECT_FALSE(TestParse(input));
 }
 
 TEST_F(ResourceParserTest, ParseIdItem) {
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index 056a27b..bc8a4d1 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -625,17 +625,17 @@
   return true;
 }
 
-bool ResourceTable::SetOverlayable(const ResourceNameRef& name, const Overlayable& overlayable,
+bool ResourceTable::AddOverlayable(const ResourceNameRef& name, const Overlayable& overlayable,
                                    IDiagnostics* diag) {
-  return SetOverlayableImpl(name, overlayable, ResourceNameValidator, diag);
+  return AddOverlayableImpl(name, overlayable, ResourceNameValidator, diag);
 }
 
-bool ResourceTable::SetOverlayableMangled(const ResourceNameRef& name,
+bool ResourceTable::AddOverlayableMangled(const ResourceNameRef& name,
                                           const Overlayable& overlayable, IDiagnostics* diag) {
-  return SetOverlayableImpl(name, overlayable, SkipNameValidator, diag);
+  return AddOverlayableImpl(name, overlayable, SkipNameValidator, diag);
 }
 
-bool ResourceTable::SetOverlayableImpl(const ResourceNameRef& name, const Overlayable& overlayable,
+bool ResourceTable::AddOverlayableImpl(const ResourceNameRef& name, const Overlayable& overlayable,
                                        NameValidator name_validator, IDiagnostics* diag) {
   CHECK(diag != nullptr);
 
@@ -646,13 +646,28 @@
   ResourceTablePackage* package = FindOrCreatePackage(name.package);
   ResourceTableType* type = package->FindOrCreateType(name.type);
   ResourceEntry* entry = type->FindOrCreateEntry(name.entry);
-  if (entry->overlayable) {
-    diag->Error(DiagMessage(overlayable.source)
-                << "duplicate overlayable declaration for resource '" << name << "'");
-    diag->Error(DiagMessage(entry->overlayable.value().source) << "previous declaration here");
-    return false;
+
+  for (auto& overlayable_declaration : entry->overlayable_declarations) {
+    // An overlayable resource cannot be declared twice with the same policy
+    if (overlayable.policy == overlayable_declaration.policy) {
+      diag->Error(DiagMessage(overlayable.source)
+                    << "duplicate overlayable declaration for resource '" << name << "'");
+      diag->Error(DiagMessage(overlayable_declaration.source) << "previous declaration here");
+      return false;
+    }
+
+    // An overlayable resource cannot be declared once with a policy and without a policy because
+    // the policy becomes unused
+    if (!overlayable.policy || !overlayable_declaration.policy) {
+      diag->Error(DiagMessage(overlayable.source)
+                    << "overlayable resource '" << name << "'"
+                    << " declared once with a policy and once with no policy");
+      diag->Error(DiagMessage(overlayable_declaration.source) << "previous declaration here");
+      return false;
+    }
   }
-  entry->overlayable = overlayable;
+
+  entry->overlayable_declarations.push_back(overlayable);
   return true;
 }
 
@@ -688,7 +703,7 @@
         new_entry->id = entry->id;
         new_entry->visibility = entry->visibility;
         new_entry->allow_new = entry->allow_new;
-        new_entry->overlayable = entry->overlayable;
+        new_entry->overlayable_declarations = entry->overlayable_declarations;
 
         for (const auto& config_value : entry->values) {
           ResourceConfigValue* new_value =
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 1917d7e..3dd0a769 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -57,8 +57,27 @@
   std::string comment;
 };
 
-// The policy dictating whether an entry is overlayable at runtime by RROs.
+// Represents a declaration that a resource is overayable at runtime.
 struct Overlayable {
+  // Represents the types overlays that are allowed to overlay the resource.
+  enum class Policy {
+    // The resource can be overlaid by any overlay.
+    kPublic,
+
+    // The resource can be overlaid by any overlay on the system partition.
+    kSystem,
+
+    // The resource can be overlaid by any overlay on the vendor partition.
+    kVendor,
+
+    // The resource can be overlaid by any overlay on the product partition.
+    kProduct,
+
+    // The resource can be overlaid by any overlay on the product services partition.
+    kProductServices,
+  };
+
+  Maybe<Policy> policy;
   Source source;
   std::string comment;
 };
@@ -96,7 +115,8 @@
 
   Maybe<AllowNew> allow_new;
 
-  Maybe<Overlayable> overlayable;
+  // The declarations of this resource as overlayable for RROs
+  std::vector<Overlayable> overlayable_declarations;
 
   // The resource's values for each configuration.
   std::vector<std::unique_ptr<ResourceConfigValue>> values;
@@ -226,9 +246,9 @@
   bool SetVisibilityWithIdMangled(const ResourceNameRef& name, const Visibility& visibility,
                                   const ResourceId& res_id, IDiagnostics* diag);
 
-  bool SetOverlayable(const ResourceNameRef& name, const Overlayable& overlayable,
+  bool AddOverlayable(const ResourceNameRef& name, const Overlayable& overlayable,
                       IDiagnostics* diag);
-  bool SetOverlayableMangled(const ResourceNameRef& name, const Overlayable& overlayable,
+  bool AddOverlayableMangled(const ResourceNameRef& name, const Overlayable& overlayable,
                              IDiagnostics* diag);
 
   bool SetAllowNew(const ResourceNameRef& name, const AllowNew& allow_new, IDiagnostics* diag);
@@ -303,7 +323,7 @@
   bool SetAllowNewImpl(const ResourceNameRef& name, const AllowNew& allow_new,
                        NameValidator name_validator, IDiagnostics* diag);
 
-  bool SetOverlayableImpl(const ResourceNameRef& name, const Overlayable& overlayable,
+  bool AddOverlayableImpl(const ResourceNameRef& name, const Overlayable& overlayable,
                           NameValidator name_validator, IDiagnostics* diag);
 
   bool SetSymbolStateImpl(const ResourceNameRef& name, const ResourceId& res_id,
diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp
index 05c6f15..7c28f07 100644
--- a/tools/aapt2/ResourceTable_test.cpp
+++ b/tools/aapt2/ResourceTable_test.cpp
@@ -242,21 +242,69 @@
   ASSERT_THAT(result.value().entry->allow_new.value().comment, StrEq("second"));
 }
 
-TEST(ResourceTableTest, SetOverlayable) {
+TEST(ResourceTableTest, AddOverlayable) {
   ResourceTable table;
   const ResourceName name = test::ParseNameOrDie("android:string/foo");
 
   Overlayable overlayable;
-
+  overlayable.policy = Overlayable::Policy::kProduct;
   overlayable.comment = "first";
-  ASSERT_TRUE(table.SetOverlayable(name, overlayable, test::GetDiagnostics()));
+  ASSERT_TRUE(table.AddOverlayable(name, overlayable, test::GetDiagnostics()));
   Maybe<ResourceTable::SearchResult> result = table.FindResource(name);
   ASSERT_TRUE(result);
-  ASSERT_TRUE(result.value().entry->overlayable);
-  ASSERT_THAT(result.value().entry->overlayable.value().comment, StrEq("first"));
+  ASSERT_THAT(result.value().entry->overlayable_declarations.size(), Eq(1));
+  ASSERT_THAT(result.value().entry->overlayable_declarations[0].comment, StrEq("first"));
+  ASSERT_THAT(result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kProduct));
 
-  overlayable.comment = "second";
-  ASSERT_FALSE(table.SetOverlayable(name, overlayable, test::GetDiagnostics()));
+  Overlayable overlayable2;
+  overlayable2.comment = "second";
+  overlayable2.policy = Overlayable::Policy::kProductServices;
+  ASSERT_TRUE(table.AddOverlayable(name, overlayable2, test::GetDiagnostics()));
+  result = table.FindResource(name);
+  ASSERT_TRUE(result);
+  ASSERT_THAT(result.value().entry->overlayable_declarations.size(), Eq(2));
+  ASSERT_THAT(result.value().entry->overlayable_declarations[0].comment, StrEq("first"));
+  ASSERT_THAT(result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kProduct));
+  ASSERT_THAT(result.value().entry->overlayable_declarations[1].comment, StrEq("second"));
+  ASSERT_THAT(result.value().entry->overlayable_declarations[1].policy,
+              Eq(Overlayable::Policy::kProductServices));
+}
+
+TEST(ResourceTableTest, AddDuplicateOverlayableFail) {
+  ResourceTable table;
+  const ResourceName name = test::ParseNameOrDie("android:string/foo");
+
+  Overlayable overlayable;
+  overlayable.policy = Overlayable::Policy::kProduct;
+  ASSERT_TRUE(table.AddOverlayable(name, overlayable, test::GetDiagnostics()));
+
+  Overlayable overlayable2;
+  overlayable2.policy = Overlayable::Policy::kProduct;
+  ASSERT_FALSE(table.AddOverlayable(name, overlayable2, test::GetDiagnostics()));
+}
+
+TEST(ResourceTableTest, AddOverlayablePolicyAndNoneFirstFail) {
+  ResourceTable table;
+  const ResourceName name = test::ParseNameOrDie("android:string/foo");
+
+  ASSERT_TRUE(table.AddOverlayable(name, {}, test::GetDiagnostics()));
+
+  Overlayable overlayable2;
+  overlayable2.policy = Overlayable::Policy::kProduct;
+  ASSERT_FALSE(table.AddOverlayable(name, overlayable2, test::GetDiagnostics()));
+}
+
+TEST(ResourceTableTest, AddOverlayablePolicyAndNoneLastFail) {
+  ResourceTable table;
+  const ResourceName name = test::ParseNameOrDie("android:string/foo");
+
+  Overlayable overlayable;
+  overlayable.policy = Overlayable::Policy::kProduct;
+  ASSERT_TRUE(table.AddOverlayable(name, overlayable, test::GetDiagnostics()));
+
+  ASSERT_FALSE(table.AddOverlayable(name, {}, test::GetDiagnostics()));
 }
 
 TEST(ResourceTableTest, AllowDuplictaeResourcesNames) {
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index dbe5ac5..da22e88 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -718,7 +718,7 @@
           // This must be a FileReference.
           std::unique_ptr<FileReference> file_ref =
               util::make_unique<FileReference>(dst_pool->MakeRef(
-                  str, StringPool::Context(StringPool::Context::kHighPriority, config)));
+                  str, StringPool::Context(StringPool::Context::kHighPriority, config), data));
           if (type == ResourceType::kRaw) {
             file_ref->type = ResourceFile::Type::kUnknown;
           } else if (util::EndsWith(*file_ref->path, ".xml")) {
@@ -730,7 +730,7 @@
         }
 
         // There are no styles associated with this string, so treat it as a simple string.
-        return util::make_unique<String>(dst_pool->MakeRef(str, StringPool::Context(config)));
+        return util::make_unique<String>(dst_pool->MakeRef(str, StringPool::Context(config), data));
       }
     } break;
 
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index d7a3771..bf9fe49 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -133,13 +133,25 @@
   string comment = 2;
 }
 
-// Whether a resource is overlayable by runtime resource overlays (RRO).
+// Represents a declaration that a resource is overayable at runtime.
 message Overlayable {
+  enum Policy {
+    NONE = 0;
+    PUBLIC = 1;
+    SYSTEM = 2;
+    VENDOR = 3;
+    PRODUCT = 4;
+    PRODUCT_SERVICES = 5;
+  }
+
   // Where this declaration was defined in source.
   Source source = 1;
 
   // Any comment associated with the declaration.
   string comment = 2;
+
+  // The policy of the overlayable declaration
+  Policy policy = 3;
 }
 
 // An entry ID in the range [0x0000, 0xffff].
@@ -169,7 +181,7 @@
   AllowNew allow_new = 4;
 
   // Whether this resource can be overlaid by a runtime resource overlay (RRO).
-  Overlayable overlayable = 5;
+  repeated Overlayable overlayable = 5;
 
   // The set of values defined for this entry, each corresponding to a different
   // configuration/variant.
diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp
index 8eabd32..a8c2666 100644
--- a/tools/aapt2/StringPool.cpp
+++ b/tools/aapt2/StringPool.cpp
@@ -165,12 +165,13 @@
   return MakeRefImpl(str, Context{}, true);
 }
 
-StringPool::Ref StringPool::MakeRef(const StringPiece& str, const Context& context) {
-  return MakeRefImpl(str, context, true);
+StringPool::Ref StringPool::MakeRef(const StringPiece& str, const Context& context,
+                                    Maybe<size_t> index) {
+  return MakeRefImpl(str, context, true, index);
 }
 
 StringPool::Ref StringPool::MakeRefImpl(const StringPiece& str, const Context& context,
-                                        bool unique) {
+                                        bool unique, Maybe<size_t> index) {
   if (unique) {
     auto range = indexed_strings_.equal_range(str);
     for (auto iter = range.first; iter != range.second; ++iter) {
@@ -180,15 +181,26 @@
     }
   }
 
+  const size_t size = strings_.size();
+  // Insert the string at the end of the string vector if no index is specified
+  const size_t insertion_index = index ? index.value() : size;
+
   std::unique_ptr<Entry> entry(new Entry());
   entry->value = str.to_string();
   entry->context = context;
-  entry->index_ = strings_.size();
+  entry->index_ = insertion_index;
   entry->ref_ = 0;
   entry->pool_ = this;
 
   Entry* borrow = entry.get();
-  strings_.emplace_back(std::move(entry));
+  if (insertion_index == size) {
+    strings_.emplace_back(std::move(entry));
+  } else {
+    // Allocate enough space for the string at the index
+    strings_.resize(std::max(insertion_index + 1, size));
+    strings_[insertion_index] = std::move(entry);
+  }
+
   indexed_strings_.insert(std::make_pair(StringPiece(borrow->value), borrow));
   return Ref(borrow);
 }
diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h
index 1006ca9..115d5d3 100644
--- a/tools/aapt2/StringPool.h
+++ b/tools/aapt2/StringPool.h
@@ -166,7 +166,8 @@
 
   // Adds a string to the pool, unless it already exists, with a context object that can be used
   // when sorting the string pool. Returns a reference to the string in the pool.
-  Ref MakeRef(const android::StringPiece& str, const Context& context);
+  Ref MakeRef(const android::StringPiece& str, const Context& context,
+              Maybe<size_t> index = {});
 
   // Adds a string from another string pool. Returns a reference to the string in the string pool.
   Ref MakeRef(const Ref& ref);
@@ -210,7 +211,8 @@
 
   static bool Flatten(BigBuffer* out, const StringPool& pool, bool utf8, IDiagnostics* diag);
 
-  Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique);
+  Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique,
+                  Maybe<size_t> index = {});
   void ReAssignIndices();
 
   std::vector<std::unique_ptr<Entry>> strings_;
diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp
index 9a7238b..648be7d 100644
--- a/tools/aapt2/StringPool_test.cpp
+++ b/tools/aapt2/StringPool_test.cpp
@@ -84,6 +84,24 @@
   EXPECT_THAT(ref_c.index(), Eq(2u));
 }
 
+TEST(StringPoolTest, AssignStringIndex) {
+  StringPool pool;
+
+  StringPool::Ref ref_a = pool.MakeRef("0", StringPool::Context{}, 0u);
+  StringPool::Ref ref_b = pool.MakeRef("1", StringPool::Context{}, 1u);
+  StringPool::Ref ref_c = pool.MakeRef("5", StringPool::Context{}, 5u);
+  StringPool::Ref ref_d = pool.MakeRef("2", StringPool::Context{}, 2u);
+  StringPool::Ref ref_e = pool.MakeRef("4", StringPool::Context{}, 4u);
+  StringPool::Ref ref_f = pool.MakeRef("3", StringPool::Context{}, 3u);
+
+  EXPECT_THAT(ref_a.index(), Eq(0u));
+  EXPECT_THAT(ref_b.index(), Eq(1u));
+  EXPECT_THAT(ref_d.index(), Eq(2u));
+  EXPECT_THAT(ref_f.index(), Eq(3u));
+  EXPECT_THAT(ref_e.index(), Eq(4u));
+  EXPECT_THAT(ref_c.index(), Eq(5u));
+}
+
 TEST(StringPoolTest, PruneStringsWithNoReferences) {
   StringPool pool;
 
diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp
index 3ea1755..4492f6b 100644
--- a/tools/aapt2/cmd/Convert.cpp
+++ b/tools/aapt2/cmd/Convert.cpp
@@ -57,78 +57,6 @@
   Source source_;
 };
 
-bool ConvertApk(IAaptContext* context, unique_ptr<LoadedApk> apk, IApkSerializer* serializer,
-                IArchiveWriter* writer) {
-  io::IFile* manifest = apk->GetFileCollection()->FindFile(kAndroidManifestPath);
-  if (!serializer->SerializeXml(apk->GetManifest(), kAndroidManifestPath, true /*utf16*/, writer,
-                                (manifest != nullptr && manifest->WasCompressed())
-                                    ? ArchiveEntry::kCompress : 0u)) {
-    context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
-                                     << "failed to serialize AndroidManifest.xml");
-    return false;
-  }
-
-  if (apk->GetResourceTable() != nullptr) {
-    // The table might be modified by below code.
-    auto converted_table = apk->GetResourceTable();
-
-    // Resources
-    for (const auto& package : converted_table->packages) {
-      for (const auto& type : package->types) {
-        for (const auto& entry : type->entries) {
-          for (const auto& config_value : entry->values) {
-            FileReference* file = ValueCast<FileReference>(config_value->value.get());
-            if (file != nullptr) {
-              if (file->file == nullptr) {
-                context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
-                                                 << "no file associated with " << *file);
-                return false;
-              }
-
-              if (!serializer->SerializeFile(file, writer)) {
-                context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
-                                                 << "failed to serialize file " << *file->path);
-                return false;
-              }
-            } // file
-          } // config_value
-        } // entry
-      } // type
-    } // package
-
-    // Converted resource table
-    if (!serializer->SerializeTable(converted_table, writer)) {
-      context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
-                                       << "failed to serialize the resource table");
-      return false;
-    }
-  }
-
-  // Other files
-  std::unique_ptr<io::IFileCollectionIterator> iterator = apk->GetFileCollection()->Iterator();
-  while (iterator->HasNext()) {
-    io::IFile* file = iterator->Next();
-    std::string path = file->GetSource().path;
-
-    // Manifest, resource table and resources have already been taken care of.
-    if (path == kAndroidManifestPath ||
-        path == kApkResourceTablePath ||
-        path == kProtoResourceTablePath ||
-        path.find("res/") == 0) {
-      continue;
-    }
-
-    if (!io::CopyFileToArchivePreserveCompression(context, file, path, writer)) {
-      context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
-                                       << "failed to copy file " << path);
-      return false;
-    }
-  }
-
-  return true;
-}
-
-
 class BinaryApkSerializer : public IApkSerializer {
  public:
   BinaryApkSerializer(IAaptContext* context, const Source& source,
@@ -323,12 +251,97 @@
   StdErrDiagnostics diag_;
 };
 
+int Convert(IAaptContext* context, LoadedApk* apk, IArchiveWriter* output_writer,
+            ApkFormat output_format, TableFlattenerOptions& options) {
+  // Do not change the ordering of strings in the values string pool
+  options.sort_stringpool_entries = false;
+
+  unique_ptr<IApkSerializer> serializer;
+  if (output_format == ApkFormat::kBinary) {
+    serializer.reset(new BinaryApkSerializer(context, apk->GetSource(), options));
+  } else if (output_format == ApkFormat::kProto) {
+    serializer.reset(new ProtoApkSerializer(context, apk->GetSource()));
+  } else {
+    context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+                                     << "Cannot convert APK to unknown format");
+    return 1;
+  }
+
+  io::IFile* manifest = apk->GetFileCollection()->FindFile(kAndroidManifestPath);
+  if (!serializer->SerializeXml(apk->GetManifest(), kAndroidManifestPath, true /*utf16*/,
+                                output_writer, (manifest != nullptr && manifest->WasCompressed())
+                                ? ArchiveEntry::kCompress : 0u)) {
+    context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+                                     << "failed to serialize AndroidManifest.xml");
+    return 1;
+  }
+
+  if (apk->GetResourceTable() != nullptr) {
+    // The table might be modified by below code.
+    auto converted_table = apk->GetResourceTable();
+
+    // Resources
+    for (const auto& package : converted_table->packages) {
+      for (const auto& type : package->types) {
+        for (const auto& entry : type->entries) {
+          for (const auto& config_value : entry->values) {
+            FileReference* file = ValueCast<FileReference>(config_value->value.get());
+            if (file != nullptr) {
+              if (file->file == nullptr) {
+                context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+                                                 << "no file associated with " << *file);
+                return 1;
+              }
+
+              if (!serializer->SerializeFile(file, output_writer)) {
+                context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+                                                 << "failed to serialize file " << *file->path);
+                return 1;
+              }
+            } // file
+          } // config_value
+        } // entry
+      } // type
+    } // package
+
+    // Converted resource table
+    if (!serializer->SerializeTable(converted_table, output_writer)) {
+      context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+                                       << "failed to serialize the resource table");
+      return 1;
+    }
+  }
+
+  // Other files
+  std::unique_ptr<io::IFileCollectionIterator> iterator = apk->GetFileCollection()->Iterator();
+  while (iterator->HasNext()) {
+    io::IFile* file = iterator->Next();
+    std::string path = file->GetSource().path;
+
+    // Manifest, resource table and resources have already been taken care of.
+    if (path == kAndroidManifestPath ||
+        path == kApkResourceTablePath ||
+        path == kProtoResourceTablePath ||
+        path.find("res/") == 0) {
+      continue;
+    }
+
+    if (!io::CopyFileToArchivePreserveCompression(context, file, path, output_writer)) {
+      context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+                                       << "failed to copy file " << path);
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
 const char* ConvertCommand::kOutputFormatProto = "proto";
 const char* ConvertCommand::kOutputFormatBinary = "binary";
 
 int ConvertCommand::Action(const std::vector<std::string>& args) {
   if (args.size() != 1) {
-    std::cerr << "must supply a single proto APK\n";
+    std::cerr << "must supply a single APK\n";
     Usage(&std::cerr);
     return 1;
   }
@@ -341,34 +354,31 @@
     return 1;
   }
 
-  Maybe<AppInfo> app_info =
-      ExtractAppInfoFromBinaryManifest(*apk->GetManifest(), context.GetDiagnostics());
+  Maybe<AppInfo> app_info = ExtractAppInfoFromBinaryManifest(*apk->GetManifest(),
+                                                             context.GetDiagnostics());
   if (!app_info) {
     return 1;
   }
 
   context.package_ = app_info.value().package;
-
-  unique_ptr<IArchiveWriter> writer =
-      CreateZipFileArchiveWriter(context.GetDiagnostics(), output_path_);
+  unique_ptr<IArchiveWriter> writer = CreateZipFileArchiveWriter(context.GetDiagnostics(),
+                                                                 output_path_);
   if (writer == nullptr) {
     return 1;
   }
 
-  unique_ptr<IApkSerializer> serializer;
+  ApkFormat format;
   if (!output_format_ || output_format_.value() == ConvertCommand::kOutputFormatBinary) {
-
-    serializer.reset(new BinaryApkSerializer(&context, apk->GetSource(), options_));
+    format = ApkFormat::kBinary;
   } else if (output_format_.value() == ConvertCommand::kOutputFormatProto) {
-    serializer.reset(new ProtoApkSerializer(&context, apk->GetSource()));
+    format = ApkFormat::kProto;
   } else {
-    context.GetDiagnostics()->Error(DiagMessage(path)
-        << "Invalid value for flag --output-format: "
-        << output_format_.value());
+    context.GetDiagnostics()->Error(DiagMessage(path) << "Invalid value for flag --output-format: "
+                                                      << output_format_.value());
     return 1;
   }
 
-  return ConvertApk(&context, std::move(apk), serializer.get(), writer.get()) ? 0 : 1;
+  return Convert(&context, apk.get(), writer.get(), format, options_);
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/cmd/Convert.h b/tools/aapt2/cmd/Convert.h
index fcec23d..6a6719c 100644
--- a/tools/aapt2/cmd/Convert.h
+++ b/tools/aapt2/cmd/Convert.h
@@ -18,6 +18,7 @@
 #define AAPT2_CONVERT_H
 
 #include "Command.h"
+#include "LoadedApk.h"
 #include "format/binary/TableFlattener.h"
 
 namespace aapt {
@@ -49,6 +50,9 @@
   bool verbose_ = false;
 };
 
-}// namespace aapt
+int Convert(IAaptContext* context, LoadedApk* input, IArchiveWriter* output_writer,
+            ApkFormat output_format, TableFlattenerOptions& options);
+
+}  // namespace aapt
 
 #endif //AAPT2_CONVERT_H
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index 3a39a6b..ed70fb3 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -398,7 +398,7 @@
       if (type_spec_flags & ResTable_typeSpec::SPEC_OVERLAYABLE) {
         Overlayable overlayable;
         overlayable.source = source_.WithLine(0);
-        if (!table_->SetOverlayableMangled(name, overlayable, diag_)) {
+        if (!table_->AddOverlayableMangled(name, overlayable, diag_)) {
           return false;
         }
       }
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index 8641a7c..6c1a9ba 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -446,7 +446,7 @@
         config_masks[entry->id.value()] |= util::HostToDevice32(ResTable_typeSpec::SPEC_PUBLIC);
       }
 
-      if (entry->overlayable) {
+      if (!entry->overlayable_declarations.empty()) {
         config_masks[entry->id.value()] |=
             util::HostToDevice32(ResTable_typeSpec::SPEC_OVERLAYABLE);
       }
@@ -573,15 +573,17 @@
 }  // namespace
 
 bool TableFlattener::Consume(IAaptContext* context, ResourceTable* table) {
-  // We must do this before writing the resources, since the string pool IDs may change.
-  table->string_pool.Prune();
-  table->string_pool.Sort([](const StringPool::Context& a, const StringPool::Context& b) -> int {
-    int diff = util::compare(a.priority, b.priority);
-    if (diff == 0) {
-      diff = a.config.compare(b.config);
-    }
-    return diff;
-  });
+  if (options_.sort_stringpool_entries) {
+    // We must do this before writing the resources, since the string pool IDs may change.
+    table->string_pool.Prune();
+    table->string_pool.Sort([](const StringPool::Context &a, const StringPool::Context &b) -> int {
+      int diff = util::compare(a.priority, b.priority);
+      if (diff == 0) {
+        diff = a.config.compare(b.config);
+      }
+      return diff;
+    });
+  }
 
   // Write the ResTable header.
   ChunkWriter table_writer(buffer_);
diff --git a/tools/aapt2/format/binary/TableFlattener.h b/tools/aapt2/format/binary/TableFlattener.h
index c2e1d4b..635cb21 100644
--- a/tools/aapt2/format/binary/TableFlattener.h
+++ b/tools/aapt2/format/binary/TableFlattener.h
@@ -43,6 +43,9 @@
 
   // Set of whitelisted resource names to avoid altering in key stringpool
   std::set<std::string> whitelisted_resources;
+
+  // When true, sort the entries in the values string pool by priority and configuration.
+  bool sort_stringpool_entries = true;
 };
 
 class TableFlattener : public IResourceTableConsumer {
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index af19b98..cd1414c 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -634,7 +634,7 @@
           .AddSimple("com.app.test:integer/overlayable", ResourceId(0x7f020000))
           .Build();
 
-  ASSERT_TRUE(table->SetOverlayable(test::ParseNameOrDie("com.app.test:integer/overlayable"),
+  ASSERT_TRUE(table->AddOverlayable(test::ParseNameOrDie("com.app.test:integer/overlayable"),
                                     Overlayable{}, test::GetDiagnostics()));
 
   ResTable res_table;
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index d1b2fdb..f612914 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -437,15 +437,37 @@
         entry->allow_new = std::move(allow_new);
       }
 
-      if (pb_entry.has_overlayable()) {
-        const pb::Overlayable& pb_overlayable = pb_entry.overlayable();
-
+      for (const pb::Overlayable& pb_overlayable : pb_entry.overlayable()) {
         Overlayable overlayable;
+        switch (pb_overlayable.policy()) {
+          case pb::Overlayable::NONE:
+            overlayable.policy = {};
+            break;
+          case pb::Overlayable::PUBLIC:
+            overlayable.policy = Overlayable::Policy::kPublic;
+            break;
+          case pb::Overlayable::PRODUCT:
+            overlayable.policy = Overlayable::Policy::kProduct;
+            break;
+          case pb::Overlayable::PRODUCT_SERVICES:
+            overlayable.policy = Overlayable::Policy::kProductServices;
+            break;
+          case pb::Overlayable::SYSTEM:
+            overlayable.policy = Overlayable::Policy::kSystem;
+            break;
+          case pb::Overlayable::VENDOR:
+            overlayable.policy = Overlayable::Policy::kVendor;
+            break;
+          default:
+            *out_error = "unknown overlayable policy";
+            return false;
+        }
+
         if (pb_overlayable.has_source()) {
           DeserializeSourceFromPb(pb_overlayable.source(), src_pool, &overlayable.source);
         }
         overlayable.comment = pb_overlayable.comment();
-        entry->overlayable = std::move(overlayable);
+        entry->overlayable_declarations.push_back(overlayable);
       }
 
       ResourceId resid(pb_package.package_id().id(), pb_type.type_id().id(),
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index 7e35ea7..f1e96d6 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -310,11 +310,31 @@
           pb_allow_new->set_comment(entry->allow_new.value().comment);
         }
 
-        if (entry->overlayable) {
-          pb::Overlayable* pb_overlayable = pb_entry->mutable_overlayable();
-          SerializeSourceToPb(entry->overlayable.value().source, &source_pool,
+        for (const Overlayable& overlayable : entry->overlayable_declarations) {
+          pb::Overlayable* pb_overlayable = pb_entry->add_overlayable();
+          if (overlayable.policy) {
+            switch (overlayable.policy.value()) {
+              case Overlayable::Policy::kPublic:
+                pb_overlayable->set_policy(pb::Overlayable::PUBLIC);
+                break;
+              case Overlayable::Policy::kProduct:
+                pb_overlayable->set_policy(pb::Overlayable::PRODUCT);
+                break;
+              case Overlayable::Policy::kProductServices:
+                pb_overlayable->set_policy(pb::Overlayable::PRODUCT_SERVICES);
+                break;
+              case Overlayable::Policy::kSystem:
+                pb_overlayable->set_policy(pb::Overlayable::SYSTEM);
+                break;
+              case Overlayable::Policy::kVendor:
+                pb_overlayable->set_policy(pb::Overlayable::VENDOR);
+                break;
+            }
+          }
+
+          SerializeSourceToPb(overlayable.source, &source_pool,
                               pb_overlayable->mutable_source());
-          pb_overlayable->set_comment(entry->overlayable.value().comment);
+          pb_overlayable->set_comment(overlayable.comment);
         }
 
         for (const std::unique_ptr<ResourceConfigValue>& config_value : entry->values) {
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index 3c4d41a..95dbbeb 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -93,7 +93,7 @@
       util::make_unique<Reference>(expected_ref), context->GetDiagnostics()));
 
   // Make an overlayable resource.
-  ASSERT_TRUE(table->SetOverlayable(test::ParseNameOrDie("com.app.a:integer/overlayable"),
+  ASSERT_TRUE(table->AddOverlayable(test::ParseNameOrDie("com.app.a:integer/overlayable"),
                                     Overlayable{}, test::GetDiagnostics()));
 
   pb::ResourceTable pb_table;
@@ -106,7 +106,7 @@
 
   ResourceTable new_table;
   std::string error;
-  ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error));
+  ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error)) << error;
   EXPECT_THAT(error, IsEmpty());
 
   Id* new_id = test::GetValue<Id>(&new_table, "com.app.a:id/foo");
@@ -160,7 +160,8 @@
       new_table.FindResource(test::ParseNameOrDie("com.app.a:integer/overlayable"));
   ASSERT_TRUE(search_result);
   ASSERT_THAT(search_result.value().entry, NotNull());
-  EXPECT_TRUE(search_result.value().entry->overlayable);
+  EXPECT_THAT(search_result.value().entry->overlayable_declarations.size(), Eq(1));
+  EXPECT_FALSE(search_result.value().entry->overlayable_declarations[0].policy);
 }
 
 TEST(ProtoSerializeTest, SerializeAndDeserializeXml) {
@@ -464,4 +465,59 @@
       "night-xhdpi-stylus-keysexposed-qwerty-navhidden-dpad-300x200-v23");
 }
 
+TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .AddOverlayable("com.app.a:bool/foo", Overlayable::Policy::kSystem)
+          .AddOverlayable("com.app.a:bool/foo", Overlayable::Policy::kProduct)
+          .AddOverlayable("com.app.a:bool/bar", Overlayable::Policy::kProductServices)
+          .AddOverlayable("com.app.a:bool/bar", Overlayable::Policy::kVendor)
+          .AddOverlayable("com.app.a:bool/baz", Overlayable::Policy::kPublic)
+          .AddOverlayable("com.app.a:bool/biz", {})
+          .AddValue("com.app.a:bool/fiz", ResourceUtils::TryParseBool("true"))
+          .Build();
+
+  pb::ResourceTable pb_table;
+  SerializeTableToPb(*table, &pb_table, context->GetDiagnostics());
+
+  MockFileCollection files;
+  ResourceTable new_table;
+  std::string error;
+  ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error));
+  EXPECT_THAT(error, IsEmpty());
+
+  Maybe<ResourceTable::SearchResult> result =
+      new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/foo"));
+  ASSERT_TRUE(result);
+  ASSERT_THAT(result.value().entry->overlayable_declarations.size(), Eq(2));
+  EXPECT_THAT(result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kSystem));
+  EXPECT_THAT(result.value().entry->overlayable_declarations[1].policy,
+              Eq(Overlayable::Policy::kProduct));
+
+  result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/bar"));
+  ASSERT_TRUE(result);
+  ASSERT_THAT(result.value().entry->overlayable_declarations.size(), Eq(2));
+  EXPECT_THAT(result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kProductServices));
+  EXPECT_THAT(result.value().entry->overlayable_declarations[1].policy,
+              Eq(Overlayable::Policy::kVendor));
+
+  result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/baz"));
+  ASSERT_TRUE(result);
+  ASSERT_THAT(result.value().entry->overlayable_declarations.size(), Eq(1));
+  EXPECT_THAT(result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kPublic));
+
+  result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/biz"));
+  ASSERT_TRUE(result);
+  ASSERT_THAT(result.value().entry->overlayable_declarations.size(), Eq(1));
+  EXPECT_FALSE(result.value().entry->overlayable_declarations[0].policy);
+
+  result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/fiz"));
+  ASSERT_TRUE(result);
+  EXPECT_THAT(result.value().entry->overlayable_declarations.size(), Eq(0));
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index afb8ae0..d777e22 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -101,7 +101,7 @@
   return true;
 }
 
-static bool MergeEntry(IAaptContext* context, const Source& src, bool overlay,
+static bool MergeEntry(IAaptContext* context, const Source& src,
                        ResourceEntry* dst_entry, ResourceEntry* src_entry,
                        bool strict_visibility) {
   if (strict_visibility
@@ -134,17 +134,35 @@
     dst_entry->allow_new = std::move(src_entry->allow_new);
   }
 
-  if (src_entry->overlayable) {
-    if (dst_entry->overlayable && !overlay) {
-      context->GetDiagnostics()->Error(DiagMessage(src_entry->overlayable.value().source)
-                                       << "duplicate overlayable declaration for resource '"
-                                       << src_entry->name << "'");
-      context->GetDiagnostics()->Error(DiagMessage(dst_entry->overlayable.value().source)
-                                       << "previous declaration here");
-      return false;
+  for (auto& src_overlayable : src_entry->overlayable_declarations) {
+    for (auto& dst_overlayable : dst_entry->overlayable_declarations) {
+      // An overlayable resource cannot be declared twice with the same policy
+      if (src_overlayable.policy == dst_overlayable.policy) {
+        context->GetDiagnostics()->Error(DiagMessage(src_overlayable.source)
+                                             << "duplicate overlayable declaration for resource '"
+                                             << src_entry->name << "'");
+        context->GetDiagnostics()->Error(DiagMessage(dst_overlayable.source)
+                                             << "previous declaration here");
+        return false;
+      }
+
+      // An overlayable resource cannot be declared once with a policy and without a policy because
+      // the policy becomes unused
+      if (!src_overlayable.policy || !dst_overlayable.policy) {
+        context->GetDiagnostics()->Error(DiagMessage(src_overlayable.source)
+                                             << "overlayable resource '" << src_entry->name
+                                             << "' declared once with a policy and once with no "
+                                             << "policy");
+        context->GetDiagnostics()->Error(DiagMessage(dst_overlayable.source)
+                                             << "previous declaration here");
+        return false;
+      }
     }
-    dst_entry->overlayable = std::move(src_entry->overlayable);
   }
+
+  dst_entry->overlayable_declarations.insert(dst_entry->overlayable_declarations.end(),
+                                             src_entry->overlayable_declarations.begin(),
+                                             src_entry->overlayable_declarations.end());
   return true;
 }
 
@@ -244,7 +262,7 @@
         continue;
       }
 
-      if (!MergeEntry(context_, src, overlay, dst_entry, src_entry.get(), options_.strict_visibility)) {
+      if (!MergeEntry(context_, src, dst_entry, src_entry.get(), options_.strict_visibility)) {
         error = true;
         continue;
       }
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index 79a734b..d6579d3 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -436,4 +436,97 @@
               Eq(make_value(Reference(test::ParseNameOrDie("com.app.a:style/OverlayParent")))));
 }
 
+TEST_F(TableMergerTest, AddOverlayable) {
+  std::unique_ptr<ResourceTable> table_a =
+      test::ResourceTableBuilder()
+          .SetPackageId("com.app.a", 0x7f)
+          .AddOverlayable("bool/foo", Overlayable::Policy::kProduct)
+          .Build();
+
+  std::unique_ptr<ResourceTable> table_b =
+      test::ResourceTableBuilder()
+          .SetPackageId("com.app.a", 0x7f)
+          .AddOverlayable("bool/foo", Overlayable::Policy::kProductServices)
+          .Build();
+
+  ResourceTable final_table;
+  TableMergerOptions options;
+  options.auto_add_overlay = true;
+  TableMerger merger(context_.get(), &final_table, options);
+  ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
+  ASSERT_TRUE(merger.Merge({}, table_b.get(), false /*overlay*/));
+
+  const ResourceName name = test::ParseNameOrDie("com.app.a:bool/foo");
+  Maybe<ResourceTable::SearchResult> result = final_table.FindResource(name);
+  ASSERT_TRUE(result);
+  ASSERT_THAT(result.value().entry->overlayable_declarations.size(), Eq(2));
+  ASSERT_THAT(result.value().entry->overlayable_declarations[0].policy,
+              Eq(Overlayable::Policy::kProduct));
+  ASSERT_THAT(result.value().entry->overlayable_declarations[1].policy,
+              Eq(Overlayable::Policy::kProductServices));
+}
+
+TEST_F(TableMergerTest, AddDuplicateOverlayableFail) {
+  std::unique_ptr<ResourceTable> table_a =
+      test::ResourceTableBuilder()
+          .SetPackageId("com.app.a", 0x7f)
+          .AddOverlayable("bool/foo", Overlayable::Policy::kProduct)
+          .Build();
+
+  std::unique_ptr<ResourceTable> table_b =
+      test::ResourceTableBuilder()
+          .SetPackageId("com.app.a", 0x7f)
+          .AddOverlayable("bool/foo", Overlayable::Policy::kProduct)
+          .Build();
+
+  ResourceTable final_table;
+  TableMergerOptions options;
+  options.auto_add_overlay = true;
+  TableMerger merger(context_.get(), &final_table, options);
+  ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
+  ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
+}
+
+TEST_F(TableMergerTest, AddOverlayablePolicyAndNoneFirstFail) {
+  std::unique_ptr<ResourceTable> table_a =
+      test::ResourceTableBuilder()
+          .SetPackageId("com.app.a", 0x7f)
+          .AddOverlayable("bool/foo", {})
+          .Build();
+
+  std::unique_ptr<ResourceTable> table_b =
+      test::ResourceTableBuilder()
+          .SetPackageId("com.app.a", 0x7f)
+          .AddOverlayable("bool/foo", Overlayable::Policy::kProduct)
+          .Build();
+
+  ResourceTable final_table;
+  TableMergerOptions options;
+  options.auto_add_overlay = true;
+  TableMerger merger(context_.get(), &final_table, options);
+  ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
+  ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
+}
+
+TEST_F(TableMergerTest, AddOverlayablePolicyAndNoneLastFail) {
+  std::unique_ptr<ResourceTable> table_a =
+      test::ResourceTableBuilder()
+          .SetPackageId("com.app.a", 0x7f)
+          .AddOverlayable("bool/foo", Overlayable::Policy::kProduct)
+          .Build();
+
+  std::unique_ptr<ResourceTable> table_b =
+      test::ResourceTableBuilder()
+          .SetPackageId("com.app.a", 0x7f)
+          .AddOverlayable("bool/foo", {})
+          .Build();
+
+  ResourceTable final_table;
+  TableMergerOptions options;
+  options.auto_add_overlay = true;
+  TableMerger merger(context_.get(), &final_table, options);
+  ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
+  ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp
index 414758e..2e717ff 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -248,6 +248,7 @@
             if (!split_entry->id) {
               split_entry->id = entry->id;
               split_entry->visibility = entry->visibility;
+              split_entry->overlayable_declarations = entry->overlayable_declarations;
             }
 
             // Copy the selected values into the new Split Entry.
diff --git a/tools/aapt2/test/Builders.cpp b/tools/aapt2/test/Builders.cpp
index f33ae31..03b59e0 100644
--- a/tools/aapt2/test/Builders.cpp
+++ b/tools/aapt2/test/Builders.cpp
@@ -135,6 +135,15 @@
   return *this;
 }
 
+ResourceTableBuilder& ResourceTableBuilder::AddOverlayable(const StringPiece& name,
+                                                           const Maybe<Overlayable::Policy> p) {
+  ResourceName res_name = ParseNameOrDie(name);
+  Overlayable overlayable;
+  overlayable.policy = p;
+  CHECK(table_->AddOverlayable(res_name, overlayable, GetDiagnostics()));
+  return *this;
+}
+
 StringPool* ResourceTableBuilder::string_pool() {
   return &table_->string_pool;
 }
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index 9159599..d68c24d 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -73,6 +73,8 @@
                                  const ResourceId& id, std::unique_ptr<Value> value);
   ResourceTableBuilder& SetSymbolState(const android::StringPiece& name, const ResourceId& id,
                                        Visibility::Level level, bool allow_new = false);
+  ResourceTableBuilder& AddOverlayable(const android::StringPiece& name,
+                                       Maybe<Overlayable::Policy> policy);
 
   StringPool* string_pool();
   std::unique_ptr<ResourceTable> Build();
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 1ef34b9..8585ae9 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -435,7 +435,7 @@
        fprintf(out, "      std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
        fprintf(out, "  }\n");
        fprintf(out, "  if (ret < 0) {\n");
-       fprintf(out, "      note_log_drop();\n");
+       fprintf(out, "      note_log_drop(ret);\n");
        fprintf(out, "  }\n");
        fprintf(out, "  return ret;\n");
        fprintf(out, "}\n");
@@ -528,7 +528,7 @@
        fprintf(out, "      std::this_thread::sleep_for(std::chrono::milliseconds(10));\n");
        fprintf(out, "  }\n");
        fprintf(out, "  if (ret < 0) {\n");
-       fprintf(out, "      note_log_drop();\n");
+       fprintf(out, "      note_log_drop(ret);\n");
        fprintf(out, "  }\n");
        fprintf(out, "  return ret;\n\n");
        fprintf(out, "}\n");
diff --git a/wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl b/wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl
new file mode 100644
index 0000000..d14ec57
--- /dev/null
+++ b/wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.net.wifi.INetworkRequestUserSelectionCallback;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+
+/**
+ * Interface for network request match callback.
+ *
+ * @hide
+ */
+oneway interface INetworkRequestMatchCallback
+{
+   void onUserSelectionCallbackRegistration(in INetworkRequestUserSelectionCallback userSelectionCallback);
+
+   void onAbort();
+
+   void onMatch(in List<ScanResult> scanResults);
+
+   void onUserSelectionConnectSuccess(in WifiConfiguration wificonfiguration);
+
+   void onUserSelectionConnectFailure(in WifiConfiguration wificonfiguration);
+}
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/wifi/java/android/net/wifi/INetworkRequestUserSelectionCallback.aidl
similarity index 66%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to wifi/java/android/net/wifi/INetworkRequestUserSelectionCallback.aidl
index ede8695..524cefb 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/wifi/java/android/net/wifi/INetworkRequestUserSelectionCallback.aidl
@@ -14,8 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package android.net.wifi;
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+import android.net.wifi.WifiConfiguration;
+
+/**
+ * Interface for providing user selection in response to
+ * network request match callback.
+ * @hide
+ */
+oneway interface INetworkRequestUserSelectionCallback
+{
+   void select(in WifiConfiguration wificonfiguration);
+
+   void reject();
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 12f50c8..3ec8a41 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -25,6 +25,7 @@
 
 import android.net.DhcpInfo;
 import android.net.Network;
+import android.net.wifi.INetworkRequestMatchCallback;
 import android.net.wifi.ISoftApCallback;
 import android.net.wifi.ITrafficStateCallback;
 import android.net.wifi.PasspointManagementObjectDefinition;
@@ -32,6 +33,7 @@
 import android.net.wifi.WifiActivityEnergyInfo;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiNetworkSuggestion;
 
 import android.os.Messenger;
 import android.os.ResultReceiver;
@@ -60,11 +62,9 @@
 
     ParceledListSlice getPrivilegedConfiguredNetworks();
 
-    WifiConfiguration getMatchingWifiConfig(in ScanResult scanResult);
+    List<WifiConfiguration> getAllMatchingWifiConfigs(in List<ScanResult> scanResult);
 
-    List<WifiConfiguration> getAllMatchingWifiConfigs(in ScanResult scanResult);
-
-    List<OsuProvider> getMatchingOsuProviders(in ScanResult scanResult);
+    List<OsuProvider> getMatchingOsuProviders(in List<ScanResult> scanResult);
 
     int addOrUpdateNetwork(in WifiConfiguration config, String packageName);
 
@@ -185,5 +185,13 @@
     void registerTrafficStateCallback(in IBinder binder, in ITrafficStateCallback callback, int callbackIdentifier);
 
     void unregisterTrafficStateCallback(int callbackIdentifier);
+
+    void registerNetworkRequestMatchCallback(in IBinder binder, in INetworkRequestMatchCallback callback, int callbackIdentifier);
+
+    void unregisterNetworkRequestMatchCallback(int callbackIdentifier);
+
+    boolean addNetworkSuggestions(in List<WifiNetworkSuggestion> networkSuggestions, in String packageName);
+
+    boolean removeNetworkSuggestions(in List<WifiNetworkSuggestion> networkSuggestions, in String packageName);
 }
 
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 3a4e88b..9b9247d 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -86,9 +86,9 @@
     public static final int PROTOCOL_WPA = 1;
     /**
      * @hide
-     * Security protocol type: WPA version 2, also called RSN.
+     * Security protocol type: RSN, for WPA version 2, and version 3.
      */
-    public static final int PROTOCOL_WPA2 = 2;
+    public static final int PROTOCOL_RSN = 2;
     /**
      * @hide
      * Security protocol type:
@@ -138,7 +138,21 @@
      * Used for Hotspot 2.0.
      */
     public static final int KEY_MGMT_OSEN = 7;
-
+     /**
+     * @hide
+     * Security key management scheme: SAE.
+     */
+    public static final int KEY_MGMT_SAE = 8;
+    /**
+     * @hide
+     * Security key management scheme: OWE.
+     */
+    public static final int KEY_MGMT_OWE = 9;
+    /**
+     * @hide
+     * Security key management scheme: SUITE_B_192.
+     */
+    public static final int KEY_MGMT_EAP_SUITE_B_192 = 10;
     /**
      * @hide
      * No cipher suite.
@@ -159,6 +173,11 @@
      * Cipher suite: CCMP
      */
     public static final int CIPHER_CCMP = 3;
+    /**
+     * @hide
+     * Cipher suite: GCMP
+     */
+    public static final int CIPHER_GCMP_256 = 4;
 
     /**
      * The detected signal level in dBm, also known as the RSSI.
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 0330614..64f8adb 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -23,6 +23,7 @@
 import android.net.IpConfiguration;
 import android.net.IpConfiguration.ProxySettings;
 import android.net.MacAddress;
+import android.net.NetworkSpecifier;
 import android.net.ProxyInfo;
 import android.net.StaticIpConfiguration;
 import android.net.Uri;
@@ -47,13 +48,17 @@
 /**
  * A class representing a configured Wi-Fi network, including the
  * security configuration.
+ *
+ * @deprecated Use {@link WifiNetworkConfigBuilder} to create {@link NetworkSpecifier} and
+ * {@link WifiNetworkSuggestion}. This will become a system use only object in the future.
  */
+@Deprecated
 public class WifiConfiguration implements Parcelable {
     private static final String TAG = "WifiConfiguration";
     /**
      * Current Version of the Backup Serializer.
     */
-    private static final int BACKUP_VERSION = 2;
+    private static final int BACKUP_VERSION = 3;
     /** {@hide} */
     public static final String ssidVarName = "ssid";
     /** {@hide} */
@@ -125,10 +130,26 @@
          */
         public static final int FT_EAP = 7;
 
+        /**
+         * Simultaneous Authentication of Equals
+         */
+        public static final int SAE = 8;
+
+        /**
+         * Opportunististic Wireless Encryption
+         */
+        public static final int OWE = 9;
+
+        /**
+         * SUITE_B_192 192 bit level
+         */
+        public static final int SUITE_B_192 = 10;
+
         public static final String varName = "key_mgmt";
 
         public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP",
-                "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP" };
+                "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP",
+                "SAE", "OWE", "SUITE_B_192"};
     }
 
     /**
@@ -142,7 +163,7 @@
          * is discouraged. WPA-2 (RSN) should be used instead. */
         @Deprecated
         public static final int WPA = 0;
-        /** WPA2/IEEE 802.11i */
+        /** RSN WPA2/WPA3/IEEE 802.11i */
         public static final int RSN = 1;
         /** HS2.0 r2 OSEN
          * @hide
@@ -190,10 +211,14 @@
         public static final int TKIP = 1;
         /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
         public static final int CCMP = 2;
+        /**
+         * AES in Galois/Counter Mode
+         */
+        public static final int GCMP_256 = 3;
 
         public static final String varName = "pairwise";
 
-        public static final String[] strings = { "NONE", "TKIP", "CCMP" };
+        public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256" };
     }
 
     /**
@@ -203,6 +228,7 @@
      * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
      * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
      * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
+     * GCMP_256 = AES in Galois/Counter Mode
      * </pre>
      */
     public static class GroupCipher {
@@ -226,12 +252,64 @@
          * @hide
          */
         public static final int GTK_NOT_USED = 4;
+        /**
+         * AES in Galois/Counter Mode
+         */
+        public static final int GCMP_256 = 5;
 
         public static final String varName = "group";
 
         public static final String[] strings =
                 { /* deprecated */ "WEP40", /* deprecated */ "WEP104",
-                        "TKIP", "CCMP", "GTK_NOT_USED" };
+                        "TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256" };
+    }
+
+    /**
+     * Recognized group management ciphers.
+     * <pre>
+     * BIP_CMAC_256 = Cipher-based Message Authentication Code 256 bits
+     * BIP_GMAC_128 = Galois Message Authentication Code 128 bits
+     * BIP_GMAC_256 = Galois Message Authentication Code 256 bits
+     * </pre>
+     */
+    public static class GroupMgmtCipher {
+        private GroupMgmtCipher() { }
+
+        /** CMAC-256 = Cipher-based Message Authentication Code */
+        public static final int BIP_CMAC_256 = 0;
+
+        /** GMAC-128 = Galois Message Authentication Code */
+        public static final int BIP_GMAC_128 = 1;
+
+        /** GMAC-256 = Galois Message Authentication Code */
+        public static final int BIP_GMAC_256 = 2;
+
+        private static final String varName = "groupMgmt";
+
+        private static final String[] strings = { "BIP_CMAC_256",
+                "BIP_GMAC_128", "BIP_GMAC_256"};
+    }
+
+    /**
+     * Recognized suiteB ciphers.
+     * <pre>
+     * ECDHE_ECDSA
+     * ECDHE_RSA
+     * </pre>
+     * @hide
+     */
+    public static class SuiteBCipher {
+        private SuiteBCipher() { }
+
+        /** Diffie-Hellman with Elliptic Curve_ECDSA signature */
+        public static final int ECDHE_ECDSA = 0;
+
+        /** Diffie-Hellman with_RSA signature */
+        public static final int ECDHE_RSA = 1;
+
+        private static final String varName = "SuiteB";
+
+        private static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" };
     }
 
     /** Possible status of a network configuration. */
@@ -409,6 +487,17 @@
      */
     public BitSet allowedGroupCiphers;
     /**
+     * The set of group management ciphers supported by this configuration.
+     * See {@link GroupMgmtCipher} for descriptions of the values.
+     */
+    public BitSet allowedGroupMgmtCiphers;
+    /**
+     * The set of SuiteB ciphers supported by this configuration.
+     * To be used for WPA3-Enterprise mode.
+     * See {@link SuiteBCipher} for descriptions of the values.
+     */
+    public BitSet allowedSuiteBCiphers;
+    /**
      * The enterprise configuration details specifying the EAP method,
      * certificates and other settings associated with the EAP.
      */
@@ -673,6 +762,13 @@
     }
 
     /**
+     * Indicate whther the network is trusted or not. Networks are considered trusted
+     * if the user explicitly allowed this network connection.
+     * @hide
+     */
+    public boolean trusted;
+
+    /**
      * Indicates if the creator of this configuration has expressed that it
      * should be considered metered.
      *
@@ -733,7 +829,8 @@
     public boolean isOpenNetwork() {
         final int cardinality = allowedKeyManagement.cardinality();
         final boolean hasNoKeyMgmt = cardinality == 0
-                || (cardinality == 1 && allowedKeyManagement.get(KeyMgmt.NONE));
+                || (cardinality == 1 && (allowedKeyManagement.get(KeyMgmt.NONE)
+                || allowedKeyManagement.get(KeyMgmt.OWE)));
 
         boolean hasNoWepKeys = true;
         if (wepKeys != null) {
@@ -1538,6 +1635,8 @@
         allowedAuthAlgorithms = new BitSet();
         allowedPairwiseCiphers = new BitSet();
         allowedGroupCiphers = new BitSet();
+        allowedGroupMgmtCiphers = new BitSet();
+        allowedSuiteBCiphers = new BitSet();
         wepKeys = new String[4];
         for (int i = 0; i < wepKeys.length; i++) {
             wepKeys[i] = null;
@@ -1546,6 +1645,7 @@
         selfAdded = false;
         didSelfAdd = false;
         ephemeral = false;
+        trusted = true; // Networks are considered trusted by default.
         meteredHint = false;
         meteredOverride = METERED_OVERRIDE_NONE;
         useExternalScores = false;
@@ -1591,7 +1691,8 @@
     @UnsupportedAppUsage
     public boolean isEnterprise() {
         return (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
-                || allowedKeyManagement.get(KeyMgmt.IEEE8021X))
+                || allowedKeyManagement.get(KeyMgmt.IEEE8021X)
+                || allowedKeyManagement.get(KeyMgmt.SUITE_B_192))
                 && enterpriseConfig != null
                 && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;
     }
@@ -1609,6 +1710,7 @@
                 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN)
                 .append(" PRIO: ").append(this.priority)
                 .append(" HIDDEN: ").append(this.hiddenSSID)
+                .append(" PMF: ").append(this.requirePMF)
                 .append('\n');
 
 
@@ -1653,10 +1755,11 @@
         if (this.selfAdded) sbuf.append(" selfAdded");
         if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess");
         if (this.ephemeral) sbuf.append(" ephemeral");
+        if (this.trusted) sbuf.append(" trusted");
         if (this.meteredHint) sbuf.append(" meteredHint");
         if (this.useExternalScores) sbuf.append(" useExternalScores");
         if (this.didSelfAdd || this.selfAdded || this.validatedInternetAccess
-            || this.ephemeral || this.meteredHint || this.useExternalScores) {
+                || this.ephemeral || this.trusted || this.meteredHint || this.useExternalScores) {
             sbuf.append("\n");
         }
         if (this.meteredOverride != METERED_OVERRIDE_NONE) {
@@ -1721,10 +1824,35 @@
                 }
             }
         }
-        sbuf.append('\n').append(" PSK: ");
+        sbuf.append('\n');
+        sbuf.append(" GroupMgmtCiphers:");
+        for (int gmc = 0; gmc < this.allowedGroupMgmtCiphers.size(); gmc++) {
+            if (this.allowedGroupMgmtCiphers.get(gmc)) {
+                sbuf.append(" ");
+                if (gmc < GroupMgmtCipher.strings.length) {
+                    sbuf.append(GroupMgmtCipher.strings[gmc]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n');
+        sbuf.append(" SuiteBCiphers:");
+        for (int sbc = 0; sbc < this.allowedSuiteBCiphers.size(); sbc++) {
+            if (this.allowedSuiteBCiphers.get(sbc)) {
+                sbuf.append(" ");
+                if (sbc < SuiteBCipher.strings.length) {
+                    sbuf.append(SuiteBCipher.strings[sbc]);
+                } else {
+                    sbuf.append("??");
+                }
+            }
+        }
+        sbuf.append('\n').append(" PSK/SAE: ");
         if (this.preSharedKey != null) {
             sbuf.append('*');
         }
+
         sbuf.append("\nEnterprise config:\n");
         sbuf.append(enterpriseConfig);
 
@@ -1887,6 +2015,12 @@
             return KeyMgmt.WPA_EAP;
         } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
             return KeyMgmt.IEEE8021X;
+        } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
+            return KeyMgmt.SAE;
+        } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
+            return KeyMgmt.OWE;
+        } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
+            return KeyMgmt.SUITE_B_192;
         }
         return KeyMgmt.NONE;
     }
@@ -1918,6 +2052,12 @@
                 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP];
             } else if (wepKeys[0] != null) {
                 key = SSID + "WEP";
+            } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
+                key = SSID + KeyMgmt.strings[KeyMgmt.OWE];
+            } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
+                key = SSID + KeyMgmt.strings[KeyMgmt.SAE];
+            } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
+                key = SSID + KeyMgmt.strings[KeyMgmt.SUITE_B_192];
             } else {
                 key = SSID + KeyMgmt.strings[KeyMgmt.NONE];
             }
@@ -2086,6 +2226,8 @@
             allowedAuthAlgorithms  = (BitSet) source.allowedAuthAlgorithms.clone();
             allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone();
             allowedGroupCiphers    = (BitSet) source.allowedGroupCiphers.clone();
+            allowedGroupMgmtCiphers    = (BitSet) source.allowedGroupMgmtCiphers.clone();
+            allowedSuiteBCiphers    = (BitSet) source.allowedSuiteBCiphers.clone();
             enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig);
 
             defaultGwMacAddress = source.defaultGwMacAddress;
@@ -2102,6 +2244,7 @@
             validatedInternetAccess = source.validatedInternetAccess;
             isLegacyPasspointConfig = source.isLegacyPasspointConfig;
             ephemeral = source.ephemeral;
+            trusted = source.trusted;
             meteredHint = source.meteredHint;
             meteredOverride = source.meteredOverride;
             useExternalScores = source.useExternalScores;
@@ -2128,6 +2271,7 @@
             recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus());
             mRandomizedMacAddress = source.mRandomizedMacAddress;
             macRandomizationSetting = source.macRandomizationSetting;
+            requirePMF = source.requirePMF;
         }
     }
 
@@ -2163,6 +2307,8 @@
         writeBitSet(dest, allowedAuthAlgorithms);
         writeBitSet(dest, allowedPairwiseCiphers);
         writeBitSet(dest, allowedGroupCiphers);
+        writeBitSet(dest, allowedGroupMgmtCiphers);
+        writeBitSet(dest, allowedSuiteBCiphers);
 
         dest.writeParcelable(enterpriseConfig, flags);
 
@@ -2174,6 +2320,7 @@
         dest.writeInt(validatedInternetAccess ? 1 : 0);
         dest.writeInt(isLegacyPasspointConfig ? 1 : 0);
         dest.writeInt(ephemeral ? 1 : 0);
+        dest.writeInt(trusted ? 1 : 0);
         dest.writeInt(meteredHint ? 1 : 0);
         dest.writeInt(meteredOverride);
         dest.writeInt(useExternalScores ? 1 : 0);
@@ -2231,6 +2378,8 @@
                 config.allowedAuthAlgorithms  = readBitSet(in);
                 config.allowedPairwiseCiphers = readBitSet(in);
                 config.allowedGroupCiphers    = readBitSet(in);
+                config.allowedGroupMgmtCiphers = readBitSet(in);
+                config.allowedSuiteBCiphers   = readBitSet(in);
 
                 config.enterpriseConfig = in.readParcelable(null);
                 config.setIpConfiguration(in.readParcelable(null));
@@ -2241,6 +2390,7 @@
                 config.validatedInternetAccess = in.readInt() != 0;
                 config.isLegacyPasspointConfig = in.readInt() != 0;
                 config.ephemeral = in.readInt() != 0;
+                config.trusted = in.readInt() != 0;
                 config.meteredHint = in.readInt() != 0;
                 config.meteredOverride = in.readInt();
                 config.useExternalScores = in.readInt() != 0;
@@ -2282,6 +2432,7 @@
         out.writeInt(apChannel);
         BackupUtils.writeString(out, preSharedKey);
         out.writeInt(getAuthType());
+        out.writeBoolean(hiddenSSID);
         return baos.toByteArray();
     }
 
@@ -2304,6 +2455,9 @@
         config.apChannel = in.readInt();
         config.preSharedKey = BackupUtils.readString(in);
         config.allowedKeyManagement.set(in.readInt());
+        if (version >= 3) {
+            config.hiddenSSID = in.readBoolean();
+        }
         return config;
     }
 }
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index e37a856..e5dcef0 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -110,6 +110,8 @@
 
     private boolean mEphemeral;
 
+    private boolean mTrusted;
+
     /**
      * Running total count of lost (not ACKed) transmitted unicast data packets.
      * @hide
@@ -215,6 +217,7 @@
             mMacAddress = source.mMacAddress;
             mMeteredHint = source.mMeteredHint;
             mEphemeral = source.mEphemeral;
+            mTrusted = source.mTrusted;
             txBad = source.txBad;
             txRetries = source.txRetries;
             txSuccess = source.txSuccess;
@@ -397,6 +400,17 @@
         return mEphemeral;
     }
 
+    /** {@hide} */
+    public void setTrusted(boolean trusted) {
+        mTrusted = trusted;
+    }
+
+    /** {@hide} */
+    public boolean isTrusted() {
+        return mTrusted;
+    }
+
+
     /** @hide */
     @UnsupportedAppUsage
     public void setNetworkId(int id) {
@@ -539,6 +553,7 @@
         dest.writeString(mMacAddress);
         dest.writeInt(mMeteredHint ? 1 : 0);
         dest.writeInt(mEphemeral ? 1 : 0);
+        dest.writeInt(mTrusted ? 1 : 0);
         dest.writeInt(score);
         dest.writeLong(txSuccess);
         dest.writeDouble(txSuccessRate);
@@ -573,6 +588,7 @@
                 info.mMacAddress = in.readString();
                 info.mMeteredHint = in.readInt() != 0;
                 info.mEphemeral = in.readInt() != 0;
+                info.mTrusted = in.readInt() != 0;
                 info.score = in.readInt();
                 info.txSuccess = in.readLong();
                 info.txSuccessRate = in.readDouble();
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 9adbe67..7aff03c 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -30,14 +30,11 @@
 import android.net.ConnectivityManager;
 import android.net.DhcpInfo;
 import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
 import android.net.wifi.hotspot2.IProvisioningCallback;
 import android.net.wifi.hotspot2.OsuProvider;
 import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.net.wifi.hotspot2.ProvisioningCallback;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -52,7 +49,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
-import com.android.server.net.NetworkPinner;
 
 import dalvik.system.CloseGuard;
 
@@ -874,6 +870,28 @@
     public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE";
 
     /**
+     * Directed broadcast intent action indicating that the device has connected to one of the
+     * network suggestions provided by the app. This will be sent post connection to a network
+     * which was created with {@link WifiNetworkConfigBuilder#setIsAppInteractionRequired()} flag
+     * set.
+     * <p>
+     * Note: The broadcast is sent to the app only if it holds either one of
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission.
+     *
+     * @see #EXTRA_NETWORK_SUGGESTION
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION =
+            "android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION";
+    /**
+     * Sent as as a part of {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} that holds
+     * an instance of {@link WifiNetworkSuggestion} corresponding to the connected network.
+     */
+    public static final String EXTRA_NETWORK_SUGGESTION =
+            "android.net.wifi.extra.NETWORK_SUGGESTION";
+
+    /**
      * Internally used Wi-Fi lock mode representing the case were no locks are held.
      * @hide
      */
@@ -1035,7 +1053,17 @@
      * </ul>
      * @return a list of network configurations in the form of a list
      * of {@link WifiConfiguration} objects.
+     *
+     * @deprecated
+     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * mechanism to trigger connection to a Wi-Fi network.
+     * b) See {@link #addNetworkSuggestions(List)},
+     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
+     * when auto-connecting to wifi.
+     * <b>Compatibility Note:</b> For applications targeting
+     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return an empty list.
      */
+    @Deprecated
     public List<WifiConfiguration> getConfiguredNetworks() {
         try {
             ParceledListSlice<WifiConfiguration> parceledList =
@@ -1066,55 +1094,43 @@
     }
 
     /**
-     * Returns a WifiConfiguration matching this ScanResult
-     *
-     * @param scanResult scanResult that represents the BSSID
-     * @return {@link WifiConfiguration} that matches this BSSID or null
-     * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) {
-        try {
-            return mService.getMatchingWifiConfig(scanResult);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Return all matching WifiConfigurations for this ScanResult.
+     * Returns all matching WifiConfigurations for a given list of ScanResult.
      *
      * An empty list will be returned when no configurations are installed or if no configurations
      * match the ScanResult.
-     *
-     * @param scanResult scanResult that represents the BSSID
-     * @return A list of {@link WifiConfiguration}
+
+     * @param scanResults a list of scanResult that represents the BSSID
+     * @return A list of {@link WifiConfiguration} that can have duplicate entries.
      * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
      * @hide
      */
-    public List<WifiConfiguration> getAllMatchingWifiConfigs(ScanResult scanResult) {
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public List<WifiConfiguration> getAllMatchingWifiConfigs(
+            @NonNull List<ScanResult> scanResults) {
         try {
-            return mService.getAllMatchingWifiConfigs(scanResult);
+            return mService.getAllMatchingWifiConfigs(scanResults);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
-
     /**
-     * Returns a list of Hotspot 2.0 OSU (Online Sign-Up) providers associated with the given AP.
+     * Returns a list of unique Hotspot 2.0 OSU (Online Sign-Up) providers associated with a given
+     * list of ScanResult.
      *
      * An empty list will be returned if no match is found.
      *
-     * @param scanResult scanResult that represents the BSSID
-     * @return list of {@link OsuProvider}
+     * @param scanResults a list of ScanResult
+     * @return A list of {@link OsuProvider} that does not contain duplicate entries.
      * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
      * @hide
      */
-    public List<OsuProvider> getMatchingOsuProviders(ScanResult scanResult) {
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public List<OsuProvider> getMatchingOsuProviders(List<ScanResult> scanResults) {
         try {
-            return mService.getMatchingOsuProviders(scanResult);
+            return mService.getMatchingOsuProviders(scanResults);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1135,7 +1151,17 @@
      * @return the ID of the newly created network description. This is used in
      *         other operations to specified the network to be acted upon.
      *         Returns {@code -1} on failure.
+     *
+     * @deprecated
+     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * mechanism to trigger connection to a Wi-Fi network.
+     * b) See {@link #addNetworkSuggestions(List)},
+     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
+     * when auto-connecting to wifi.
+     * <b>Compatibility Note:</b> For applications targeting
+     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return {@code -1}.
      */
+    @Deprecated
     public int addNetwork(WifiConfiguration config) {
         if (config == null) {
             return -1;
@@ -1160,7 +1186,17 @@
      *         Returns {@code -1} on failure, including when the {@code networkId}
      *         field of the {@code WifiConfiguration} does not refer to an
      *         existing network.
+     *
+     * @deprecated
+     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * mechanism to trigger connection to a Wi-Fi network.
+     * b) See {@link #addNetworkSuggestions(List)},
+     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
+     * when auto-connecting to wifi.
+     * <b>Compatibility Note:</b> For applications targeting
+     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return {@code -1}.
      */
+    @Deprecated
     public int updateNetwork(WifiConfiguration config) {
         if (config == null || config.networkId < 0) {
             return -1;
@@ -1185,6 +1221,320 @@
     }
 
     /**
+     * Interface for indicating user selection from the list of networks presented in the
+     * {@link NetworkRequestMatchCallback#onMatch(List)}.
+     *
+     * The platform will implement this callback and pass it along with the
+     * {@link NetworkRequestMatchCallback#onUserSelectionCallbackRegistration(
+     * NetworkRequestUserSelectionCallback)}. The UI component handling
+     * {@link NetworkRequestMatchCallback} will invoke {@link #select(WifiConfiguration)} or
+     * {@link #reject()} to return the user's selection back to the platform via this callback.
+     * @hide
+     */
+    @SystemApi
+    public interface NetworkRequestUserSelectionCallback {
+        /**
+         * User selected this network to connect to.
+         * @param wifiConfiguration WifiConfiguration object corresponding to the network
+         *                          user selected.
+         */
+        void select(@NonNull WifiConfiguration wifiConfiguration);
+
+        /**
+         * User rejected the app's request.
+         */
+        void reject();
+    }
+
+    /**
+     * Interface for network request callback. Should be implemented by applications and passed when
+     * calling {@link #registerNetworkRequestMatchCallback(NetworkRequestMatchCallback, Handler)}.
+     *
+     * This is meant to be implemented by a UI component to present the user with a list of networks
+     * matching the app's request. The user is allowed to pick one of these networks to connect to
+     * or reject the request by the app.
+     * @hide
+     */
+    @SystemApi
+    public interface NetworkRequestMatchCallback {
+        /**
+         * Invoked to register a callback to be invoked to convey user selection. The callback
+         * object paased in this method is to be invoked by the UI component after the service sends
+         * a list of matching scan networks using {@link #onMatch(List)} and user picks a network
+         * from that list.
+         *
+         * @param userSelectionCallback Callback object to send back the user selection.
+         */
+        void onUserSelectionCallbackRegistration(
+                @NonNull NetworkRequestUserSelectionCallback userSelectionCallback);
+
+        /**
+         * Invoked when the active network request is aborted, either because
+         * <li> The app released the request, OR</li>
+         * <li> Request was overridden by a new request</li>
+         * This signals the end of processing for the current request and should stop the UI
+         * component. No subsequent calls from the UI component will be handled by the platform.
+         */
+        void onAbort();
+
+        /**
+         * Invoked when a network request initiated by an app matches some networks in scan results.
+         * This may be invoked multiple times for a single network request as the platform finds new
+         * matching networks in scan results.
+         *
+         * @param scanResults List of {@link ScanResult} objects corresponding to the networks
+         *                    matching the request.
+         */
+        void onMatch(@NonNull List<ScanResult> scanResults);
+
+        /**
+         * Invoked on a successful connection with the network that the user selected
+         * via {@link NetworkRequestUserSelectionCallback}.
+         *
+         * @param wifiConfiguration WifiConfiguration object corresponding to the network that the
+         *                          user selected.
+         */
+        void onUserSelectionConnectSuccess(@NonNull WifiConfiguration wifiConfiguration);
+
+        /**
+         * Invoked on failure to establish connection with the network that the user selected
+         * via {@link NetworkRequestUserSelectionCallback}.
+         *
+         * @param wifiConfiguration WifiConfiguration object corresponding to the network
+         *                          user selected.
+         */
+        void onUserSelectionConnectFailure(@NonNull WifiConfiguration wifiConfiguration);
+    }
+
+    /**
+     * Callback proxy for NetworkRequestUserSelectionCallback objects.
+     * @hide
+     */
+    private class NetworkRequestUserSelectionCallbackProxy implements
+            NetworkRequestUserSelectionCallback {
+        private final INetworkRequestUserSelectionCallback mCallback;
+
+        NetworkRequestUserSelectionCallbackProxy(
+                INetworkRequestUserSelectionCallback callback) {
+            mCallback = callback;
+        }
+
+        @Override
+        public void select(@NonNull WifiConfiguration wifiConfiguration) {
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: select "
+                        + "wificonfiguration: " + wifiConfiguration);
+            }
+            try {
+                mCallback.select(wifiConfiguration);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to invoke onSelected", e);
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        @Override
+        public void reject() {
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: reject");
+            }
+            try {
+                mCallback.reject();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to invoke onRejected", e);
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Callback proxy for NetworkRequestMatchCallback objects.
+     * @hide
+     */
+    private class NetworkRequestMatchCallbackProxy extends INetworkRequestMatchCallback.Stub {
+        private final Handler mHandler;
+        private final NetworkRequestMatchCallback mCallback;
+
+        NetworkRequestMatchCallbackProxy(Looper looper, NetworkRequestMatchCallback callback) {
+            mHandler = new Handler(looper);
+            mCallback = callback;
+        }
+
+        @Override
+        public void onUserSelectionCallbackRegistration(
+                INetworkRequestUserSelectionCallback userSelectionCallback) {
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "NetworkRequestMatchCallbackProxy: "
+                        + "onUserSelectionCallbackRegistration callback: " + userSelectionCallback);
+            }
+            mHandler.post(() -> {
+                mCallback.onUserSelectionCallbackRegistration(
+                        new NetworkRequestUserSelectionCallbackProxy(userSelectionCallback));
+            });
+        }
+
+        @Override
+        public void onAbort() {
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "NetworkRequestMatchCallbackProxy: onAbort");
+            }
+            mHandler.post(() -> {
+                mCallback.onAbort();
+            });
+        }
+
+        @Override
+        public void onMatch(List<ScanResult> scanResults) {
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "NetworkRequestMatchCallbackProxy: onMatch scanResults: "
+                        + scanResults);
+            }
+            mHandler.post(() -> {
+                mCallback.onMatch(scanResults);
+            });
+        }
+
+        @Override
+        public void onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration) {
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectSuccess "
+                        + " wificonfiguration: " + wifiConfiguration);
+            }
+            mHandler.post(() -> {
+                mCallback.onUserSelectionConnectSuccess(wifiConfiguration);
+            });
+        }
+
+        @Override
+        public void onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration) {
+            if (mVerboseLoggingEnabled) {
+                Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectFailure"
+                        + " wificonfiguration: " + wifiConfiguration);
+            }
+            mHandler.post(() -> {
+                mCallback.onUserSelectionConnectFailure(wifiConfiguration);
+            });
+        }
+    }
+
+    /**
+     * Registers a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}.
+     * Caller can unregister a previously registered callback using
+     * {@link #unregisterNetworkRequestMatchCallback(NetworkRequestMatchCallback)}
+     * <p>
+     * Applications should have the
+     * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers
+     * without the permission will trigger a {@link java.lang.SecurityException}.
+     * <p>
+     *
+     * @param callback Callback for network match events
+     * @param handler  The Handler on whose thread to execute the callbacks of the {@code callback}
+     *                 object. If null, then the application's main thread will be used.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void registerNetworkRequestMatchCallback(@NonNull NetworkRequestMatchCallback callback,
+                                                    @Nullable Handler handler) {
+        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+        Log.v(TAG, "registerNetworkRequestMatchCallback: callback=" + callback
+                + ", handler=" + handler);
+
+        Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
+        Binder binder = new Binder();
+        try {
+            mService.registerNetworkRequestMatchCallback(
+                    binder, new NetworkRequestMatchCallbackProxy(looper, callback),
+                    callback.hashCode());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Unregisters a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}.
+     * <p>
+     * Applications should have the
+     * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers
+     * without the permission will trigger a {@link java.lang.SecurityException}.
+     * <p>
+     *
+     * @param callback Callback for network match events
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void unregisterNetworkRequestMatchCallback(
+            @NonNull NetworkRequestMatchCallback callback) {
+        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+        Log.v(TAG, "unregisterNetworkRequestMatchCallback: callback=" + callback);
+
+        try {
+            mService.unregisterNetworkRequestMatchCallback(callback.hashCode());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Provide a list of network suggestions to the device. See {@link WifiNetworkSuggestion}
+     * for a detailed explanation of the parameters.
+     * When the device decides to connect to one of the provided network suggestions, platform sends
+     * a directed broadcast {@link #ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} to the app if
+     * the network was created with {@link WifiNetworkConfigBuilder#setIsAppInteractionRequired()}
+     * flag set and the app holds either one of
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission.
+     *<p>
+     * NOTE:
+     * <li> These networks are just a suggestion to the platform. The platform will ultimately
+     * decide on which network the device connects to. </li>
+     * <li> When an app is uninstalled, all its suggested networks are discarded. If the device is
+     * currently connected to a suggested network which is being removed then the device will
+     * disconnect from that network.</li>
+     * <li> No in-place modification of existing suggestions are allowed. Apps are expected to
+     * remove suggestions using {@link #removeNetworkSuggestions(List)} and then add the modified
+     * suggestion back using this API.</li>
+     *
+     * @param networkSuggestions List of network suggestions provided by the app.
+     * @return true on success, false if any of the suggestions match (See
+     * {@link WifiNetworkSuggestion#equals(Object)} any previously provided suggestions by the app.
+     * @throws {@link SecurityException} if the caller is missing required permissions.
+     */
+    @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
+    public boolean addNetworkSuggestions(@NonNull List<WifiNetworkSuggestion> networkSuggestions) {
+        try {
+            return mService.addNetworkSuggestions(networkSuggestions, mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+
+    /**
+     * Remove a subset of or all of networks from previously provided suggestions by the app to the
+     * device.
+     * See {@link WifiNetworkSuggestion} for a detailed explanation of the parameters.
+     * See {@link WifiNetworkSuggestion#equals(Object)} for the equivalence evaluation used.
+     *
+     * @param networkSuggestions List of network suggestions to be removed. Pass an empty list
+     *                           to remove all the previous suggestions provided by the app.
+     * @return true on success, false if any of the suggestions do not match any suggestions
+     * previously provided by the app. Any matching suggestions are removed from the device and
+     * will not be considered for any further connection attempts.
+     */
+    @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
+    public boolean removeNetworkSuggestions(
+            @NonNull List<WifiNetworkSuggestion> networkSuggestions) {
+        try {
+            return mService.removeNetworkSuggestions(
+                    networkSuggestions, mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Add or update a Passpoint configuration.  The configuration provides a credential
      * for connecting to Passpoint networks that are operated by the Passpoint
      * service provider specified in the configuration.
@@ -1299,7 +1649,17 @@
      * @param netId the ID of the network as returned by {@link #addNetwork} or {@link
      *        #getConfiguredNetworks}.
      * @return {@code true} if the operation succeeded
+     *
+     * @deprecated
+     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * mechanism to trigger connection to a Wi-Fi network.
+     * b) See {@link #addNetworkSuggestions(List)},
+     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
+     * when auto-connecting to wifi.
+     * <b>Compatibility Note:</b> For applications targeting
+     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false.
      */
+    @Deprecated
     public boolean removeNetwork(int netId) {
         try {
             return mService.removeNetwork(netId, mContext.getOpPackageName());
@@ -1314,10 +1674,8 @@
      * network is initiated. This may result in the asynchronous delivery
      * of state change events.
      * <p>
-     * <b>Note:</b> If an application's target SDK version is
-     * {@link android.os.Build.VERSION_CODES#LOLLIPOP} or newer, network
-     * communication may not use Wi-Fi even if Wi-Fi is connected; traffic may
-     * instead be sent through another network, such as cellular data,
+     * <b>Note:</b> Network communication may not use Wi-Fi even if Wi-Fi is connected;
+     * traffic may instead be sent through another network, such as cellular data,
      * Bluetooth tethering, or Ethernet. For example, traffic will never use a
      * Wi-Fi network that does not provide Internet access (e.g. a wireless
      * printer), if another network that does offer Internet access (e.g.
@@ -1335,29 +1693,24 @@
      * @param attemptConnect The way to select a particular network to connect to is specify
      *        {@code true} for this parameter.
      * @return {@code true} if the operation succeeded
+     *
+     * @deprecated
+     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * mechanism to trigger connection to a Wi-Fi network.
+     * b) See {@link #addNetworkSuggestions(List)},
+     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
+     * when auto-connecting to wifi.
+     * <b>Compatibility Note:</b> For applications targeting
+     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false.
      */
+    @Deprecated
     public boolean enableNetwork(int netId, boolean attemptConnect) {
-        final boolean pin = attemptConnect && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP;
-        if (pin) {
-            NetworkRequest request = new NetworkRequest.Builder()
-                    .clearCapabilities()
-                    .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
-                    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
-                    .build();
-            NetworkPinner.pin(mContext, request);
-        }
-
         boolean success;
         try {
             success = mService.enableNetwork(netId, attemptConnect, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
-
-        if (pin && !success) {
-            NetworkPinner.unpin();
-        }
-
         return success;
     }
 
@@ -1372,7 +1725,17 @@
      * @param netId the ID of the network as returned by {@link #addNetwork} or {@link
      *        #getConfiguredNetworks}.
      * @return {@code true} if the operation succeeded
+     *
+     * @deprecated
+     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * mechanism to trigger connection to a Wi-Fi network.
+     * b) See {@link #addNetworkSuggestions(List)},
+     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
+     * when auto-connecting to wifi.
+     * <b>Compatibility Note:</b> For applications targeting
+     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false.
      */
+    @Deprecated
     public boolean disableNetwork(int netId) {
         try {
             return mService.disableNetwork(netId, mContext.getOpPackageName());
@@ -1385,7 +1748,17 @@
      * Disassociate from the currently active access point. This may result
      * in the asynchronous delivery of state change events.
      * @return {@code true} if the operation succeeded
+     *
+     * @deprecated
+     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * mechanism to trigger connection to a Wi-Fi network.
+     * b) See {@link #addNetworkSuggestions(List)},
+     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
+     * when auto-connecting to wifi.
+     * <b>Compatibility Note:</b> For applications targeting
+     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false.
      */
+    @Deprecated
     public boolean disconnect() {
         try {
             mService.disconnect(mContext.getOpPackageName());
@@ -1400,7 +1773,17 @@
      * disconnected. This may result in the asynchronous delivery of state
      * change events.
      * @return {@code true} if the operation succeeded
+     *
+     * @deprecated
+     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * mechanism to trigger connection to a Wi-Fi network.
+     * b) See {@link #addNetworkSuggestions(List)},
+     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
+     * when auto-connecting to wifi.
+     * <b>Compatibility Note:</b> For applications targeting
+     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false.
      */
+    @Deprecated
     public boolean reconnect() {
         try {
             mService.reconnect(mContext.getOpPackageName());
@@ -1415,7 +1798,17 @@
      * connected. This may result in the asynchronous delivery of state
      * change events.
      * @return {@code true} if the operation succeeded
+     *
+     * @deprecated
+     * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new
+     * mechanism to trigger connection to a Wi-Fi network.
+     * b) See {@link #addNetworkSuggestions(List)},
+     * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration
+     * when auto-connecting to wifi.
+     * <b>Compatibility Note:</b> For applications targeting
+     * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false.
      */
+    @Deprecated
     public boolean reassociate() {
         try {
             mService.reassociate(mContext.getOpPackageName());
@@ -1490,7 +1883,12 @@
     public static final int WIFI_FEATURE_SCAN_RAND        = 0x2000000; // Random MAC & Probe seq
     /** @hide */
     public static final int WIFI_FEATURE_TX_POWER_LIMIT   = 0x4000000; // Set Tx power limit
-
+    /** @hide */
+    public static final int WIFI_FEATURE_WPA3_SAE         = 0x8000000; // WPA3-Personal SAE
+    /** @hide */
+    public static final int WIFI_FEATURE_WPA3_SUITE_B     = 0x10000000; // WPA3-Enterprise Suite-B
+    /** @hide */
+    public static final int WIFI_FEATURE_OWE              = 0x20000000; // Enhanced Open
 
     private int getSupportedFeatures() {
         try {
@@ -1715,7 +2113,10 @@
      * even when Wi-Fi is turned off.
      *
      * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}.
+     * @deprecated The ability for apps to trigger scan requests will be removed in a future
+     * release.
      */
+    @Deprecated
     public boolean isScanAlwaysAvailable() {
         try {
             return mService.isScanAlwaysAvailable();
@@ -1821,7 +2222,12 @@
      * @return {@code false} if the request cannot be satisfied; {@code true} indicates that wifi is
      *         either already in the requested state, or in progress toward the requested state.
      * @throws  {@link java.lang.SecurityException} if the caller is missing required permissions.
+     *
+     * @deprecated Starting with Build.VERSION_CODES#Q, applications are not allowed to
+     * enable/disable Wi-Fi regardless of application's target SDK. This API will have no effect
+     * and will always return false.
      */
+    @Deprecated
     public boolean setWifiEnabled(boolean enabled) {
         try {
             return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
@@ -3875,4 +4281,25 @@
     private void updateVerboseLoggingEnabledFromService() {
         mVerboseLoggingEnabled = getVerboseLoggingLevel() > 0;
     }
+
+    /**
+     * @return true if this device supports WPA3-Personal SAE
+     */
+    public boolean isWpa3SaeSupported() {
+        return isFeatureSupported(WIFI_FEATURE_WPA3_SAE);
+    }
+
+    /**
+     * @return true if this device supports WPA3-Enterprise Suite-B-192
+     */
+    public boolean isWpa3SuiteBSupported() {
+        return isFeatureSupported(WIFI_FEATURE_WPA3_SUITE_B);
+    }
+
+    /**
+     * @return true if this device supports Wi-Fi Enhanced Open (OWE)
+     */
+    public boolean isOweSupported() {
+        return isFeatureSupported(WIFI_FEATURE_OWE);
+    }
 }
diff --git a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
new file mode 100644
index 0000000..955e040
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+import static com.android.internal.util.Preconditions.checkState;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.MacAddress;
+import android.net.MatchAllNetworkSpecifier;
+import android.net.NetworkAgent;
+import android.net.NetworkRequest;
+import android.net.NetworkSpecifier;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Network specifier object used by wifi's {@link android.net.NetworkAgent}.
+ * @hide
+ */
+public final class WifiNetworkAgentSpecifier extends NetworkSpecifier implements Parcelable {
+    /**
+     * Security credentials for the currently connected network.
+     */
+    private final WifiConfiguration mWifiConfiguration;
+
+    /**
+     * The UID of the app that requested a specific wifi network using {@link WifiNetworkSpecifier}.
+     *
+     * Will only be filled when the device connects to a wifi network as a result of a
+     * {@link NetworkRequest} with {@link WifiNetworkSpecifier}. Will be set to -1 if the device
+     * auto-connected to a wifi network.
+     */
+    private final int mOriginalRequestorUid;
+
+    public WifiNetworkAgentSpecifier(@NonNull WifiConfiguration wifiConfiguration,
+                                     int originalRequestorUid) {
+        checkNotNull(wifiConfiguration);
+
+        mWifiConfiguration = wifiConfiguration;
+        mOriginalRequestorUid = originalRequestorUid;
+    }
+
+    /**
+     * @hide
+     */
+    public static final Creator<WifiNetworkAgentSpecifier> CREATOR =
+            new Creator<WifiNetworkAgentSpecifier>() {
+                @Override
+                public WifiNetworkAgentSpecifier createFromParcel(@NonNull Parcel in) {
+                    WifiConfiguration wifiConfiguration = in.readParcelable(null);
+                    int originalRequestorUid = in.readInt();
+                    return new WifiNetworkAgentSpecifier(wifiConfiguration, originalRequestorUid);
+                }
+
+                @Override
+                public WifiNetworkAgentSpecifier[] newArray(int size) {
+                    return new WifiNetworkAgentSpecifier[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeParcelable(mWifiConfiguration, flags);
+        dest.writeInt(mOriginalRequestorUid);
+    }
+
+    @Override
+    public boolean satisfiedBy(@Nullable NetworkSpecifier other) {
+        if (this == other) {
+            return true;
+        }
+        // Any generic requests should be satisifed by a specific wifi network.
+        if (other == null || other instanceof MatchAllNetworkSpecifier) {
+            return true;
+        }
+        if (other instanceof WifiNetworkSpecifier) {
+            return satisfiesNetworkSpecifier((WifiNetworkSpecifier) other);
+        }
+        return equals(other);
+    }
+
+    /**
+     * Match {@link WifiNetworkSpecifier} in app's {@link NetworkRequest} with the
+     * {@link WifiNetworkAgentSpecifier} in wifi platform's {@link NetworkAgent}.
+     */
+    public boolean satisfiesNetworkSpecifier(@NonNull WifiNetworkSpecifier ns) {
+        // None of these should be null by construction.
+        // {@link WifiNetworkConfigBuilder} enforces non-null in {@link WifiNetworkSpecifier}.
+        // {@link WifiNetworkFactory} ensures non-null in {@link WifiNetworkAgentSpecifier}.
+        checkNotNull(ns);
+        checkNotNull(ns.ssidPatternMatcher);
+        checkNotNull(ns.bssidPatternMatcher);
+        checkNotNull(ns.wifiConfiguration.allowedKeyManagement);
+        checkNotNull(this.mWifiConfiguration.SSID);
+        checkNotNull(this.mWifiConfiguration.BSSID);
+        checkNotNull(this.mWifiConfiguration.allowedKeyManagement);
+
+        final String ssidWithQuotes = this.mWifiConfiguration.SSID;
+        checkState(ssidWithQuotes.startsWith("\"") && ssidWithQuotes.endsWith("\""));
+        final String ssidWithoutQuotes = ssidWithQuotes.substring(1, ssidWithQuotes.length() - 1);
+        if (!ns.ssidPatternMatcher.match(ssidWithoutQuotes)) {
+            return false;
+        }
+        final MacAddress bssid = MacAddress.fromString(this.mWifiConfiguration.BSSID);
+        final MacAddress matchBaseAddress = ns.bssidPatternMatcher.first;
+        final MacAddress matchMask = ns.bssidPatternMatcher.second;
+        if (!bssid.matches(matchBaseAddress, matchMask))  {
+            return false;
+        }
+        if (!ns.wifiConfiguration.allowedKeyManagement.equals(
+                this.mWifiConfiguration.allowedKeyManagement)) {
+            return false;
+        }
+        if (ns.requestorUid != this.mOriginalRequestorUid) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+                mWifiConfiguration.SSID,
+                mWifiConfiguration.BSSID,
+                mWifiConfiguration.allowedKeyManagement,
+                mOriginalRequestorUid);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof WifiNetworkAgentSpecifier)) {
+            return false;
+        }
+        WifiNetworkAgentSpecifier lhs = (WifiNetworkAgentSpecifier) obj;
+        return Objects.equals(this.mWifiConfiguration.SSID, lhs.mWifiConfiguration.SSID)
+                && Objects.equals(this.mWifiConfiguration.BSSID, lhs.mWifiConfiguration.BSSID)
+                && Objects.equals(this.mWifiConfiguration.allowedKeyManagement,
+                    lhs.mWifiConfiguration.allowedKeyManagement)
+                && mOriginalRequestorUid == lhs.mOriginalRequestorUid;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("WifiNetworkAgentSpecifier [");
+        sb.append("WifiConfiguration=").append(
+                mWifiConfiguration == null ? null : mWifiConfiguration.configKey())
+                .append(", mOriginalRequestorUid=").append(mOriginalRequestorUid)
+                .append("]");
+        return sb.toString();
+    }
+
+    @Override
+    public void assertValidFromUid(int requestorUid) {
+        throw new IllegalStateException("WifiNetworkAgentSpecifier should never be used "
+                + "for requests.");
+    }
+}
diff --git a/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
new file mode 100644
index 0000000..aa8d325
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.MacAddress;
+import android.net.NetworkRequest;
+import android.net.NetworkSpecifier;
+import android.os.PatternMatcher;
+import android.os.Process;
+import android.text.TextUtils;
+import android.util.Pair;
+
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+/**
+ * WifiNetworkConfigBuilder to use for creating Wi-Fi network configuration.
+ * <li>See {@link #buildNetworkSpecifier()} for creating a network specifier to use in
+ * {@link NetworkRequest}.</li>
+ * <li>See {@link #buildNetworkSuggestion()} for creating a network suggestion to use in
+ * {@link WifiManager#addNetworkSuggestions(List)}.</li>
+ */
+public class WifiNetworkConfigBuilder {
+    private static final String MATCH_ALL_SSID_PATTERN_PATH = ".*";
+    private static final String MATCH_EMPTY_SSID_PATTERN_PATH = "";
+    private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN =
+            new Pair(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS);
+    private static final Pair<MacAddress, MacAddress> MATCH_ALL_BSSID_PATTERN =
+            new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS);
+    private static final MacAddress MATCH_EXACT_BSSID_PATTERN_MASK =
+            MacAddress.BROADCAST_ADDRESS;
+    private static final int UNASSIGNED_PRIORITY = -1;
+
+    /**
+     * SSID pattern match specified by the app.
+     */
+    private @Nullable PatternMatcher mSsidPatternMatcher;
+    /**
+     * BSSID pattern match specified by the app.
+     * Pair of <BaseAddress, Mask>.
+     */
+    private @Nullable Pair<MacAddress, MacAddress> mBssidPatternMatcher;
+    /**
+     * Pre-shared key for use with WPA-PSK networks.
+     */
+    private @Nullable String mPskPassphrase;
+    /**
+     * The enterprise configuration details specifying the EAP method,
+     * certificates and other settings associated with the EAP.
+     */
+    private @Nullable WifiEnterpriseConfig mEnterpriseConfig;
+    /**
+     * This is a network that does not broadcast its SSID, so an
+     * SSID-specific probe request must be used for scans.
+     */
+    private boolean mIsHiddenSSID;
+    /**
+     * Whether app needs to log in to captive portal to obtain Internet access.
+     */
+    private boolean mIsAppInteractionRequired;
+    /**
+     * Whether user needs to log in to captive portal to obtain Internet access.
+     */
+    private boolean mIsUserInteractionRequired;
+    /**
+     * Whether this network is metered or not.
+     */
+    private boolean mIsMetered;
+    /**
+     * Priority of this network among other network suggestions provided by the app.
+     * The lower the number, the higher the priority (i.e value of 0 = highest priority).
+     */
+    private int mPriority;
+
+    public WifiNetworkConfigBuilder() {
+        mSsidPatternMatcher = null;
+        mBssidPatternMatcher = null;
+        mPskPassphrase = null;
+        mEnterpriseConfig = null;
+        mIsHiddenSSID = false;
+        mIsAppInteractionRequired = false;
+        mIsUserInteractionRequired = false;
+        mIsMetered = false;
+        mPriority = UNASSIGNED_PRIORITY;
+    }
+
+    /**
+     * Set the unicode SSID match pattern to use for filtering networks from scan results.
+     * <p>
+     * <li>Only allowed for creating network specifier, i.e {@link #buildNetworkSpecifier()}. </li>
+     * <li>Overrides any previous value set using {@link #setSsid(String)} or
+     * {@link #setSsidPattern(PatternMatcher)}.</li>
+     *
+     * @param ssidPattern Instance of {@link PatternMatcher} containing the UTF-8 encoded
+     *                    string pattern to use for matching the network's SSID.
+     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
+     * method.
+     */
+    public WifiNetworkConfigBuilder setSsidPattern(@NonNull PatternMatcher ssidPattern) {
+        checkNotNull(ssidPattern);
+        mSsidPatternMatcher = ssidPattern;
+        return this;
+    }
+
+    /**
+     * Set the unicode SSID for the network.
+     * <p>
+     * <li>For network requests ({@link NetworkSpecifier}), built using
+     * {@link #buildNetworkSpecifier}, sets the SSID to use for filtering networks from scan
+     * results. Will only match networks whose SSID is identical to the UTF-8 encoding of the
+     * specified value.</li>
+     * <li>For network suggestions ({@link WifiNetworkSuggestion}), built using
+     * {@link #buildNetworkSuggestion()}, sets the SSID for the network.</li>
+     * <li>Overrides any previous value set using {@link #setSsid(String)} or
+     * {@link #setSsidPattern(PatternMatcher)}.</li>
+     *
+     * @param ssid The SSID of the network. It must be valid Unicode.
+     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
+     * method.
+     * @throws IllegalArgumentException if the SSID is not valid unicode.
+     */
+    public WifiNetworkConfigBuilder setSsid(@NonNull String ssid) {
+        checkNotNull(ssid);
+        final CharsetEncoder unicodeEncoder = StandardCharsets.UTF_8.newEncoder();
+        if (!unicodeEncoder.canEncode(ssid)) {
+            throw new IllegalArgumentException("SSID is not a valid unicode string");
+        }
+        mSsidPatternMatcher = new PatternMatcher(ssid, PatternMatcher.PATTERN_LITERAL);
+        return this;
+    }
+
+    /**
+     * Set the BSSID match pattern to use for filtering networks from scan results.
+     * Will match all networks with BSSID which satisfies the following:
+     * {@code BSSID & mask == baseAddress}.
+     * <p>
+     * <li>Only allowed for creating network specifier, i.e {@link #buildNetworkSpecifier()}. </li>
+     * <li>Overrides any previous value set using {@link #setBssid(MacAddress)} or
+     * {@link #setBssidPattern(MacAddress, MacAddress)}.</li>
+     *
+     * @param baseAddress Base address for BSSID pattern.
+     * @param mask Mask for BSSID pattern.
+     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
+     * method.
+     */
+    public WifiNetworkConfigBuilder setBssidPattern(
+            @NonNull MacAddress baseAddress, @NonNull MacAddress mask) {
+        checkNotNull(baseAddress, mask);
+        mBssidPatternMatcher = Pair.create(baseAddress, mask);
+        return this;
+    }
+
+    /**
+     * Set the BSSID to use for filtering networks from scan results. Will only match network whose
+     * BSSID is identical to the specified value.
+     * <p>
+     * <li>Only allowed for creating network specifier, i.e {@link #buildNetworkSpecifier()}. </li>
+     * <li>Overrides any previous value set using {@link #setBssid(MacAddress)} or
+     * {@link #setBssidPattern(MacAddress, MacAddress)}.</li>
+     *
+     * @param bssid BSSID of the network.
+     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
+     * method.
+     */
+    public WifiNetworkConfigBuilder setBssid(@NonNull MacAddress bssid) {
+        checkNotNull(bssid);
+        mBssidPatternMatcher = Pair.create(bssid, MATCH_EXACT_BSSID_PATTERN_MASK);
+        return this;
+    }
+
+    /**
+     * Set the ASCII PSK passphrase for this network. Needed for authenticating to
+     * WPA_PSK networks.
+     *
+     * @param pskPassphrase PSK passphrase of the network.
+     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
+     * method.
+     * @throws IllegalArgumentException if the passphrase is not ASCII encodable.
+     */
+    public WifiNetworkConfigBuilder setPskPassphrase(@NonNull String pskPassphrase) {
+        checkNotNull(pskPassphrase);
+        final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder();
+        if (!asciiEncoder.canEncode(pskPassphrase)) {
+            throw new IllegalArgumentException("passphrase not ASCII encodable");
+        }
+        mPskPassphrase = pskPassphrase;
+        return this;
+    }
+
+    /**
+     * Set the associated enterprise configuration for this network. Needed for authenticating to
+     * WPA_EAP networks. See {@link WifiEnterpriseConfig} for description.
+     *
+     * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
+     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
+     * method.
+     */
+    public WifiNetworkConfigBuilder setEnterpriseConfig(
+            @NonNull WifiEnterpriseConfig enterpriseConfig) {
+        checkNotNull(enterpriseConfig);
+        mEnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
+        return this;
+    }
+
+    /**
+     * Specifies whether this represents a hidden network.
+     * <p>
+     * <li>For network requests (see {@link NetworkSpecifier}), built using
+     * {@link #buildNetworkSpecifier}, setting this disallows the usage of
+     * {@link #setSsidPattern(PatternMatcher)} since hidden networks need to be explicitly
+     * probed for.</li>
+     * <li>If not set, defaults to false (i.e not a hidden network).</li>
+     *
+     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
+     * method.
+     */
+    public WifiNetworkConfigBuilder setIsHiddenSsid() {
+        mIsHiddenSSID = true;
+        return this;
+    }
+
+    /**
+     * Specifies whether the app needs to log in to a captive portal to obtain Internet access.
+     * <p>
+     * This will dictate if the directed broadcast
+     * {@link WifiManager#ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION} will be sent to the app
+     * after successfully connecting to the network.
+     * Use this for captive portal type networks where the app needs to authenticate the user
+     * before the device can access the network.
+     * <p>
+     * <li>Only allowed for creating network suggestion, i.e {@link #buildNetworkSuggestion()}.</li>
+     * <li>If not set, defaults to false (i.e no app interaction required).</li>
+     *
+     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
+     * method.
+     */
+    public WifiNetworkConfigBuilder setIsAppInteractionRequired() {
+        mIsAppInteractionRequired = true;
+        return this;
+    }
+
+    /**
+     * Specifies whether the user needs to log in to a captive portal to obtain Internet access.
+     * <p>
+     * <li>Only allowed for creating network suggestion, i.e {@link #buildNetworkSuggestion()}.</li>
+     * <li>If not set, defaults to false (i.e no user interaction required).</li>
+     *
+     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
+     * method.
+     */
+    public WifiNetworkConfigBuilder setIsUserInteractionRequired() {
+        mIsUserInteractionRequired = true;
+        return this;
+    }
+
+    /**
+     * Specify the priority of this network among other network suggestions provided by the same app
+     * (priorities have no impact on suggestions by different apps). The lower the number, the
+     * higher the priority (i.e value of 0 = highest priority).
+     * <p>
+     * <li>Only allowed for creating network suggestion, i.e {@link #buildNetworkSuggestion()}.</li>
+     * <li>If not set, defaults to -1 (i.e unassigned priority).</li>
+     *
+     * @param priority Integer number representing the priority among suggestions by the app.
+     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
+     * method.
+     * @throws IllegalArgumentException if the priority value is negative.
+     */
+    public WifiNetworkConfigBuilder setPriority(int priority) {
+        if (priority < 0) {
+            throw new IllegalArgumentException("Invalid priority value " + priority);
+        }
+        mPriority = priority;
+        return this;
+    }
+
+    /**
+     * Specifies whether this network is metered.
+     * <p>
+     * <li>Only allowed for creating network suggestion, i.e {@link #buildNetworkSuggestion()}.</li>
+     * <li>If not set, defaults to false (i.e not metered).</li>
+     *
+     * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder
+     * method.
+     */
+    public WifiNetworkConfigBuilder setIsMetered() {
+        mIsMetered = true;
+        return this;
+    }
+
+    /**
+     * Set defaults for the various low level credential type fields in the newly created
+     * WifiConfiguration object.
+     *
+     * See {@link com.android.server.wifi.WifiConfigManager#setDefaultsInWifiConfiguration(
+     * WifiConfiguration)}.
+     *
+     * @param configuration provided WifiConfiguration object.
+     */
+    private static void setDefaultsInWifiConfiguration(@NonNull WifiConfiguration configuration) {
+        configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+        configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+        configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+        configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+        configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
+    }
+
+    private void setKeyMgmtInWifiConfiguration(@NonNull WifiConfiguration configuration) {
+        if (!TextUtils.isEmpty(mPskPassphrase)) {
+            // WPA_PSK network.
+            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        } else if (mEnterpriseConfig != null) {
+            // WPA_EAP network
+            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+        } else {
+            // Open network
+            configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        }
+    }
+
+    /**
+     * Helper method to build WifiConfiguration object from the builder.
+     * @return Instance of {@link WifiConfiguration}.
+     */
+    private WifiConfiguration buildWifiConfiguration() {
+        final WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        setDefaultsInWifiConfiguration(wifiConfiguration);
+        // WifiConfiguration.SSID needs quotes around unicode SSID.
+        if (mSsidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL) {
+            wifiConfiguration.SSID = "\"" + mSsidPatternMatcher.getPath() + "\"";
+        }
+        setKeyMgmtInWifiConfiguration(wifiConfiguration);
+        // WifiConfiguration.preSharedKey needs quotes around ASCII password.
+        if (mPskPassphrase != null) {
+            wifiConfiguration.preSharedKey = "\"" + mPskPassphrase + "\"";
+        }
+        wifiConfiguration.enterpriseConfig = mEnterpriseConfig;
+        wifiConfiguration.hiddenSSID = mIsHiddenSSID;
+        wifiConfiguration.priority = mPriority;
+        wifiConfiguration.meteredOverride =
+                mIsMetered ? WifiConfiguration.METERED_OVERRIDE_METERED
+                           : WifiConfiguration.METERED_OVERRIDE_NONE;
+        return wifiConfiguration;
+    }
+
+    private boolean hasSetAnyPattern() {
+        return mSsidPatternMatcher != null || mBssidPatternMatcher != null;
+    }
+
+    private void setMatchAnyPatternIfUnset() {
+        if (mSsidPatternMatcher == null) {
+            mSsidPatternMatcher = new PatternMatcher(MATCH_ALL_SSID_PATTERN_PATH,
+                    PatternMatcher.PATTERN_SIMPLE_GLOB);
+        }
+        if (mBssidPatternMatcher == null) {
+            mBssidPatternMatcher = MATCH_ALL_BSSID_PATTERN;
+        }
+    }
+
+    private boolean hasSetMatchNonePattern() {
+        if (mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_PREFIX
+                && mSsidPatternMatcher.getPath().equals(MATCH_EMPTY_SSID_PATTERN_PATH)) {
+            return true;
+        }
+        if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN)) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean hasSetMatchAllPattern() {
+        if ((mSsidPatternMatcher.match(MATCH_EMPTY_SSID_PATTERN_PATH))
+                && mBssidPatternMatcher.equals(MATCH_ALL_BSSID_PATTERN)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Create a specifier object used to request a Wi-Fi network. The generated
+     * {@link NetworkSpecifier} should be used in
+     * {@link NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} when building
+     * the {@link NetworkRequest}.
+     *<p>
+     * Note: Apps can set a combination of network match params:
+     * <li> SSID Pattern using {@link #setSsidPattern(PatternMatcher)} OR Specific SSID using
+     * {@link #setSsid(String)}. </li>
+     * AND/OR
+     * <li> BSSID Pattern using {@link #setBssidPattern(MacAddress, MacAddress)} OR Specific BSSID
+     * using {@link #setBssid(MacAddress)} </li>
+     * to trigger connection to a network that matches the set params.
+     * The system will find the set of networks matching the request and present the user
+     * with a system dialog which will allow the user to select a specific Wi-Fi network to connect
+     * to or to deny the request.
+     *</p>
+     *
+     * For example:
+     * To connect to an open network with a SSID prefix of "test" and a BSSID OUI of "10:03:23":
+     * {@code
+     * final NetworkSpecifier specifier =
+     *      new WifiNetworkConfigBuilder()
+     *      .setSsidPattern(new PatternMatcher("test", PatterMatcher.PATTERN_PREFIX))
+     *      .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"),
+     *                       MacAddress.fromString("ff:ff:ff:00:00:00"))
+     *      .buildNetworkSpecifier()
+     * final NetworkRequest request =
+     *      new NetworkRequest.Builder()
+     *      .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+     *      .setNetworkSpecifier(specifier)
+     *      .build();
+     * final ConnectivityManager connectivityManager =
+     *      context.getSystemService(Context.CONNECTIVITY_SERVICE);
+     * final NetworkCallback networkCallback = new NetworkCallback() {
+     *      ...
+     *      {@literal @}Override
+     *      void onAvailable(...) {}
+     *      // etc.
+     * };
+     * connectivityManager.requestNetwork(request, networkCallback);
+     * }
+     *
+     * @return Instance of {@link NetworkSpecifier}.
+     * @throws IllegalStateException on invalid params set.
+     */
+    public NetworkSpecifier buildNetworkSpecifier() {
+        if (!hasSetAnyPattern()) {
+            throw new IllegalStateException("one of setSsidPattern/setSsid/setBssidPattern/setBssid"
+                    + " should be invoked for specifier");
+        }
+        setMatchAnyPatternIfUnset();
+        if (hasSetMatchNonePattern()) {
+            throw new IllegalStateException("cannot set match-none pattern for specifier");
+        }
+        if (hasSetMatchAllPattern()) {
+            throw new IllegalStateException("cannot set match-all pattern for specifier");
+        }
+        if (mIsHiddenSSID && mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_LITERAL) {
+            throw new IllegalStateException("setSsid should also be invoked when "
+                    + "setIsHiddenSsid is invoked for network specifier");
+        }
+        if (mIsAppInteractionRequired || mIsUserInteractionRequired
+                || mPriority != -1 || mIsMetered) {
+            throw new IllegalStateException("none of setIsAppInteractionRequired/"
+                    + "setIsUserInteractionRequired/setPriority/setIsMetered are allowed for "
+                    + "specifier");
+        }
+        if (!TextUtils.isEmpty(mPskPassphrase) && mEnterpriseConfig != null) {
+            throw new IllegalStateException("only one of setPreSharedKey or setEnterpriseConfig can"
+                    + " be invoked for network specifier");
+        }
+
+        return new WifiNetworkSpecifier(
+                mSsidPatternMatcher,
+                mBssidPatternMatcher,
+                buildWifiConfiguration(),
+                Process.myUid());
+    }
+
+    /**
+     * Create a network suggestion object use in
+     * {@link WifiManager#addNetworkSuggestions(List)}.
+     * See {@link WifiNetworkSuggestion}.
+     *
+     * @return Instance of {@link WifiNetworkSuggestion}.
+     * @throws IllegalStateException on invalid params set.
+     */
+    public WifiNetworkSuggestion buildNetworkSuggestion() {
+        if (mSsidPatternMatcher == null) {
+            throw new IllegalStateException("setSsid should be invoked for suggestion");
+        }
+        if (mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_LITERAL
+                || mBssidPatternMatcher != null) {
+            throw new IllegalStateException("none of setSsidPattern/setBssidPattern/setBssid are"
+                    + " allowed for suggestion");
+        }
+        if (!TextUtils.isEmpty(mPskPassphrase) && mEnterpriseConfig != null) {
+            throw new IllegalStateException("only one of setPreSharedKey or setEnterpriseConfig can"
+                    + "be invoked for suggestion");
+        }
+
+        return new WifiNetworkSuggestion(
+                buildWifiConfiguration(),
+                mIsAppInteractionRequired,
+                mIsUserInteractionRequired,
+                Process.myUid());
+
+    }
+}
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
new file mode 100644
index 0000000..4348399
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.NonNull;
+import android.net.MacAddress;
+import android.net.MatchAllNetworkSpecifier;
+import android.net.NetworkSpecifier;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.PatternMatcher;
+import android.util.Pair;
+
+import java.util.Objects;
+
+/**
+ * Network specifier object used to request a Wi-Fi network. Apps should use the
+ * {@link WifiNetworkConfigBuilder} class to create an instance.
+ * @hide
+ */
+public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+    /**
+     * SSID pattern match specified by the app.
+     */
+    public final PatternMatcher ssidPatternMatcher;
+
+    /**
+     * BSSID pattern match specified by the app.
+     * Pair of <BaseAddress, Mask>.
+     */
+    public final Pair<MacAddress, MacAddress> bssidPatternMatcher;
+
+    /**
+     * Security credentials for the network.
+     * <p>
+     * Note: {@link WifiConfiguration#SSID} & {@link WifiConfiguration#BSSID} fields from
+     * WifiConfiguration are not used. Instead we use the {@link #ssidPatternMatcher} &
+     * {@link #bssidPatternMatcher} fields embedded directly
+     * within {@link WifiNetworkSpecifier}.
+     */
+    public final WifiConfiguration wifiConfiguration;
+
+    /**
+     * The UID of the process initializing this network specifier. Validated by receiver using
+     * checkUidIfNecessary() and is used by satisfiedBy() to determine whether the specifier
+     * matches the offered network.
+     */
+    public final int requestorUid;
+
+    public WifiNetworkSpecifier(@NonNull PatternMatcher ssidPatternMatcher,
+                 @NonNull Pair<MacAddress, MacAddress> bssidPatternMatcher,
+                 @NonNull WifiConfiguration wifiConfiguration,
+                 int requestorUid) {
+        checkNotNull(ssidPatternMatcher);
+        checkNotNull(bssidPatternMatcher);
+        checkNotNull(wifiConfiguration);
+
+        this.ssidPatternMatcher = ssidPatternMatcher;
+        this.bssidPatternMatcher = bssidPatternMatcher;
+        this.wifiConfiguration = wifiConfiguration;
+        this.requestorUid = requestorUid;
+    }
+
+    public static final Creator<WifiNetworkSpecifier> CREATOR =
+            new Creator<WifiNetworkSpecifier>() {
+                @Override
+                public WifiNetworkSpecifier createFromParcel(Parcel in) {
+                    PatternMatcher ssidPatternMatcher = in.readParcelable(/* classLoader */null);
+                    MacAddress baseAddress = in.readParcelable(null);
+                    MacAddress mask = in.readParcelable(null);
+                    Pair<MacAddress, MacAddress> bssidPatternMatcher =
+                            Pair.create(baseAddress, mask);
+                    WifiConfiguration wifiConfiguration = in.readParcelable(null);
+                    int requestorUid = in.readInt();
+                    return new WifiNetworkSpecifier(ssidPatternMatcher, bssidPatternMatcher,
+                            wifiConfiguration, requestorUid);
+                }
+
+                @Override
+                public WifiNetworkSpecifier[] newArray(int size) {
+                    return new WifiNetworkSpecifier[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(ssidPatternMatcher, flags);
+        dest.writeParcelable(bssidPatternMatcher.first, flags);
+        dest.writeParcelable(bssidPatternMatcher.second, flags);
+        dest.writeParcelable(wifiConfiguration, flags);
+        dest.writeInt(requestorUid);
+    }
+
+    @Override
+    public boolean satisfiedBy(NetworkSpecifier other) {
+        if (this == other) {
+            return true;
+        }
+        // Any generic requests should be satisifed by a specific wifi network.
+        if (other == null || other instanceof MatchAllNetworkSpecifier) {
+            return true;
+        }
+        if (other instanceof WifiNetworkAgentSpecifier) {
+            return ((WifiNetworkAgentSpecifier) other).satisfiesNetworkSpecifier(this);
+        }
+        // Specific requests are checked for equality although testing for equality of 2 patterns do
+        // not make much sense!
+        return equals(other);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+                ssidPatternMatcher.getPath(),
+                ssidPatternMatcher.getType(),
+                bssidPatternMatcher,
+                wifiConfiguration.allowedKeyManagement,
+                requestorUid);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof WifiNetworkSpecifier)) {
+            return false;
+        }
+        WifiNetworkSpecifier lhs = (WifiNetworkSpecifier) obj;
+        return Objects.equals(this.ssidPatternMatcher.getPath(),
+                    lhs.ssidPatternMatcher.getPath())
+                && Objects.equals(this.ssidPatternMatcher.getType(),
+                    lhs.ssidPatternMatcher.getType())
+                && Objects.equals(this.bssidPatternMatcher,
+                    lhs.bssidPatternMatcher)
+                && Objects.equals(this.wifiConfiguration.allowedKeyManagement,
+                    lhs.wifiConfiguration.allowedKeyManagement)
+                && requestorUid == lhs.requestorUid;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder()
+                .append("WifiNetworkSpecifierWifiNetworkSpecifier [")
+                .append(", SSID Match pattern=").append(ssidPatternMatcher)
+                .append(", BSSID Match pattern=").append(bssidPatternMatcher)
+                .append(", WifiConfiguration=").append(
+                wifiConfiguration == null ? null : wifiConfiguration.configKey())
+                .append(", requestorUid=").append(requestorUid)
+                .append("]")
+                .toString();
+    }
+
+    @Override
+    public void assertValidFromUid(int requestorUid) {
+        if (this.requestorUid != requestorUid) {
+            throw new SecurityException("mismatched UIDs");
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/IRcs.aidl b/wifi/java/android/net/wifi/WifiNetworkSuggestion.aidl
similarity index 71%
copy from telephony/java/com/android/internal/telephony/IRcs.aidl
copy to wifi/java/android/net/wifi/WifiNetworkSuggestion.aidl
index ede8695..eb6995f 100644
--- a/telephony/java/com/android/internal/telephony/IRcs.aidl
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
+/**
+ * Copyright (c) 2018, 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
+ *     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,
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony;
+package android.net.wifi;
 
-interface IRcs {
-    void deleteThread(int threadId);
-}
\ No newline at end of file
+parcelable WifiNetworkSuggestion;
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
new file mode 100644
index 0000000..25121e2
--- /dev/null
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * The Network Suggestion object is used to provide a Wi-Fi network for consideration when
+ * auto-connecting to networks. Apps cannot directly create this object, they must use
+ * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} to obtain an instance
+ * of this object.
+ *<p>
+ * Apps can provide a list of such networks to the platform using
+ * {@link WifiManager#addNetworkSuggestions(List)}.
+ */
+public final class WifiNetworkSuggestion implements Parcelable {
+    /**
+     * Network configuration for the provided network.
+     * @hide
+     */
+    public final WifiConfiguration wifiConfiguration;
+
+    /**
+     * Whether app needs to log in to captive portal to obtain Internet access.
+     * @hide
+     */
+    public final boolean isAppInteractionRequired;
+
+    /**
+     * Whether user needs to log in to captive portal to obtain Internet access.
+     * @hide
+     */
+    public final boolean isUserInteractionRequired;
+
+    /**
+     * The UID of the process initializing this network suggestion.
+     * @hide
+     */
+    public final int suggestorUid;
+
+    /** @hide */
+    public WifiNetworkSuggestion(WifiConfiguration wifiConfiguration,
+                                 boolean isAppInteractionRequired,
+                                 boolean isUserInteractionRequired,
+                                 int suggestorUid) {
+        checkNotNull(wifiConfiguration);
+
+        this.wifiConfiguration = wifiConfiguration;
+        this.isAppInteractionRequired = isAppInteractionRequired;
+        this.isUserInteractionRequired = isUserInteractionRequired;
+        this.suggestorUid = suggestorUid;
+    }
+
+    public static final Creator<WifiNetworkSuggestion> CREATOR =
+            new Creator<WifiNetworkSuggestion>() {
+                @Override
+                public WifiNetworkSuggestion createFromParcel(Parcel in) {
+                    return new WifiNetworkSuggestion(
+                            in.readParcelable(null), // wifiConfiguration
+                            in.readBoolean(), // isAppInteractionRequired
+                            in.readBoolean(), // isUserInteractionRequired
+                            in.readInt() // suggestorUid
+                    );
+                }
+
+                @Override
+                public WifiNetworkSuggestion[] newArray(int size) {
+                    return new WifiNetworkSuggestion[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(wifiConfiguration, flags);
+        dest.writeBoolean(isAppInteractionRequired);
+        dest.writeBoolean(isUserInteractionRequired);
+        dest.writeInt(suggestorUid);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.allowedKeyManagement,
+                suggestorUid);
+    }
+
+    /**
+     * Equals for network suggestions.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof WifiNetworkSuggestion)) {
+            return false;
+        }
+        WifiNetworkSuggestion lhs = (WifiNetworkSuggestion) obj;
+        return Objects.equals(this.wifiConfiguration.SSID, lhs.wifiConfiguration.SSID)
+                && Objects.equals(this.wifiConfiguration.allowedKeyManagement,
+                                  lhs.wifiConfiguration.allowedKeyManagement)
+                && suggestorUid == lhs.suggestorUid;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("WifiNetworkSuggestion [")
+                .append(", WifiConfiguration=").append(wifiConfiguration)
+                .append(", isAppInteractionRequired=").append(isAppInteractionRequired)
+                .append(", isUserInteractionRequired=").append(isUserInteractionRequired)
+                .append(", suggestorUid=").append(suggestorUid)
+                .append("]");
+        return sb.toString();
+    }
+}
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 71d4173..26bdb18 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -20,10 +20,10 @@
 import android.net.wifi.hotspot2.pps.HomeSp;
 import android.net.wifi.hotspot2.pps.Policy;
 import android.net.wifi.hotspot2.pps.UpdateParameter;
+import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
 import android.util.Log;
-import android.os.Parcel;
 
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
@@ -467,24 +467,54 @@
     }
 
     /**
-     * Validate the configuration data.
+     * Validate the R1 configuration data.
      *
      * @return true on success or false on failure
      * @hide
      */
     public boolean validate() {
-        if (mHomeSp == null || !mHomeSp.validate()) {
-            return false;
-        }
-        if (mCredential == null || !mCredential.validate()) {
-            return false;
-        }
-        if (mPolicy != null && !mPolicy.validate()) {
-            return false;
-        }
+        // Optional: PerProviderSubscription/<X+>/SubscriptionUpdate
         if (mSubscriptionUpdate != null && !mSubscriptionUpdate.validate()) {
             return false;
         }
+        return validateForCommonR1andR2(true);
+    }
+
+    /**
+     * Validate the R2 configuration data.
+     *
+     * @return true on success or false on failure
+     * @hide
+     */
+    public boolean validateForR2() {
+        // Required: PerProviderSubscription/UpdateIdentifier
+        if (mUpdateIdentifier == Integer.MIN_VALUE) {
+            return false;
+        }
+
+        // Required: PerProviderSubscription/<X+>/SubscriptionUpdate
+        if (mSubscriptionUpdate == null || !mSubscriptionUpdate.validate()) {
+            return false;
+        }
+        return validateForCommonR1andR2(false);
+    }
+
+    private boolean validateForCommonR1andR2(boolean isR1) {
+        // Required: PerProviderSubscription/<X+>/HomeSP
+        if (mHomeSp == null || !mHomeSp.validate()) {
+            return false;
+        }
+
+        // Required: PerProviderSubscription/<X+>/Credential
+        if (mCredential == null || !mCredential.validate(isR1)) {
+            return false;
+        }
+
+        // Optional: PerProviderSubscription/<X+>/Policy
+        if (mPolicy != null && !mPolicy.validate()) {
+            return false;
+        }
+
         if (mTrustRootCertList != null) {
             for (Map.Entry<String, byte[]> entry : mTrustRootCertList.entrySet()) {
                 String url = entry.getKey();
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index e8fcbfd..7689fc3 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -18,8 +18,8 @@
 
 import android.net.wifi.EAPConstants;
 import android.net.wifi.ParcelUtil;
-import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -1019,10 +1019,11 @@
     /**
      * Validate the configuration data.
      *
+     * @param isR1 {@code true} if the configuration is for R1
      * @return true on success or false on failure
      * @hide
      */
-    public boolean validate() {
+    public boolean validate(boolean isR1) {
         if (TextUtils.isEmpty(mRealm)) {
             Log.d(TAG, "Missing realm");
             return false;
@@ -1035,11 +1036,11 @@
 
         // Verify the credential.
         if (mUserCredential != null) {
-            if (!verifyUserCredential()) {
+            if (!verifyUserCredential(isR1)) {
                 return false;
             }
         } else if (mCertCredential != null) {
-            if (!verifyCertCredential()) {
+            if (!verifyCertCredential(isR1)) {
                 return false;
             }
         } else if (mSimCredential != null) {
@@ -1081,9 +1082,10 @@
     /**
      * Verify user credential.
      *
+     * @param isR1 {@code true} if credential is for R1
      * @return true if user credential is valid, false otherwise.
      */
-    private boolean verifyUserCredential() {
+    private boolean verifyUserCredential(boolean isR1) {
         if (mUserCredential == null) {
             Log.d(TAG, "Missing user credential");
             return false;
@@ -1095,7 +1097,10 @@
         if (!mUserCredential.validate()) {
             return false;
         }
-        if (mCaCertificate == null) {
+
+        // CA certificate is required for R1 Passpoint profile.
+        // For R2, it is downloaded using cert URL provided in PPS MO after validation completes.
+        if (isR1 && mCaCertificate == null) {
             Log.d(TAG, "Missing CA Certificate for user credential");
             return false;
         }
@@ -1106,9 +1111,10 @@
      * Verify certificate credential, which is used for EAP-TLS.  This will verify
      * that the necessary client key and certificates are provided.
      *
+     * @param isR1 {@code true} if credential is for R1
      * @return true if certificate credential is valid, false otherwise.
      */
-    private boolean verifyCertCredential() {
+    private boolean verifyCertCredential(boolean isR1) {
         if (mCertCredential == null) {
             Log.d(TAG, "Missing certificate credential");
             return false;
@@ -1123,7 +1129,9 @@
         }
 
         // Verify required key and certificates for certificate credential.
-        if (mCaCertificate == null) {
+        // CA certificate is required for R1 Passpoint profile.
+        // For R2, it is downloaded using cert URL provided in PPS MO after validation completes.
+        if (isR1 && mCaCertificate == null) {
             Log.d(TAG, "Missing CA Certificate for certificate credential");
             return false;
         }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 5a4c898..f58a006 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -16,9 +16,13 @@
 
 package android.net.wifi.p2p;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
-import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.net.wifi.WpsInfo;
@@ -480,6 +484,23 @@
     /** @hide */
     public static final int REPORT_NFC_HANDOVER_FAILED              = BASE + 81;
 
+    /** @hide */
+    public static final int FACTORY_RESET                           = BASE + 82;
+    /** @hide */
+    public static final int FACTORY_RESET_FAILED                    = BASE + 83;
+    /** @hide */
+    public static final int FACTORY_RESET_SUCCEEDED                 = BASE + 84;
+
+    /** @hide */
+    public static final int REQUEST_ONGOING_PEER_CONFIG             = BASE + 85;
+    /** @hide */
+    public static final int RESPONSE_ONGOING_PEER_CONFIG            = BASE + 86;
+    /** @hide */
+    public static final int SET_ONGOING_PEER_CONFIG                 = BASE + 87;
+    /** @hide */
+    public static final int SET_ONGOING_PEER_CONFIG_FAILED          = BASE + 88;
+    /** @hide */
+    public static final int SET_ONGOING_PEER_CONFIG_SUCCEEDED       = BASE + 89;
 
     /**
      * Create a new WifiP2pManager instance. Applications use
@@ -670,6 +691,18 @@
     }
 
     /**
+     * Interface for callback invocation when ongoing peer info is available
+     * @hide
+     */
+    public interface OngoingPeerInfoListener {
+        /**
+         * The requested ongoing WifiP2pConfig is available
+         * @param peerConfig WifiP2pConfig for current connecting session
+         */
+        void onOngoingPeerAvailable(WifiP2pConfig peerConfig);
+    }
+
+    /**
      * A channel that connects the application to the Wifi p2p framework.
      * Most p2p operations require a Channel as an argument. An instance of Channel is obtained
      * by doing a call on {@link #initialize}
@@ -776,6 +809,8 @@
                     case STOP_LISTEN_FAILED:
                     case SET_CHANNEL_FAILED:
                     case REPORT_NFC_HANDOVER_FAILED:
+                    case FACTORY_RESET_FAILED:
+                    case SET_ONGOING_PEER_CONFIG_FAILED:
                         if (listener != null) {
                             ((ActionListener) listener).onFailure(message.arg1);
                         }
@@ -802,6 +837,8 @@
                     case STOP_LISTEN_SUCCEEDED:
                     case SET_CHANNEL_SUCCEEDED:
                     case REPORT_NFC_HANDOVER_SUCCEEDED:
+                    case FACTORY_RESET_SUCCEEDED:
+                    case SET_ONGOING_PEER_CONFIG_SUCCEEDED:
                         if (listener != null) {
                             ((ActionListener) listener).onSuccess();
                         }
@@ -845,6 +882,13 @@
                                     .onHandoverMessageAvailable(handoverMessage);
                         }
                         break;
+                    case RESPONSE_ONGOING_PEER_CONFIG:
+                        WifiP2pConfig peerConfig = (WifiP2pConfig) message.obj;
+                        if (listener != null) {
+                            ((OngoingPeerInfoListener) listener)
+                                    .onOngoingPeerAvailable(peerConfig);
+                        }
+                        break;
                     default:
                         Log.d(TAG, "Ignored " + message);
                         break;
@@ -1521,4 +1565,55 @@
         c.mAsyncChannel.sendMessage(RESPONDER_REPORT_NFC_HANDOVER, 0,
                 c.putListener(listener), bundle);
     }
+
+    /**
+     * Removes all saved p2p groups.
+     *
+     * @param c is the channel created at {@link #initialize}.
+     * @param listener for callback on success or failure. Can be null.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void factoryReset(@NonNull Channel c, @Nullable ActionListener listener) {
+        checkChannel(c);
+        Bundle callingPackage = new Bundle();
+        callingPackage.putString(CALLING_PACKAGE, c.mContext.getOpPackageName());
+        c.mAsyncChannel.sendMessage(FACTORY_RESET, 0, c.putListener(listener),
+                callingPackage);
+    }
+
+    /**
+     * Request saved WifiP2pConfig which used for an ongoing peer connection
+     *
+     * @param c is the channel created at {@link #initialize}
+     * @param listener for callback when ongoing peer config updated. Can't be null.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
+    public void requestOngoingPeerConfig(@NonNull Channel c,
+            @NonNull OngoingPeerInfoListener listener) {
+        checkChannel(c);
+        c.mAsyncChannel.sendMessage(REQUEST_ONGOING_PEER_CONFIG,
+                Binder.getCallingUid(), c.putListener(listener));
+    }
+
+     /**
+     * Set saved WifiP2pConfig which used for an ongoing peer connection
+     *
+     * @param c is the channel created at {@link #initialize}
+     * @param config used for change an ongoing peer connection
+     * @param listener for callback when ongoing peer config updated. Can be null.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
+    public void setOngoingPeerConfig(@NonNull Channel c, @NonNull WifiP2pConfig config,
+            @Nullable ActionListener listener) {
+        checkChannel(c);
+        checkP2pConfig(config);
+        c.mAsyncChannel.sendMessage(SET_ONGOING_PEER_CONFIG, 0,
+                c.putListener(listener), config);
+    }
 }
diff --git a/wifi/java/com/android/server/wifi/AbstractWifiService.java b/wifi/java/com/android/server/wifi/AbstractWifiService.java
new file mode 100644
index 0000000..04bc557
--- /dev/null
+++ b/wifi/java/com/android/server/wifi/AbstractWifiService.java
@@ -0,0 +1,455 @@
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License") {
+ *  throw new UnsupportedOperationException();
+ }
+ * 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.wifi;
+
+import android.content.pm.ParceledListSlice;
+import android.net.DhcpInfo;
+import android.net.Network;
+import android.net.wifi.INetworkRequestMatchCallback;
+import android.net.wifi.ISoftApCallback;
+import android.net.wifi.ITrafficStateCallback;
+import android.net.wifi.IWifiManager;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiActivityEnergyInfo;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiNetworkSuggestion;
+import android.net.wifi.hotspot2.IProvisioningCallback;
+import android.net.wifi.hotspot2.OsuProvider;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.os.IBinder;
+import android.os.Messenger;
+import android.os.ResultReceiver;
+import android.os.WorkSource;
+
+import java.util.List;
+
+/**
+ * Abstract class implementing IWifiManager with stub methods throwing runtime exceptions.
+ *
+ * This class is meant to be extended by real implementations of IWifiManager in order to facilitate
+ * cross-repo changes to WiFi internal APIs, including the introduction of new APIs, the removal of
+ * deprecated APIs, or the migration of existing API signatures.
+ *
+ * When an existing API is scheduled for removal, it can be removed from IWifiManager.aidl
+ * immediately and marked as @Deprecated first in this class. Children inheriting this class are
+ * then given a short grace period to update themselves before the @Deprecated stub is removed for
+ * good. If the API scheduled for removal has a replacement or an overload (signature change),
+ * these should be introduced before the stub is removed to allow children to migrate.
+ */
+public abstract class AbstractWifiService extends IWifiManager.Stub {
+
+    private static final String TAG = AbstractWifiService.class.getSimpleName();
+
+    @Override
+    public int getSupportedFeatures() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public WifiActivityEnergyInfo reportActivityInfo() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void requestActivityInfo(ResultReceiver result) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ParceledListSlice getConfiguredNetworks() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ParceledListSlice getPrivilegedConfiguredNetworks() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns a WifiConfiguration matching this ScanResult
+     * @param scanResult a single ScanResult Object
+     * @return
+     * @deprecated use {@link #getAllMatchingWifiConfigs(List)} instead.
+     */
+    @Deprecated
+    public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns all matching WifiConfigurations for this ScanResult.
+     * @param scanResult a single ScanResult Object
+     * @return
+     * @deprecated use {@link #getAllMatchingWifiConfigs(List)} instead.
+     */
+    @Deprecated
+    public List<WifiConfiguration> getAllMatchingWifiConfigs(ScanResult scanResult) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<WifiConfiguration> getAllMatchingWifiConfigs(List<ScanResult> scanResults) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns a list of Hotspot 2.0 OSU (Online Sign-Up) providers associated with the given AP.
+     *
+     * @param scanResult a single ScanResult Object
+     * @return
+     * @deprecated use {@link #getMatchingOsuProviders(List)} instead.
+     */
+    @Deprecated
+    public List<OsuProvider> getMatchingOsuProviders(ScanResult scanResult) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<OsuProvider> getMatchingOsuProviders(List<ScanResult> scanResults) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int addOrUpdateNetwork(WifiConfiguration config, String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean addOrUpdatePasspointConfiguration(
+            PasspointConfiguration config, String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean removePasspointConfiguration(String fqdn, String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<PasspointConfiguration> getPasspointConfigurations() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void queryPasspointIcon(long bssid, String fileName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int matchProviderWithCurrentNetwork(String fqdn) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void deauthenticateNetwork(long holdoff, boolean ess) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean removeNetwork(int netId, String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean enableNetwork(int netId, boolean disableOthers, String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean disableNetwork(int netId, String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean startScan(String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public List<ScanResult> getScanResults(String callingPackage) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void disconnect(String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void reconnect(String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void reassociate(String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public WifiInfo getConnectionInfo(String callingPackage) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean setWifiEnabled(String packageName, boolean enable) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getWifiEnabledState() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void setCountryCode(String country) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getCountryCode() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isDualBandSupported() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean needs5GHzToAnyApBandConversion() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public DhcpInfo getDhcpInfo() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isScanAlwaysAvailable() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean acquireWifiLock(IBinder lock, int lockType, String tag, WorkSource ws) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void updateWifiLockWorkSource(IBinder lock, WorkSource ws) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean releaseWifiLock(IBinder lock) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void initializeMulticastFiltering() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isMulticastEnabled() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void acquireMulticastLock(IBinder binder, String tag) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void releaseMulticastLock(String tag) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void updateInterfaceIpState(String ifaceName, int mode) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean startSoftAp(WifiConfiguration wifiConfig) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean stopSoftAp() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int startLocalOnlyHotspot(Messenger messenger, IBinder binder, String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void stopLocalOnlyHotspot() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void startWatchLocalOnlyHotspot(Messenger messenger, IBinder binder) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void stopWatchLocalOnlyHotspot() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getWifiApEnabledState() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public WifiConfiguration getWifiApConfiguration() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void notifyUserOfApBandConversion(String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Messenger getWifiServiceMessenger(String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void enableTdls(String remoteIPAddress, boolean enable) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getCurrentNetworkWpsNfcConfigurationToken() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void enableVerboseLogging(int verbose) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getVerboseLoggingLevel() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void enableWifiConnectivityManager(boolean enabled) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void disableEphemeralNetwork(String SSID, String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void factoryReset(String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Network getCurrentNetwork() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public byte[] retrieveBackupData() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void restoreBackupData(byte[] data) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void startSubscriptionProvisioning(
+            OsuProvider provider, IProvisioningCallback callback) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void registerSoftApCallback(
+            IBinder binder, ISoftApCallback callback, int callbackIdentifier) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void unregisterSoftApCallback(int callbackIdentifier) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void registerTrafficStateCallback(
+            IBinder binder, ITrafficStateCallback callback, int callbackIdentifier) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void unregisterTrafficStateCallback(int callbackIdentifier) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void registerNetworkRequestMatchCallback(
+            IBinder binder, INetworkRequestMatchCallback callback, int callbackIdentifier) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void unregisterNetworkRequestMatchCallback(int callbackIdentifier) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean addNetworkSuggestions(
+            List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean removeNetworkSuggestions(
+            List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName) {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index 3b9f93e..8d97307 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -23,6 +23,7 @@
 import static org.junit.Assert.assertTrue;
 
 import android.net.MacAddress;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
@@ -30,6 +31,9 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+
 /**
  * Unit tests for {@link android.net.wifi.WifiConfiguration}.
  */
@@ -53,6 +57,7 @@
         String cookie = "C O.o |<IE";
         WifiConfiguration config = new WifiConfiguration();
         config.setPasspointManagementObjectTree(cookie);
+        config.trusted = false;
         MacAddress macBeforeParcel = config.getOrCreateRandomizedMacAddress();
         Parcel parcelW = Parcel.obtain();
         config.writeToParcel(parcelW, 0);
@@ -67,6 +72,7 @@
         // lacking a useful config.equals, check two fields near the end.
         assertEquals(cookie, reconfig.getMoTree());
         assertEquals(macBeforeParcel, reconfig.getOrCreateRandomizedMacAddress());
+        assertFalse(reconfig.trusted);
 
         Parcel parcelWW = Parcel.obtain();
         reconfig.writeToParcel(parcelWW, 0);
@@ -155,7 +161,10 @@
     @Test
     public void testIsOpenNetwork_NotOpen_HasAuthType() {
         for (int keyMgmt = 0; keyMgmt < WifiConfiguration.KeyMgmt.strings.length; keyMgmt++) {
-            if (keyMgmt == WifiConfiguration.KeyMgmt.NONE) continue;
+            if (keyMgmt == WifiConfiguration.KeyMgmt.NONE
+                    || keyMgmt == WifiConfiguration.KeyMgmt.OWE) {
+                continue;
+            }
             WifiConfiguration config = new WifiConfiguration();
             config.allowedKeyManagement.clear();
             config.allowedKeyManagement.set(keyMgmt);
@@ -239,4 +248,30 @@
         config.setRandomizedMacAddress(null);
         assertEquals(defaultMac, config.getRandomizedMacAddress());
     }
+
+    /**
+     * Verifies that the serialization/de-serialization for softap config works.
+     */
+    @Test
+    public void testSoftApConfigBackupAndRestore() throws Exception {
+        WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "TestAP";
+        config.apBand = WifiConfiguration.AP_BAND_5GHZ;
+        config.apChannel = 40;
+        config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
+        config.preSharedKey = "TestPsk";
+        config.hiddenSSID = true;
+
+        byte[] data = config.getBytesForBackup();
+        ByteArrayInputStream bais = new ByteArrayInputStream(data);
+        DataInputStream in = new DataInputStream(bais);
+        WifiConfiguration restoredConfig = WifiConfiguration.getWifiConfigFromBackup(in);
+
+        assertEquals(config.SSID, restoredConfig.SSID);
+        assertEquals(config.preSharedKey, restoredConfig.preSharedKey);
+        assertEquals(config.getAuthType(), restoredConfig.getAuthType());
+        assertEquals(config.apBand, restoredConfig.apBand);
+        assertEquals(config.apChannel, restoredConfig.apChannel);
+        assertEquals(config.hiddenSSID, restoredConfig.hiddenSSID);
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
index f5a8b29..f9fb062 100644
--- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
@@ -44,6 +45,7 @@
         writeWifiInfo.txRetries = TEST_TX_RETRIES;
         writeWifiInfo.txBad = TEST_TX_BAD;
         writeWifiInfo.rxSuccess = TEST_RX_SUCCESS;
+        writeWifiInfo.setTrusted(true);
 
         Parcel parcel = Parcel.obtain();
         writeWifiInfo.writeToParcel(parcel, 0);
@@ -56,5 +58,6 @@
         assertEquals(TEST_TX_RETRIES, readWifiInfo.txRetries);
         assertEquals(TEST_TX_BAD, readWifiInfo.txBad);
         assertEquals(TEST_RX_SUCCESS, readWifiInfo.rxSuccess);
+        assertTrue(readWifiInfo.isTrusted());
     }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index e40b657a..8fe5af9 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -35,7 +35,20 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyList;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -43,6 +56,8 @@
 import android.net.wifi.WifiManager.LocalOnlyHotspotObserver;
 import android.net.wifi.WifiManager.LocalOnlyHotspotReservation;
 import android.net.wifi.WifiManager.LocalOnlyHotspotSubscription;
+import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
+import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
 import android.net.wifi.WifiManager.SoftApCallback;
 import android.net.wifi.WifiManager.TrafficStateCallback;
 import android.os.Handler;
@@ -59,6 +74,9 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Unit tests for {@link android.net.wifi.WifiManager}.
  */
@@ -67,16 +85,19 @@
 
     private static final int ERROR_NOT_SET = -1;
     private static final int ERROR_TEST_REASON = 5;
+    private static final int TEST_UID = 14553;
     private static final String TEST_PACKAGE_NAME = "TestPackage";
     private static final String TEST_COUNTRY_CODE = "US";
 
     @Mock Context mContext;
-    @Mock IWifiManager mWifiService;
+    @Mock
+    android.net.wifi.IWifiManager mWifiService;
     @Mock ApplicationInfo mApplicationInfo;
     @Mock WifiConfiguration mApConfig;
     @Mock IBinder mAppBinder;
     @Mock SoftApCallback mSoftApCallback;
     @Mock TrafficStateCallback mTrafficStateCallback;
+    @Mock NetworkRequestMatchCallback mNetworkRequestMatchCallback;
 
     private Handler mHandler;
     private TestLooper mLooper;
@@ -1163,4 +1184,127 @@
         assertEquals(1, altLooper.dispatchAll());
         verify(mTrafficStateCallback).onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
     }
+
+    /**
+     * Verify the call to registerNetworkRequestMatchCallback goes to WifiServiceImpl.
+     */
+    @Test
+    public void registerNetworkRequestMatchCallbackCallGoesToWifiServiceImpl()
+            throws Exception {
+        when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+        ArgumentCaptor<INetworkRequestMatchCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(INetworkRequestMatchCallback.Stub.class);
+        mWifiManager.registerNetworkRequestMatchCallback(mNetworkRequestMatchCallback, null);
+        verify(mWifiService).registerNetworkRequestMatchCallback(
+                any(IBinder.class), callbackCaptor.capture(), anyInt());
+
+        INetworkRequestUserSelectionCallback iUserSelectionCallback =
+                mock(INetworkRequestUserSelectionCallback.class);
+
+        assertEquals(0, mLooper.dispatchAll());
+
+        callbackCaptor.getValue().onAbort();
+        assertEquals(1, mLooper.dispatchAll());
+        verify(mNetworkRequestMatchCallback).onAbort();
+
+        callbackCaptor.getValue().onMatch(new ArrayList<ScanResult>());
+        assertEquals(1, mLooper.dispatchAll());
+        verify(mNetworkRequestMatchCallback).onMatch(anyList());
+
+        callbackCaptor.getValue().onUserSelectionConnectSuccess(new WifiConfiguration());
+        assertEquals(1, mLooper.dispatchAll());
+        verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(
+                any(WifiConfiguration.class));
+
+        callbackCaptor.getValue().onUserSelectionConnectFailure(new WifiConfiguration());
+        assertEquals(1, mLooper.dispatchAll());
+        verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(
+                any(WifiConfiguration.class));
+    }
+
+    /**
+     * Verify the call to unregisterNetworkRequestMatchCallback goes to WifiServiceImpl.
+     */
+    @Test
+    public void unregisterNetworkRequestMatchCallbackCallGoesToWifiServiceImpl() throws Exception {
+        ArgumentCaptor<Integer> callbackIdentifier = ArgumentCaptor.forClass(Integer.class);
+        mWifiManager.registerNetworkRequestMatchCallback(mNetworkRequestMatchCallback, mHandler);
+        verify(mWifiService).registerNetworkRequestMatchCallback(
+                any(IBinder.class), any(INetworkRequestMatchCallback.class),
+                callbackIdentifier.capture());
+
+        mWifiManager.unregisterNetworkRequestMatchCallback(mNetworkRequestMatchCallback);
+        verify(mWifiService).unregisterNetworkRequestMatchCallback(
+                eq((int) callbackIdentifier.getValue()));
+    }
+
+    /**
+     * Verify the call to NetworkRequestUserSelectionCallback goes to
+     * WifiServiceImpl.
+     */
+    @Test
+    public void networkRequestUserSelectionCallbackCallGoesToWifiServiceImpl()
+            throws Exception {
+        when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+        ArgumentCaptor<INetworkRequestMatchCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(INetworkRequestMatchCallback.Stub.class);
+        mWifiManager.registerNetworkRequestMatchCallback(mNetworkRequestMatchCallback, null);
+        verify(mWifiService).registerNetworkRequestMatchCallback(
+                any(IBinder.class), callbackCaptor.capture(), anyInt());
+
+        INetworkRequestUserSelectionCallback iUserSelectionCallback =
+                mock(INetworkRequestUserSelectionCallback.class);
+        ArgumentCaptor<NetworkRequestUserSelectionCallback> userSelectionCallbackCaptor =
+                ArgumentCaptor.forClass(NetworkRequestUserSelectionCallback.class);
+        callbackCaptor.getValue().onUserSelectionCallbackRegistration(
+                iUserSelectionCallback);
+        assertEquals(1, mLooper.dispatchAll());
+        verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration(
+                userSelectionCallbackCaptor.capture());
+
+        WifiConfiguration selected = new WifiConfiguration();
+        userSelectionCallbackCaptor.getValue().select(selected);
+        verify(iUserSelectionCallback).select(selected);
+
+        userSelectionCallbackCaptor.getValue().reject();
+        verify(iUserSelectionCallback).reject();
+    }
+
+    /**
+     * Check the call to getAllMatchingWifiConfigs calls getAllMatchingWifiConfigs of WifiService
+     * with the provided a list of ScanResult.
+     */
+    @Test
+    public void testGetAllMatchingWifiConfigs() throws Exception {
+        mWifiManager.getAllMatchingWifiConfigs(new ArrayList<>());
+
+        verify(mWifiService).getAllMatchingWifiConfigs(any(List.class));
+    }
+
+    /**
+     * Check the call to getMatchingOsuProviders calls getMatchingOsuProviders of WifiService
+     * with the provided a list of ScanResult.
+     */
+    @Test
+    public void testGetMatchingOsuProviders() throws Exception {
+        mWifiManager.getMatchingOsuProviders(new ArrayList<>());
+
+        verify(mWifiService).getMatchingOsuProviders(any(List.class));
+    }
+
+    /**
+     * Verify calls to {@link WifiManager#addNetworkSuggestions(List)} and
+     * {@link WifiManager#removeNetworkSuggestions(List)}.
+     */
+    @Test
+    public void addRemoveNetworkSuggestions() throws Exception {
+        when(mWifiService.addNetworkSuggestions(any(List.class), anyString())).thenReturn(true);
+        when(mWifiService.removeNetworkSuggestions(any(List.class), anyString())).thenReturn(true);
+
+        assertTrue(mWifiManager.addNetworkSuggestions(new ArrayList<>()));
+        verify(mWifiService).addNetworkSuggestions(anyList(), eq(TEST_PACKAGE_NAME));
+
+        assertTrue(mWifiManager.removeNetworkSuggestions(new ArrayList<>()));
+        verify(mWifiService).removeNetworkSuggestions(anyList(), eq(TEST_PACKAGE_NAME));
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
new file mode 100644
index 0000000..f8ab8a2
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.net.MacAddress;
+import android.net.MatchAllNetworkSpecifier;
+import android.net.NetworkRequest;
+import android.os.Parcel;
+import android.os.PatternMatcher;
+import android.support.test.filters.SmallTest;
+import android.util.Pair;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiNetworkAgentSpecifier}.
+ */
+@SmallTest
+public class WifiNetworkAgentSpecifierTest {
+    private static final int TEST_UID = 5;
+    private static final int TEST_UID_1 = 8;
+    private static final String TEST_SSID = "Test123";
+    private static final String TEST_SSID_PATTERN = "Test";
+    private static final String TEST_SSID_1 = "456test";
+    private static final String TEST_BSSID = "12:12:12:aa:0b:c0";
+    private static final String TEST_BSSID_OUI_BASE_ADDRESS = "12:12:12:00:00:00";
+    private static final String TEST_BSSID_OUI_MASK = "ff:ff:ff:00:00:00";
+    private static final String TEST_BSSID_1 = "aa:cc:12:aa:0b:c0";
+    private static final String TEST_PRESHARED_KEY = "\"Test123\"";
+
+    /**
+     * Validate that parcel marshalling/unmarshalling works
+     */
+    @Test
+    public void testWifiNetworkAgentSpecifierParcel() {
+        WifiNetworkAgentSpecifier specifier = createDefaultNetworkAgentSpecifier();
+
+        Parcel parcelW = Parcel.obtain();
+        specifier.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        WifiNetworkAgentSpecifier parcelSpecifier =
+                WifiNetworkAgentSpecifier.CREATOR.createFromParcel(parcelR);
+
+        assertEquals(specifier, parcelSpecifier);
+    }
+
+    /**
+     * Validate that the NetworkAgentSpecifier cannot be used in a {@link NetworkRequest} by apps.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkAgentSpecifierNotUsedInNetworkRequest() {
+        WifiNetworkAgentSpecifier specifier = createDefaultNetworkAgentSpecifier();
+
+        specifier.assertValidFromUid(TEST_UID);
+    }
+
+    /**
+     * Validate NetworkAgentSpecifier equals with itself.
+     * a) Create network agent specifier 1 for WPA_PSK network
+     * b) Create network agent specifier 2 with the same params as specifier 1.
+     * c) Ensure that the specifier 2 equals specifier 1.
+     */
+    @Test
+    public void testWifiNetworkAgentSpecifierEqualsSame() {
+        WifiNetworkAgentSpecifier specifier1 = createDefaultNetworkAgentSpecifier();
+        WifiNetworkAgentSpecifier specifier2 = createDefaultNetworkAgentSpecifier();
+
+        assertTrue(specifier2.equals(specifier1));
+    }
+
+    /**
+     * Validate NetworkAgentSpecifier equals between instances of {@link WifiNetworkAgentSpecifier}.
+     * a) Create network agent specifier 1 for WPA_PSK network
+     * b) Create network agent specifier 2 with different key mgmt params.
+     * c) Ensure that the specifier 2 does not equal specifier 1.
+     */
+    @Test
+    public void testWifiNetworkAgentSpecifierDoesNotEqualsWhenKeyMgmtDifferent() {
+        WifiConfiguration wifiConfiguration1 = createDefaultWifiConfiguration();
+        WifiNetworkAgentSpecifier specifier1 =
+                new WifiNetworkAgentSpecifier(
+                        wifiConfiguration1,
+                        TEST_UID);
+
+        WifiConfiguration wifiConfiguration2 = new WifiConfiguration(wifiConfiguration1);
+        wifiConfiguration2.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        WifiNetworkAgentSpecifier specifier2 =
+                new WifiNetworkAgentSpecifier(
+                        wifiConfiguration2,
+                        TEST_UID);
+
+        assertFalse(specifier2.equals(specifier1));
+    }
+
+    /**
+     * Validate NetworkAgentSpecifier equals between instances of {@link WifiNetworkAgentSpecifier}.
+     * a) Create network agent specifier 1 for WPA_PSK network
+     * b) Create network agent specifier 2 with different SSID.
+     * c) Ensure that the specifier 2 does not equal specifier 1.
+     */
+    @Test
+    public void testWifiNetworkAgentSpecifierDoesNotSatisifyWhenSsidDifferent() {
+        WifiConfiguration wifiConfiguration1 = createDefaultWifiConfiguration();
+        WifiNetworkAgentSpecifier specifier1 =
+                new WifiNetworkAgentSpecifier(
+                        wifiConfiguration1,
+                        TEST_UID);
+
+        WifiConfiguration wifiConfiguration2 = new WifiConfiguration(wifiConfiguration1);
+        wifiConfiguration2.SSID = TEST_SSID_1;
+        WifiNetworkAgentSpecifier specifier2 =
+                new WifiNetworkAgentSpecifier(
+                        wifiConfiguration2,
+                        TEST_UID);
+
+        assertFalse(specifier2.equals(specifier1));
+    }
+
+    /**
+     * Validate NetworkAgentSpecifier equals between instances of {@link WifiNetworkAgentSpecifier}.
+     * a) Create network agent specifier 1 for WPA_PSK network
+     * b) Create network agent specifier 2 with different BSSID.
+     * c) Ensure that the specifier 2 does not equal specifier 1.
+     */
+    @Test
+    public void testWifiNetworkAgentSpecifierDoesNotSatisifyWhenBssidDifferent() {
+        WifiConfiguration wifiConfiguration1 = createDefaultWifiConfiguration();
+        WifiNetworkAgentSpecifier specifier1 =
+                new WifiNetworkAgentSpecifier(
+                        wifiConfiguration1,
+                        TEST_UID);
+
+        WifiConfiguration wifiConfiguration2 = new WifiConfiguration(wifiConfiguration1);
+        wifiConfiguration2.BSSID = TEST_BSSID_1;
+        WifiNetworkAgentSpecifier specifier2 =
+                new WifiNetworkAgentSpecifier(
+                        wifiConfiguration2,
+                        TEST_UID);
+
+        assertFalse(specifier2.equals(specifier1));
+    }
+
+    /**
+     * Validate NetworkAgentSpecifier matching.
+     * a) Create a network agent specifier for WPA_PSK network
+     * b) Ensure that the specifier matches {@code null} and {@link MatchAllNetworkSpecifier}
+     * specifiers.
+     */
+    @Test
+    public void testWifiNetworkAgentSpecifierSatisifiesNullAndAllMatch() {
+        WifiNetworkAgentSpecifier specifier = createDefaultNetworkAgentSpecifier();
+
+        assertTrue(specifier.satisfiedBy(null));
+        assertTrue(specifier.satisfiedBy(new MatchAllNetworkSpecifier()));
+    }
+
+    /**
+     * Validate NetworkAgentSpecifier matching with itself.
+     * a) Create network agent specifier 1 for WPA_PSK network
+     * b) Create network agent specifier 2 with the same params as specifier 1.
+     * c) Ensure that the agent specifier is satisfied by itself.
+     */
+    @Test
+    public void testWifiNetworkAgentSpecifierDoesSatisifySame() {
+        WifiNetworkAgentSpecifier specifier1 = createDefaultNetworkAgentSpecifier();
+        WifiNetworkAgentSpecifier specifier2 = createDefaultNetworkAgentSpecifier();
+
+        assertTrue(specifier2.satisfiedBy(specifier1));
+    }
+
+    /**
+     * Validate {@link WifiNetworkAgentSpecifier} with {@link WifiNetworkSpecifier} matching.
+     * a) Create network agent specifier for WPA_PSK network
+     * b) Create network specifier with matching SSID pattern.
+     * c) Ensure that the agent specifier is satisfied by specifier.
+     */
+    @Test
+    public void
+            testWifiNetworkAgentSpecifierSatisfiesNetworkSpecifierWithSsidPattern() {
+        WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier = createDefaultNetworkAgentSpecifier();
+
+        PatternMatcher ssidPattern =
+                new PatternMatcher(TEST_SSID_PATTERN, PatternMatcher.PATTERN_PREFIX);
+        Pair<MacAddress, MacAddress> bssidPattern =
+                Pair.create(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS);
+        WifiConfiguration wificonfigurationNetworkSpecifier = new WifiConfiguration();
+        wificonfigurationNetworkSpecifier.allowedKeyManagement
+                .set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier(
+                ssidPattern,
+                bssidPattern,
+                wificonfigurationNetworkSpecifier,
+                TEST_UID);
+
+        assertTrue(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
+        assertTrue(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+    }
+
+    /**
+     * Validate {@link WifiNetworkAgentSpecifier} with {@link WifiNetworkSpecifier} matching.
+     * a) Create network agent specifier for WPA_PSK network
+     * b) Create network specifier with matching BSSID pattern.
+     * c) Ensure that the agent specifier is satisfied by specifier.
+     */
+    @Test
+    public void
+            testWifiNetworkAgentSpecifierSatisfiesNetworkSpecifierWithBssidPattern() {
+        WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier = createDefaultNetworkAgentSpecifier();
+
+        PatternMatcher ssidPattern =
+                new PatternMatcher(".*", PatternMatcher.PATTERN_SIMPLE_GLOB);
+        Pair<MacAddress, MacAddress> bssidPattern =
+                Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                        MacAddress.fromString(TEST_BSSID_OUI_MASK));
+        WifiConfiguration wificonfigurationNetworkSpecifier = new WifiConfiguration();
+        wificonfigurationNetworkSpecifier.allowedKeyManagement
+                .set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier(
+                ssidPattern,
+                bssidPattern,
+                wificonfigurationNetworkSpecifier,
+                TEST_UID);
+
+        assertTrue(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
+        assertTrue(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+    }
+
+    /**
+     * Validate {@link WifiNetworkAgentSpecifier} with {@link WifiNetworkSpecifier} matching.
+     * a) Create network agent specifier for WPA_PSK network
+     * b) Create network specifier with matching SSID & BSSID pattern.
+     * c) Ensure that the agent specifier is satisfied by specifier.
+     */
+    @Test
+    public void
+            testWifiNetworkAgentSpecifierSatisfiesNetworkSpecifierWithSsidAndBssidPattern() {
+        WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier = createDefaultNetworkAgentSpecifier();
+
+        PatternMatcher ssidPattern =
+                new PatternMatcher(TEST_SSID_PATTERN, PatternMatcher.PATTERN_PREFIX);
+        Pair<MacAddress, MacAddress> bssidPattern =
+                Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                        MacAddress.fromString(TEST_BSSID_OUI_MASK));
+        WifiConfiguration wificonfigurationNetworkSpecifier = new WifiConfiguration();
+        wificonfigurationNetworkSpecifier.allowedKeyManagement
+                .set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier(
+                ssidPattern,
+                bssidPattern,
+                wificonfigurationNetworkSpecifier,
+                TEST_UID);
+
+        assertTrue(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
+        assertTrue(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+    }
+
+    /**
+     * Validate {@link WifiNetworkAgentSpecifier} with {@link WifiNetworkSpecifier} matching.
+     * a) Create network agent specifier for WPA_PSK network
+     * b) Create network specifier with non-matching SSID pattern.
+     * c) Ensure that the agent specifier is not satisfied by specifier.
+     */
+    @Test
+    public void
+            testWifiNetworkAgentSpecifierDoesNotSatisfyNetworkSpecifierWithSsidPattern() {
+        WifiConfiguration wifiConfigurationNetworkAgent = createDefaultWifiConfiguration();
+        wifiConfigurationNetworkAgent.SSID = "\"" + TEST_SSID_1 + "\"";
+        WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier =
+                new WifiNetworkAgentSpecifier(
+                        wifiConfigurationNetworkAgent,
+                        TEST_UID);
+
+        PatternMatcher ssidPattern =
+                new PatternMatcher(TEST_SSID_PATTERN, PatternMatcher.PATTERN_PREFIX);
+        Pair<MacAddress, MacAddress> bssidPattern =
+                Pair.create(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS);
+        WifiConfiguration wificonfigurationNetworkSpecifier = new WifiConfiguration();
+        wificonfigurationNetworkSpecifier.allowedKeyManagement
+                .set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier(
+                ssidPattern,
+                bssidPattern,
+                wificonfigurationNetworkSpecifier,
+                TEST_UID);
+
+        assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
+        assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+    }
+
+    /**
+     * Validate {@link WifiNetworkAgentSpecifier} with {@link WifiNetworkSpecifier} matching.
+     * a) Create network agent specifier for WPA_PSK network
+     * b) Create network specifier with non-matching BSSID pattern.
+     * c) Ensure that the agent specifier is not satisfied by specifier.
+     */
+    @Test
+    public void
+            testWifiNetworkAgentSpecifierDoesNotSatisfyNetworkSpecifierWithBssidPattern() {
+        WifiConfiguration wifiConfigurationNetworkAgent = createDefaultWifiConfiguration();
+        wifiConfigurationNetworkAgent.BSSID = TEST_BSSID_1;
+        WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier =
+                new WifiNetworkAgentSpecifier(
+                        wifiConfigurationNetworkAgent,
+                        TEST_UID);
+
+        PatternMatcher ssidPattern =
+                new PatternMatcher(".*", PatternMatcher.PATTERN_SIMPLE_GLOB);
+        Pair<MacAddress, MacAddress> bssidPattern =
+                Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                        MacAddress.fromString(TEST_BSSID_OUI_MASK));
+        WifiConfiguration wificonfigurationNetworkSpecifier = new WifiConfiguration();
+        wificonfigurationNetworkSpecifier.allowedKeyManagement
+                .set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier(
+                ssidPattern,
+                bssidPattern,
+                wificonfigurationNetworkSpecifier,
+                TEST_UID);
+
+        assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
+        assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+    }
+
+    /**
+     * Validate {@link WifiNetworkAgentSpecifier} with {@link WifiNetworkSpecifier} matching.
+     * a) Create network agent specifier for WPA_PSK network
+     * b) Create network specifier with non-matching SSID and BSSID pattern.
+     * c) Ensure that the agent specifier is not satisfied by specifier.
+     */
+    @Test
+    public void
+            testWifiNetworkAgentSpecifierDoesNotSatisfyNetworkSpecifierWithSsidAndBssidPattern() {
+        WifiConfiguration wifiConfigurationNetworkAgent = createDefaultWifiConfiguration();
+        wifiConfigurationNetworkAgent.BSSID = TEST_BSSID_1;
+        WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier =
+                new WifiNetworkAgentSpecifier(
+                        wifiConfigurationNetworkAgent,
+                        TEST_UID);
+
+        PatternMatcher ssidPattern =
+                new PatternMatcher(TEST_SSID_PATTERN, PatternMatcher.PATTERN_PREFIX);
+        Pair<MacAddress, MacAddress> bssidPattern =
+                Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                        MacAddress.fromString(TEST_BSSID_OUI_MASK));
+        WifiConfiguration wificonfigurationNetworkSpecifier = new WifiConfiguration();
+        wificonfigurationNetworkSpecifier.allowedKeyManagement
+                .set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier(
+                ssidPattern,
+                bssidPattern,
+                wificonfigurationNetworkSpecifier,
+                TEST_UID);
+
+        assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
+        assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+    }
+
+    /**
+     * Validate {@link WifiNetworkAgentSpecifier} with {@link WifiNetworkSpecifier} matching.
+     * a) Create network agent specifier for WPA_PSK network
+     * b) Create network specifier with matching SSID and BSSID pattern, but different key mgmt.
+     * c) Ensure that the agent specifier is not satisfied by specifier.
+     */
+    @Test
+    public void
+            testWifiNetworkAgentSpecifierDoesNotSatisfyNetworkSpecifierWithDifferentKeyMgmt() {
+        WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier = createDefaultNetworkAgentSpecifier();
+
+        PatternMatcher ssidPattern =
+                new PatternMatcher(TEST_SSID_PATTERN, PatternMatcher.PATTERN_PREFIX);
+        Pair<MacAddress, MacAddress> bssidPattern =
+                Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                        MacAddress.fromString(TEST_BSSID_OUI_MASK));
+        WifiConfiguration wificonfigurationNetworkSpecifier = new WifiConfiguration();
+        wificonfigurationNetworkSpecifier.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier(
+                ssidPattern,
+                bssidPattern,
+                wificonfigurationNetworkSpecifier,
+                TEST_UID);
+
+        assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
+        assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+    }
+
+    /**
+     * Validate {@link WifiNetworkAgentSpecifier} with {@link WifiNetworkSpecifier} matching.
+     * a) Create network agent specifier for WPA_PSK network
+     * b) Create network specifier with matching SSID and BSSID pattern, but different UID.
+     * c) Ensure that the agent specifier is not satisfied by specifier.
+     */
+    @Test
+    public void
+            testWifiNetworkAgentSpecifierDoesNotSatisfyNetworkSpecifierWithDifferentUid() {
+        WifiNetworkAgentSpecifier wifiNetworkAgentSpecifier = createDefaultNetworkAgentSpecifier();
+
+        PatternMatcher ssidPattern =
+                new PatternMatcher(TEST_SSID_PATTERN, PatternMatcher.PATTERN_PREFIX);
+        Pair<MacAddress, MacAddress> bssidPattern =
+                Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                        MacAddress.fromString(TEST_BSSID_OUI_MASK));
+        WifiConfiguration wificonfigurationNetworkSpecifier = new WifiConfiguration();
+        wificonfigurationNetworkSpecifier.allowedKeyManagement
+                .set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        WifiNetworkSpecifier wifiNetworkSpecifier = new WifiNetworkSpecifier(
+                ssidPattern,
+                bssidPattern,
+                wificonfigurationNetworkSpecifier,
+                TEST_UID_1);
+
+        assertFalse(wifiNetworkSpecifier.satisfiedBy(wifiNetworkAgentSpecifier));
+        assertFalse(wifiNetworkAgentSpecifier.satisfiedBy(wifiNetworkSpecifier));
+    }
+
+    private WifiConfiguration createDefaultWifiConfiguration() {
+        WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.SSID = "\"" + TEST_SSID + "\"";
+        wifiConfiguration.BSSID = TEST_BSSID;
+        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        wifiConfiguration.preSharedKey = TEST_PRESHARED_KEY;
+        return wifiConfiguration;
+    }
+
+    private WifiNetworkAgentSpecifier createDefaultNetworkAgentSpecifier() {
+        return new WifiNetworkAgentSpecifier(createDefaultWifiConfiguration(), TEST_UID);
+    }
+
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java
new file mode 100644
index 0000000..8980ddb
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static android.os.PatternMatcher.PATTERN_LITERAL;
+import static android.os.PatternMatcher.PATTERN_PREFIX;
+import static android.os.PatternMatcher.PATTERN_SIMPLE_GLOB;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.net.MacAddress;
+import android.net.NetworkSpecifier;
+import android.os.PatternMatcher;
+import android.os.Process;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiNetworkConfigBuilder}.
+ */
+@SmallTest
+public class WifiNetworkConfigBuilderTest {
+    private static final String TEST_SSID = "Test123";
+    private static final String TEST_BSSID_OUI_BASE_ADDRESS = "12:12:12:00:00:00";
+    private static final String TEST_BSSID_OUI_MASK = "ff:ff:ff:00:00:00";
+    private static final String TEST_BSSID = "12:12:12:12:12:12";
+    private static final String TEST_PRESHARED_KEY = "Test123";
+
+    /**
+     * Validate correctness of WifiNetworkSpecifier object created by
+     * {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for open network with SSID pattern.
+     */
+    @Test
+    public void testWifiNetworkSpecifierBuilderForOpenNetworkWithSsidPattern() {
+        NetworkSpecifier specifier = new WifiNetworkConfigBuilder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_PREFIX))
+                .buildNetworkSpecifier();
+
+        assertTrue(specifier instanceof WifiNetworkSpecifier);
+        WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+        assertEquals(Process.myUid(), wifiNetworkSpecifier.requestorUid);
+        assertEquals(TEST_SSID, wifiNetworkSpecifier.ssidPatternMatcher.getPath());
+        assertEquals(PATTERN_PREFIX, wifiNetworkSpecifier.ssidPatternMatcher.getType());
+        assertEquals(MacAddress.ALL_ZEROS_ADDRESS, wifiNetworkSpecifier.bssidPatternMatcher.first);
+        assertEquals(MacAddress.ALL_ZEROS_ADDRESS, wifiNetworkSpecifier.bssidPatternMatcher.second);
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.NONE));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedProtocols
+                .get(WifiConfiguration.Protocol.RSN));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedAuthAlgorithms
+                .get(WifiConfiguration.AuthAlgorithm.OPEN));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedPairwiseCiphers
+                .get(WifiConfiguration.PairwiseCipher.CCMP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.CCMP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.TKIP));
+    }
+
+    /**
+     * Validate correctness of WifiNetworkSpecifier object created by
+     * {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for WPA_PSK network with BSSID
+     * pattern.
+     */
+    @Test
+    public void testWifiNetworkSpecifierBuilderForWpaPskNetworkWithBssidPattern() {
+        NetworkSpecifier specifier = new WifiNetworkConfigBuilder()
+                .setBssidPattern(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                        MacAddress.fromString(TEST_BSSID_OUI_MASK))
+                .setPskPassphrase(TEST_PRESHARED_KEY)
+                .buildNetworkSpecifier();
+
+        assertTrue(specifier instanceof WifiNetworkSpecifier);
+        WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+        assertEquals(".*", wifiNetworkSpecifier.ssidPatternMatcher.getPath());
+        assertEquals(PATTERN_SIMPLE_GLOB, wifiNetworkSpecifier.ssidPatternMatcher.getType());
+        assertEquals(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                wifiNetworkSpecifier.bssidPatternMatcher.first);
+        assertEquals(MacAddress.fromString(TEST_BSSID_OUI_MASK),
+                wifiNetworkSpecifier.bssidPatternMatcher.second);
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.WPA_PSK));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedProtocols
+                .get(WifiConfiguration.Protocol.RSN));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedAuthAlgorithms
+                .get(WifiConfiguration.AuthAlgorithm.OPEN));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedPairwiseCiphers
+                .get(WifiConfiguration.PairwiseCipher.CCMP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.CCMP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.TKIP));
+        assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
+                wifiNetworkSpecifier.wifiConfiguration.preSharedKey);
+    }
+
+    /**
+     * Validate correctness of WifiNetworkSpecifier object created by
+     * {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for WPA_EAP network with
+     * SSID and BSSID pattern.
+     */
+    @Test
+    public void testWifiNetworkSpecifierBuilderForEnterpriseHiddenNetworkWithSsidAndBssid() {
+        WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+        enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+        enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
+
+        NetworkSpecifier specifier = new WifiNetworkConfigBuilder()
+                .setSsid(TEST_SSID)
+                .setBssid(MacAddress.fromString(TEST_BSSID))
+                .setEnterpriseConfig(enterpriseConfig)
+                .setIsHiddenSsid()
+                .buildNetworkSpecifier();
+
+        assertTrue(specifier instanceof WifiNetworkSpecifier);
+        WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier;
+
+        assertEquals(TEST_SSID, wifiNetworkSpecifier.ssidPatternMatcher.getPath());
+        assertEquals(PATTERN_LITERAL, wifiNetworkSpecifier.ssidPatternMatcher.getType());
+        assertEquals(MacAddress.fromString(TEST_BSSID),
+                wifiNetworkSpecifier.bssidPatternMatcher.first);
+        assertEquals(MacAddress.BROADCAST_ADDRESS,
+                wifiNetworkSpecifier.bssidPatternMatcher.second);
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.WPA_EAP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.IEEE8021X));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedProtocols
+                .get(WifiConfiguration.Protocol.RSN));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedAuthAlgorithms
+                .get(WifiConfiguration.AuthAlgorithm.OPEN));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedPairwiseCiphers
+                .get(WifiConfiguration.PairwiseCipher.CCMP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.CCMP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers
+                .get(WifiConfiguration.GroupCipher.TKIP));
+        assertTrue(wifiNetworkSpecifier.wifiConfiguration.hiddenSSID);
+        assertEquals(enterpriseConfig.getEapMethod(),
+                wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig.getEapMethod());
+        assertEquals(enterpriseConfig.getPhase2Method(),
+                wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig.getPhase2Method());
+    }
+
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#setSsid(String)} throws an exception
+     * when the string is not Unicode.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testSetSsidWithNonUnicodeString() {
+        new WifiNetworkConfigBuilder()
+                .setSsid("\ud800")
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#setPskPassphrase(String)} throws an exception
+     * when the string is not ASCII encodable.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testSetPskPassphraseWithNonAsciiString() {
+        new WifiNetworkConfigBuilder()
+                .setSsid(TEST_SSID)
+                .setPskPassphrase("salvē")
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when neither SSID nor BSSID patterns were set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithNoSsidAndBssidPattern() {
+        new WifiNetworkConfigBuilder().buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when match-all SSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchAllSsidPattern1() {
+        new WifiNetworkConfigBuilder()
+                .setSsidPattern(new PatternMatcher(".*", PatternMatcher.PATTERN_SIMPLE_GLOB))
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when match-all SSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchAllSsidPattern2() {
+        new WifiNetworkConfigBuilder()
+                .setSsidPattern(new PatternMatcher(".*", PatternMatcher.PATTERN_ADVANCED_GLOB))
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when match-all SSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchAllSsidPattern3() {
+        new WifiNetworkConfigBuilder()
+                .setSsidPattern(new PatternMatcher("", PatternMatcher.PATTERN_PREFIX))
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when match-all BSSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchAllBssidPattern() {
+        new WifiNetworkConfigBuilder()
+                .setBssidPattern(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS)
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when match-none SSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchNoneSsidPattern() {
+        new WifiNetworkConfigBuilder()
+                .setSsidPattern(new PatternMatcher("", PatternMatcher.PATTERN_LITERAL))
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when match-none BSSID pattern is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern() {
+        new WifiNetworkConfigBuilder()
+                .setBssidPattern(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS)
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when SSID pattern is set for hidden network.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithBssidMatchPatternForHiddenNetwork() {
+        new WifiNetworkConfigBuilder()
+                .setBssidPattern(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                        MacAddress.fromString(TEST_BSSID_OUI_MASK))
+                .setIsHiddenSsid()
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when both {@link WifiNetworkConfigBuilder#setPskPassphrase(String)} and
+     * {@link WifiNetworkConfigBuilder#setEnterpriseConfig(WifiEnterpriseConfig)} are invoked.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithBothPskPassphraseAndEnterpriseConfig() {
+        new WifiNetworkConfigBuilder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
+                .setPskPassphrase(TEST_PRESHARED_KEY)
+                .setEnterpriseConfig(new WifiEnterpriseConfig())
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when SSID pattern is set for hidden network.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithSsidMatchPatternForHiddenNetwork() {
+        new WifiNetworkConfigBuilder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PatternMatcher.PATTERN_PREFIX))
+                .setIsHiddenSsid()
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when {@link WifiNetworkConfigBuilder#setIsAppInteractionRequired()} is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithRequiredAppInteraction() {
+        new WifiNetworkConfigBuilder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
+                .setIsAppInteractionRequired()
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when {@link WifiNetworkConfigBuilder#setIsUserInteractionRequired()} is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithRequiredUserInteraction() {
+        new WifiNetworkConfigBuilder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
+                .setIsUserInteractionRequired()
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when {@link WifiNetworkConfigBuilder#setPriority(int)} is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithSetPriority() {
+        new WifiNetworkConfigBuilder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
+                .setPriority(4)
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+     * when {@link WifiNetworkConfigBuilder#setIsMetered()} is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSpecifierBuilderWithMetered() {
+        new WifiNetworkConfigBuilder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_LITERAL))
+                .setIsMetered()
+                .buildNetworkSpecifier();
+    }
+
+    /**
+     * Validate correctness of WifiNetworkSuggestion object created by
+     * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} for Open network which requires
+     * app interaction.
+     */
+    @Test
+    public void testWifiNetworkSuggestionBuilderForOpenNetworkWithReqAppInteraction() {
+        WifiNetworkSuggestion suggestion = new WifiNetworkConfigBuilder()
+                .setSsid(TEST_SSID)
+                .setIsAppInteractionRequired()
+                .buildNetworkSuggestion();
+
+        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.NONE));
+        assertTrue(suggestion.isAppInteractionRequired);
+        assertFalse(suggestion.isUserInteractionRequired);
+        assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE,
+                suggestion.wifiConfiguration.meteredOverride);
+        assertEquals(-1, suggestion.wifiConfiguration.priority);
+    }
+
+    /**
+     * Validate correctness of WifiNetworkSuggestion object created by
+     * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} for WPA_EAP network which requires
+     * app interaction and has a priority of zero set.
+     */
+    @Test
+    public void testWifiNetworkSuggestionBuilderForWpaEapNetworkWithPriorityAndReqAppInteraction() {
+        WifiNetworkSuggestion suggestion = new WifiNetworkConfigBuilder()
+                .setSsid(TEST_SSID)
+                .setPskPassphrase(TEST_PRESHARED_KEY)
+                .setIsAppInteractionRequired()
+                .setPriority(0)
+                .buildNetworkSuggestion();
+
+        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.WPA_PSK));
+        assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
+                suggestion.wifiConfiguration.preSharedKey);
+        assertTrue(suggestion.isAppInteractionRequired);
+        assertFalse(suggestion.isUserInteractionRequired);
+        assertEquals(WifiConfiguration.METERED_OVERRIDE_NONE,
+                suggestion.wifiConfiguration.meteredOverride);
+        assertEquals(0, suggestion.wifiConfiguration.priority);
+    }
+
+    /**
+     * Validate correctness of WifiNetworkSuggestion object created by
+     * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} for WPA_PSK network which requires
+     * user interaction and is metered.
+     */
+    @Test
+    public void testWifiNetworkSuggestionBuilderForWpaPskNetworkWithMeteredAndReqUserInteraction() {
+        WifiNetworkSuggestion suggestion = new WifiNetworkConfigBuilder()
+                .setSsid(TEST_SSID)
+                .setPskPassphrase(TEST_PRESHARED_KEY)
+                .setIsUserInteractionRequired()
+                .setIsMetered()
+                .buildNetworkSuggestion();
+
+        assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+        assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+                .get(WifiConfiguration.KeyMgmt.WPA_PSK));
+        assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
+                suggestion.wifiConfiguration.preSharedKey);
+        assertFalse(suggestion.isAppInteractionRequired);
+        assertTrue(suggestion.isUserInteractionRequired);
+        assertEquals(WifiConfiguration.METERED_OVERRIDE_METERED,
+                suggestion.wifiConfiguration.meteredOverride);
+        assertEquals(-1, suggestion.wifiConfiguration.priority);
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
+     * when {@link WifiNetworkConfigBuilder#setSsidPattern(PatternMatcher)} is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithSsidPattern() {
+        new WifiNetworkConfigBuilder()
+                .setSsidPattern(new PatternMatcher(TEST_SSID, PATTERN_PREFIX))
+                .buildNetworkSuggestion();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
+     * when {@link WifiNetworkConfigBuilder#setBssid(MacAddress)} is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBssidPattern() {
+        new WifiNetworkConfigBuilder()
+                .setSsid(TEST_SSID)
+                .setBssidPattern(MacAddress.fromString(TEST_BSSID),
+                        MacAddress.fromString(TEST_BSSID))
+                .buildNetworkSuggestion();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
+     * when {@link WifiNetworkConfigBuilder#setBssidPattern(MacAddress, MacAddress)} is set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithBssid() {
+        new WifiNetworkConfigBuilder()
+                .setSsid(TEST_SSID)
+                .setBssid(MacAddress.fromString(TEST_BSSID))
+                .buildNetworkSuggestion();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
+     * when {@link WifiNetworkConfigBuilder#setSsid(String)} is not set.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkSuggestionBuilderWithNoSsid() {
+        new WifiNetworkConfigBuilder()
+                .buildNetworkSuggestion();
+    }
+
+    /**
+     * Ensure {@link WifiNetworkConfigBuilder#setPriority(int)} throws an exception
+     * when the value is negative.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testWifiNetworkSuggestionBuilderWithInvalidPriority() {
+        new WifiNetworkConfigBuilder()
+                .setSsid(TEST_SSID)
+                .setPriority(-1)
+                .buildNetworkSuggestion();
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
new file mode 100644
index 0000000..856f0c7
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static android.os.PatternMatcher.PATTERN_LITERAL;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.net.MacAddress;
+import android.net.MatchAllNetworkSpecifier;
+import android.os.Parcel;
+import android.os.PatternMatcher;
+import android.support.test.filters.SmallTest;
+import android.util.Pair;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiNetworkSpecifier}.
+ */
+@SmallTest
+public class WifiNetworkSpecifierTest {
+    private static final int TEST_UID = 5;
+    private static final String TEST_SSID = "Test123";
+    private static final String TEST_BSSID_OUI_BASE_ADDRESS = "12:12:12:00:00:00";
+    private static final String TEST_BSSID_OUI_MASK = "ff:ff:ff:00:00:00";
+    private static final String TEST_PRESHARED_KEY = "\"Test123\"";
+
+    /**
+     * Validate that parcel marshalling/unmarshalling works
+     */
+    @Test
+    public void testWifiNetworkSpecifierParcel() {
+        WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        wifiConfiguration.preSharedKey = TEST_PRESHARED_KEY;
+        WifiNetworkSpecifier specifier =
+                new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
+                        Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                                MacAddress.fromString(TEST_BSSID_OUI_MASK)),
+                        wifiConfiguration,
+                        TEST_UID);
+
+        Parcel parcelW = Parcel.obtain();
+        specifier.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        WifiNetworkSpecifier parcelSpecifier =
+                WifiNetworkSpecifier.CREATOR.createFromParcel(parcelR);
+
+        assertEquals(specifier, parcelSpecifier);
+    }
+
+    /**
+     * Validate NetworkSpecifier matching.
+     * a) Create a network specifier for WPA_PSK network
+     * b) Ensure that the specifier matches {@code null} and {@link MatchAllNetworkSpecifier}
+     * specifiers.
+     */
+    @Test
+    public void testWifiNetworkSpecifierSatisfiesNullAndAllMatch() {
+        WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        wifiConfiguration.preSharedKey = TEST_PRESHARED_KEY;
+        WifiNetworkSpecifier specifier =
+                new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
+                        Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                                MacAddress.fromString(TEST_BSSID_OUI_MASK)),
+                        wifiConfiguration,
+                        TEST_UID);
+
+        assertTrue(specifier.satisfiedBy(null));
+        assertTrue(specifier.satisfiedBy(new MatchAllNetworkSpecifier()));
+    }
+
+    /**
+     * Validate NetworkSpecifier matching.
+     * a) Create network specifier 1 for WPA_PSK network
+     * b) Create network specifier 2 with the same params as specifier 1.
+     * c) Ensure that the specifier 2 is satisfied by specifier 1.
+     */
+    @Test
+    public void testWifiNetworkSpecifierSatisfiesSame() {
+        WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        wifiConfiguration.preSharedKey = TEST_PRESHARED_KEY;
+
+        WifiNetworkSpecifier specifier1 =
+                new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
+                        Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                                MacAddress.fromString(TEST_BSSID_OUI_MASK)),
+                        wifiConfiguration,
+                        TEST_UID);
+
+        WifiNetworkSpecifier specifier2 =
+                new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
+                        Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                                MacAddress.fromString(TEST_BSSID_OUI_MASK)),
+                        wifiConfiguration,
+                        TEST_UID);
+
+        assertTrue(specifier2.satisfiedBy(specifier1));
+    }
+
+    /**
+     * Validate NetworkSpecifier matching.
+     * a) Create network specifier 1 for WPA_PSK network
+     * b) Create network specifier 2 with different key mgmt params.
+     * c) Ensure that the specifier 2 is not satisfied by specifier 1.
+     */
+    @Test
+    public void testWifiNetworkSpecifierDoesNotSatisfyWhenKeyMgmtDifferent() {
+        WifiConfiguration wifiConfiguration1 = new WifiConfiguration();
+        wifiConfiguration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        wifiConfiguration1.preSharedKey = TEST_PRESHARED_KEY;
+
+        WifiNetworkSpecifier specifier1 =
+                new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
+                        Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                                MacAddress.fromString(TEST_BSSID_OUI_MASK)),
+                        wifiConfiguration1,
+                        TEST_UID);
+
+        WifiConfiguration wifiConfiguration2 = new WifiConfiguration();
+        wifiConfiguration2.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        WifiNetworkSpecifier specifier2 =
+                new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
+                        Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                                MacAddress.fromString(TEST_BSSID_OUI_MASK)),
+                        wifiConfiguration2,
+                        TEST_UID);
+
+        assertFalse(specifier2.satisfiedBy(specifier1));
+    }
+
+    /**
+     * Validate NetworkSpecifier matching.
+     * a) Create network specifier 1 for WPA_PSK network
+     * b) Create network specifier 2 with different SSID pattern.
+     * c) Ensure that the specifier 2 is not satisfied by specifier 1.
+     */
+    @Test
+    public void testWifiNetworkSpecifierDoesNotSatisfyWhenSsidDifferent() {
+        WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        wifiConfiguration.preSharedKey = TEST_PRESHARED_KEY;
+
+        WifiNetworkSpecifier specifier1 =
+                new WifiNetworkSpecifier(new PatternMatcher("", PATTERN_LITERAL),
+                        Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                                MacAddress.fromString(TEST_BSSID_OUI_MASK)),
+                        wifiConfiguration,
+                        TEST_UID);
+
+        WifiNetworkSpecifier specifier2 =
+                new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
+                        Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                                MacAddress.fromString(TEST_BSSID_OUI_MASK)),
+                        wifiConfiguration,
+                        TEST_UID);
+
+        assertFalse(specifier2.satisfiedBy(specifier1));
+    }
+
+    /**
+     * Validate NetworkSpecifier matching.
+     * a) Create network specifier 1 for WPA_PSK network
+     * b) Create network specifier 2 with different BSSID pattern.
+     * c) Ensure that the specifier 2 is not satisfied by specifier 1.
+     */
+    @Test
+    public void testWifiNetworkSpecifierDoesNotSatisfyWhenBssidDifferent() {
+        WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        wifiConfiguration.preSharedKey = TEST_PRESHARED_KEY;
+
+        WifiNetworkSpecifier specifier1 =
+                new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
+                        Pair.create(MacAddress.fromString(TEST_BSSID_OUI_BASE_ADDRESS),
+                                MacAddress.fromString(TEST_BSSID_OUI_MASK)),
+                        wifiConfiguration,
+                        TEST_UID);
+
+        WifiNetworkSpecifier specifier2 =
+                new WifiNetworkSpecifier(new PatternMatcher(TEST_SSID, PATTERN_LITERAL),
+                        Pair.create(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS),
+                        wifiConfiguration,
+                        TEST_UID);
+
+        assertFalse(specifier2.satisfiedBy(specifier1));
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
new file mode 100644
index 0000000..6bab60d
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static org.junit.Assert.*;
+
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.WifiNetworkSuggestion}.
+ */
+@SmallTest
+public class WifiNetworkSuggestionTest {
+    private static final String TEST_SSID = "\"Test123\"";
+    private static final String TEST_SSID_1 = "\"Test1234\"";
+
+    /**
+     * Check that parcel marshalling/unmarshalling works
+     */
+    @Test
+    public void testWifiNetworkSuggestionParcel() {
+        WifiConfiguration configuration = new WifiConfiguration();
+        configuration.SSID = TEST_SSID;
+        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        WifiNetworkSuggestion suggestion =
+                new WifiNetworkSuggestion(configuration, false, true, 0);
+
+        Parcel parcelW = Parcel.obtain();
+        suggestion.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        WifiNetworkSuggestion parcelSuggestion =
+                WifiNetworkSuggestion.CREATOR.createFromParcel(parcelR);
+
+        // Two suggestion objects are considered equal if they point to the same network (i.e same
+        // SSID + keyMgmt + same UID). |isAppInteractionRequired| & |isUserInteractionRequired| are
+        // not considered for equality and hence needs to be checked for explicitly below.
+        assertEquals(suggestion, parcelSuggestion);
+        assertEquals(suggestion.isAppInteractionRequired,
+                parcelSuggestion.isAppInteractionRequired);
+        assertEquals(suggestion.isUserInteractionRequired,
+                parcelSuggestion.isUserInteractionRequired);
+    }
+
+    /**
+     * Check NetworkSuggestion equals returns {@code true} for 2 network suggestions with the same
+     * SSID, key mgmt and UID.
+     */
+    @Test
+    public void testWifiNetworkSuggestionEqualsSame() {
+        WifiConfiguration configuration = new WifiConfiguration();
+        configuration.SSID = TEST_SSID;
+        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        WifiNetworkSuggestion suggestion =
+                new WifiNetworkSuggestion(configuration, true, false, 0);
+
+        WifiConfiguration configuration1 = new WifiConfiguration();
+        configuration1.SSID = TEST_SSID;
+        configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        WifiNetworkSuggestion suggestion1 =
+                new WifiNetworkSuggestion(configuration1, false, true, 0);
+
+        assertEquals(suggestion, suggestion1);
+    }
+
+    /**
+     * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same
+     * key mgmt and UID, but different SSID.
+     */
+    @Test
+    public void testWifiNetworkSuggestionEqualsFailsWhenSsidIsDifferent() {
+        WifiConfiguration configuration = new WifiConfiguration();
+        configuration.SSID = TEST_SSID;
+        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        WifiNetworkSuggestion suggestion =
+                new WifiNetworkSuggestion(configuration, false, false, 0);
+
+        WifiConfiguration configuration1 = new WifiConfiguration();
+        configuration1.SSID = TEST_SSID_1;
+        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        WifiNetworkSuggestion suggestion1 =
+                new WifiNetworkSuggestion(configuration1, false, false, 0);
+
+        assertNotEquals(suggestion, suggestion1);
+    }
+
+    /**
+     * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same
+     * SSID and UID, but different key mgmt.
+     */
+    @Test
+    public void testWifiNetworkSuggestionEqualsFailsWhenKeyMgmtIsDifferent() {
+        WifiConfiguration configuration = new WifiConfiguration();
+        configuration.SSID = TEST_SSID;
+        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        WifiNetworkSuggestion suggestion =
+                new WifiNetworkSuggestion(configuration, false, false, 0);
+
+        WifiConfiguration configuration1 = new WifiConfiguration();
+        configuration1.SSID = TEST_SSID;
+        configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        WifiNetworkSuggestion suggestion1 =
+                new WifiNetworkSuggestion(configuration1, false, false, 0);
+
+        assertNotEquals(suggestion, suggestion1);
+    }
+
+    /**
+     * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same
+     * SSID and key mgmt, but different UID.
+     */
+    @Test
+    public void testWifiNetworkSuggestionEqualsFailsWhenUidIsDifferent() {
+        WifiConfiguration configuration = new WifiConfiguration();
+        configuration.SSID = TEST_SSID;
+        configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+        WifiNetworkSuggestion suggestion =
+                new WifiNetworkSuggestion(configuration, false, false, 0);
+
+        WifiNetworkSuggestion suggestion1 =
+                new WifiNetworkSuggestion(configuration, false, false, 1);
+
+        assertNotEquals(suggestion, suggestion1);
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 940adc8..775ce21 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -146,6 +146,7 @@
      */
     private static PasspointConfiguration createConfig() {
         PasspointConfiguration config = new PasspointConfiguration();
+        config.setUpdateIdentifier(1234);
         config.setHomeSp(createHomeSp());
         config.setCredential(createCredential());
         config.setPolicy(createPolicy());
@@ -273,18 +274,37 @@
     @Test
     public void validateDefaultConfig() throws Exception {
         PasspointConfiguration config = new PasspointConfiguration();
+
         assertFalse(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
-     * Verify that a configuration contained all fields is valid.
+     * Verify that a configuration containing all fields is valid for R1/R2.
      *
      * @throws Exception
      */
     @Test
     public void validateFullConfig() throws Exception {
         PasspointConfiguration config = createConfig();
+
         assertTrue(config.validate());
+        assertTrue(config.validateForR2());
+    }
+
+    /**
+     * Verify that a configuration containing all fields except for UpdateIdentifier is valid for
+     * R1, but invalid for R2.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateFullConfigWithoutUpdateIdentifier() throws Exception {
+        PasspointConfiguration config = createConfig();
+        config.setUpdateIdentifier(Integer.MIN_VALUE);
+
+        assertTrue(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
@@ -296,7 +316,9 @@
     public void validateConfigWithoutCredential() throws Exception {
         PasspointConfiguration config = createConfig();
         config.setCredential(null);
+
         assertFalse(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
@@ -308,12 +330,14 @@
     public void validateConfigWithoutHomeSp() throws Exception {
         PasspointConfiguration config = createConfig();
         config.setHomeSp(null);
+
         assertFalse(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
      * Verify that a configuration without Policy is valid, since Policy configurations
-     * are optional (applied for Hotspot 2.0 Release only).
+     * are optional for R1 and R2.
      *
      * @throws Exception
      */
@@ -321,12 +345,14 @@
     public void validateConfigWithoutPolicy() throws Exception {
         PasspointConfiguration config = createConfig();
         config.setPolicy(null);
+
         assertTrue(config.validate());
+        assertTrue(config.validateForR2());
     }
 
     /**
-     * Verify that a configuration without subscription update is valid, since subscription
-     * update configurations are optional (applied for Hotspot 2.0 Release only).
+     * Verify that a configuration without subscription update is valid for R1 and invalid for R2,
+     * since subscription update configuration is only applicable for R2.
      *
      * @throws Exception
      */
@@ -334,7 +360,9 @@
     public void validateConfigWithoutSubscriptionUpdate() throws Exception {
         PasspointConfiguration config = createConfig();
         config.setSubscriptionUpdate(null);
+
         assertTrue(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
@@ -352,12 +380,15 @@
         trustRootCertList.put(new String(rawUrlBytes, StandardCharsets.UTF_8),
                 new byte[CERTIFICATE_FINGERPRINT_BYTES]);
         config.setTrustRootCertList(trustRootCertList);
+
         assertFalse(config.validate());
 
         trustRootCertList = new HashMap<>();
         trustRootCertList.put(null, new byte[CERTIFICATE_FINGERPRINT_BYTES]);
         config.setTrustRootCertList(trustRootCertList);
+
         assertFalse(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
@@ -382,6 +413,7 @@
         trustRootCertList.put("test.cert.com", null);
         config.setTrustRootCertList(trustRootCertList);
         assertFalse(config.validate());
+        assertFalse(config.validateForR2());
     }
 
     /**
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index c5ad7de..c07db6c 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -24,14 +24,13 @@
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
 
+import org.junit.Test;
+
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
-import java.util.Arrays;
-
-import org.junit.Test;
 
 /**
  * Unit tests for {@link android.net.wifi.hotspot2.pps.CredentialTest}.
@@ -169,7 +168,12 @@
     @Test
     public void validateUserCredential() throws Exception {
         Credential cred = createCredentialWithUserCredential();
-        assertTrue(cred.validate());
+
+        // For R1 validation
+        assertTrue(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(false));
     }
 
     /**
@@ -181,7 +185,12 @@
     public void validateUserCredentialWithoutCaCert() throws Exception {
         Credential cred = createCredentialWithUserCredential();
         cred.setCaCertificate(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(false));
     }
 
     /**
@@ -193,7 +202,12 @@
     public void validateUserCredentialWithEapTls() throws Exception {
         Credential cred = createCredentialWithUserCredential();
         cred.getUserCredential().setEapType(EAPConstants.EAP_TLS);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
 
@@ -206,7 +220,12 @@
     public void validateUserCredentialWithoutRealm() throws Exception {
         Credential cred = createCredentialWithUserCredential();
         cred.setRealm(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -218,7 +237,12 @@
     public void validateUserCredentialWithoutUsername() throws Exception {
         Credential cred = createCredentialWithUserCredential();
         cred.getUserCredential().setUsername(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -230,7 +254,12 @@
     public void validateUserCredentialWithoutPassword() throws Exception {
         Credential cred = createCredentialWithUserCredential();
         cred.getUserCredential().setPassword(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -242,7 +271,12 @@
     public void validateUserCredentialWithoutAuthMethod() throws Exception {
         Credential cred = createCredentialWithUserCredential();
         cred.getUserCredential().setNonEapInnerMethod(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -255,7 +289,12 @@
     @Test
     public void validateCertCredential() throws Exception {
         Credential cred = createCredentialWithCertificateCredential();
-        assertTrue(cred.validate());
+
+        // For R1 validation
+        assertTrue(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(true));
     }
 
     /**
@@ -267,7 +306,12 @@
     public void validateCertCredentialWithoutCaCert() throws Exception {
         Credential cred = createCredentialWithCertificateCredential();
         cred.setCaCertificate(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(false));
     }
 
     /**
@@ -279,7 +323,12 @@
     public void validateCertCredentialWithoutClientCertChain() throws Exception {
         Credential cred = createCredentialWithCertificateCredential();
         cred.setClientCertificateChain(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -291,7 +340,12 @@
     public void validateCertCredentialWithoutClientPrivateKey() throws Exception {
         Credential cred = createCredentialWithCertificateCredential();
         cred.setClientPrivateKey(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -304,7 +358,12 @@
     public void validateCertCredentialWithMismatchFingerprint() throws Exception {
         Credential cred = createCredentialWithCertificateCredential();
         cred.getCertCredential().setCertSha256Fingerprint(new byte[32]);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -315,7 +374,12 @@
     @Test
     public void validateSimCredentialWithEapSim() throws Exception {
         Credential cred = createCredentialWithSimCredential();
-        assertTrue(cred.validate());
+
+        // For R1 validation
+        assertTrue(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(false));
     }
 
     /**
@@ -327,7 +391,12 @@
     public void validateSimCredentialWithEapAka() throws Exception {
         Credential cred = createCredentialWithSimCredential();
         cred.getSimCredential().setEapType(EAPConstants.EAP_AKA);
-        assertTrue(cred.validate());
+
+        // For R1 validation
+        assertTrue(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(false));
     }
 
     /**
@@ -339,7 +408,12 @@
     public void validateSimCredentialWithEapAkaPrime() throws Exception {
         Credential cred = createCredentialWithSimCredential();
         cred.getSimCredential().setEapType(EAPConstants.EAP_AKA_PRIME);
-        assertTrue(cred.validate());
+
+        // For R1 validation
+        assertTrue(cred.validate(true));
+
+        // For R2 validation
+        assertTrue(cred.validate(false));
     }
 
     /**
@@ -351,7 +425,12 @@
     public void validateSimCredentialWithoutIMSI() throws Exception {
         Credential cred = createCredentialWithSimCredential();
         cred.getSimCredential().setImsi(null);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -363,7 +442,12 @@
     public void validateSimCredentialWithInvalidIMSI() throws Exception {
         Credential cred = createCredentialWithSimCredential();
         cred.getSimCredential().setImsi("dummy");
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -375,7 +459,12 @@
     public void validateSimCredentialWithEapTls() throws Exception {
         Credential cred = createCredentialWithSimCredential();
         cred.getSimCredential().setEapType(EAPConstants.EAP_TLS);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**
@@ -391,7 +480,12 @@
         simCredential.setImsi("1234*");
         simCredential.setEapType(EAPConstants.EAP_SIM);
         cred.setSimCredential(simCredential);
-        assertFalse(cred.validate());
+
+        // For R1 validation
+        assertFalse(cred.validate(true));
+
+        // For R2 validation
+        assertFalse(cred.validate(false));
     }
 
     /**